
    rh×                    t   S SK J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   " S S5      r " S S\5      r " S S\5      r " S S\5      rSS jr " S S\5      r " S S\5      r " S S\R,                  5      r\S:X  a  S SKr\R2                  " \5        gg)    )annotations)deepcopyN)duration)expressions)interval)note)pitch)stream)aligner)ornamentRecognizerc                  *    \ rS rSrSrS rS rS rSrg)OMRMidiFixer   z}
Base class for future fixers
changes is a list of changes associated with the midiStream and omrStream,
not a list of lists
c                (    Xl         X l        X0l        g Nchanges
midiStream	omrStream)selfr   r   r   s       V/home/james-whalen/.local/lib/python3.13/site-packages/music21/alpha/analysis/fixer.py__init__OMRMidiFixer.__init__    s    $"    c                    g r    )r   s    r   fixOMRMidiFixer.fix%   s    r   c                    [        U[        R                  5      (       a   [        U[        R                  5      (       a  gg)NTF)
isinstancer   Noter   midiRefomrRefs      r   checkIfNoteInstance OMRMidiFixer.checkIfNoteInstance(   s)    gtyy))j.K.Kr   r   N)	__name__
__module____qualname____firstlineno____doc__r   r   r%   __static_attributes__r   r   r   r   r      s    
#
r   r   c                  ,   ^  \ rS rSrSrU 4S jrSrU =r$ )DeleteFixer-   a  
The DeleteFixer was designed to fit the specifications of the OpenScore project.
The goal of the OpenScore project is to open-source music with open source software
(like music21!). OpenScore will use a combination of computer and human power
to digitize classical music scores and put them in the public domain. One idea is
that software can identify wrong recognized notes in a scanned score and mark or
delete the entire measure that that note is in and pass it off to a human corrector to
re-transcribe the entire measure. The DeleteFixer could be the computer power in
this method of score correction that OpenScore is using.

CAUTION: this does really weird things still.
c                l  > [         TU ]  5         U R                   H  u  pnU R                  X5      SL a  M  [	        U[
        R                  5      (       a   U[
        R                  R                  :X  a  M[  UR                  [        R                  5      nU R                  R                  U5        M     g )NF)superr   r   r%   r    r   	ChangeOpsNoChangegetContextByClassr
   Measurer   remove)r   r#   r$   opm	__class__s        r   r   DeleteFixer.fix:   s    %)\\!Wb''8EA "g//00R7;L;L;U;U5U((8ANN!!!$ &2r   r   )r'   r(   r)   r*   r+   r   r,   __classcell__r9   s   @r   r.   r.   -   s    % %r   r.   c                  Z   ^  \ rS rSrSrU 4S jrS rS rS rS r	S r
S	 rSS
 jrSrU =r$ )EnharmonicFixerG   aA  
Fixes incorrectly spelled enharmonics
initialized with self.changes -- a list of tuples in this form:
(MIDIReference, OMRReference, op)
MIDIReference and OMRReference are actual note/rest/chord object in some stream
op is a ChangeOp that relates the two references

TEST 1, no changes in OMR stream

>>> omrStream1 = stream.Stream()
>>> midiStream1 = stream.Stream()

>>> omrNote1 = note.Note('A#4')
>>> omrNote2 = note.Note('A#4')
>>> midiNote1 = note.Note('B-4')
>>> midiNote2 = note.Note('B-4')

>>> omrStream1.append([omrNote1, omrNote2])
>>> midiStream1.append([midiNote1, midiNote2])
>>> subOp = alpha.analysis.aligner.ChangeOps.Substitution

>>> ct1 = (midiNote1, omrNote1, subOp)
>>> ct2 = (midiNote2, omrNote2, subOp)
>>> changes1 = [ct1, ct2]

>>> fixer1 = alpha.analysis.fixer.EnharmonicFixer(changes1, None, None)
>>> fixer1.fix()
>>> omrStream1[0]
<music21.note.Note A#>
>>> omrStream1[1]
<music21.note.Note A#>


TEST 2, no changes in OMR stream

>>> omrStream2 = stream.Stream()
>>> midiStream2 = stream.Stream()

>>> omr2Note1 = note.Note('A#4')
>>> omr2Note2 = note.Note('A#4')
>>> midi2Note1 = note.Note('A#4')
>>> midi2Note2 = note.Note('A#4')

>>> omrStream2.append([omr2Note1, omr2Note2])
>>> midiStream2.append([midi2Note1, midi2Note2])
>>> ncOp = alpha.analysis.aligner.ChangeOps.NoChange

>>> ct2_1 = (midi2Note1, omr2Note1, ncOp)
>>> ct2_2 = (midi2Note2, omr2Note2, ncOp)
>>> changes2 = [ct2_1, ct2_2]

>>> fixer2 = alpha.analysis.fixer.EnharmonicFixer(changes2, None, None)
>>> fixer2.fix()
>>> omrStream2[0]
<music21.note.Note A#>
>>> omrStream1[1]
<music21.note.Note A#>


TEST 3 (case 1)

>>> midiNote3 = note.Note('A4')
>>> omrNote3 = note.Note('An4')

>>> subOp = alpha.analysis.aligner.ChangeOps.Substitution

>>> ct3 = (midiNote3, omrNote3, subOp)
>>> changes3 = [ct3]
>>> omrNote3.pitch.accidental
<music21.pitch.Accidental natural>
>>> fixer3 = alpha.analysis.fixer.EnharmonicFixer(changes3, None, None)
>>> fixer3.fix()
>>> omrNote3.pitch.accidental


TEST 4 (case 2-1) e.g MIDI = g#, ground truth = a-, OMR = an

>>> midiNote4 = note.Note('G#4')
>>> omrNote4 = note.Note('An4')

>>> subOp = alpha.analysis.aligner.ChangeOps.Substitution

>>> ct4 = (midiNote4, omrNote4, subOp)
>>> changes4 = [ct4]
>>> omrNote4.pitch.accidental
<music21.pitch.Accidental natural>
>>> fixer4 = alpha.analysis.fixer.EnharmonicFixer(changes4, None, None)
>>> fixer4.fix()
>>> omrNote4.pitch.accidental
<music21.pitch.Accidental flat>


TEST 5 (case 2-2) e.g midi = g-, gt = f#, omr = fn

>>> midiNote5 = note.Note('G-4')
>>> omrNote5 = note.Note('Fn4')

>>> subOp = alpha.analysis.aligner.ChangeOps.Substitution

>>> ct5 = (midiNote5, omrNote5, subOp)
>>> changes5 = [ct5]
>>> omrNote5.pitch.accidental
<music21.pitch.Accidental natural>
>>> fixer5 = alpha.analysis.fixer.EnharmonicFixer(changes5, None, None)
>>> fixer5.fix()
>>> omrNote5.pitch.accidental
<music21.pitch.Accidental sharp>


TEST 6.1 (case 3) e.g. midi = g#, gt = g#, omr = gn or omr = g-

>>> midiNote6_1 = note.Note('G#4')
>>> midiNote6_2 = note.Note('G#4')
>>> omrNote6_1 = note.Note('Gn4')
>>> omrNote6_2 = note.Note('G-4')

>>> subOp6_1 = alpha.analysis.aligner.ChangeOps.Substitution
>>> subOp6_2 = alpha.analysis.aligner.ChangeOps.Substitution
>>> ct6_1 = (midiNote6_1, omrNote6_1, subOp6_1)
>>> ct6_2 = (midiNote6_2, omrNote6_2, subOp6_2)
>>> changes6 = [ct6_1, ct6_2]

>>> omrNote6_1.pitch.accidental
<music21.pitch.Accidental natural>
>>> omrNote6_2.pitch.accidental
<music21.pitch.Accidental flat>
>>> fixer6 = alpha.analysis.fixer.EnharmonicFixer(changes6, None, None)
>>> fixer6.fix()
>>> omrNote6_1.pitch.accidental
<music21.pitch.Accidental sharp>
>>> omrNote6_2.pitch.accidental
<music21.pitch.Accidental sharp>


TEST 7 (case 4-1, 4-2) notes are on different step, off by an interval of 2:
* 4-1: e.g. midi = g#, gt = a-, omr = a#
* 4-2: e.g. midi = a-, gt = g#, omr = g-

>>> midiNote7_1 = note.Note('G#4')
>>> omrNote7_1 = note.Note('A#4')

>>> midiNote7_2 = note.Note('A-4')
>>> omrNote7_2 = note.Note('G-4')

>>> subOp7_1 = alpha.analysis.aligner.ChangeOps.Substitution
>>> subOp7_2 = alpha.analysis.aligner.ChangeOps.Substitution
>>> ct7_1 = (midiNote7_1, omrNote7_1, subOp7_1)
>>> ct7_2 = (midiNote7_2, omrNote7_2, subOp7_2)
>>> changes7 = [ct7_1, ct7_2]

>>> omrNote7_1.pitch.accidental
<music21.pitch.Accidental sharp>
>>> omrNote7_2.pitch.accidental
<music21.pitch.Accidental flat>
>>> fixer7 = alpha.analysis.fixer.EnharmonicFixer(changes7, None, None)
>>> fixer7.fix()

>>> omrNote7_1.pitch.step
'A'
>>> omrNote7_1.pitch.accidental
<music21.pitch.Accidental flat>

>>> omrNote7_2.pitch.step
'G'
>>> omrNote7_2.pitch.accidental
<music21.pitch.Accidental sharp>
c                D	  > [         TU ]  5         U R                   GH  u  pnSUR                  l        U R                  X5      SL a  M.  [        U[        R                  5      (       a   U[        R                  R                  :X  a  Mm  U R                  XSS9(       a  M  U R                  U5      (       GaP  U R                  X5      (       a  SUR                  l        M  UR                  UR                  :  ax  UR                  R                  [         R"                  " S5      5      R                  UR                  5      (       a(  [        R$                  " S5      UR                  l        GMS  GMV  UR                  UR                  :  ax  UR                  R                  [         R"                  " S5      5      R                  UR                  5      (       a(  [        R$                  " S	5      UR                  l        GM  GM  GM  U R'                  U5      (       ah  U R)                  X5      (       aR  U R+                  U5      (       a(  UR                  R                  UR                  l        GMU  SUR                  l        GMi  U R'                  U5      (       Ga  U R-                  X5      (       Ga  UR                  UR                  :  a  UR                  R                  [        R$                  " S	5      :X  ax  UR                  R                  [         R"                  " S
5      5      R                  UR                  5      (       a(  [        R$                  " S5      UR                  l        GMT  GMW  GMZ  UR                  UR                  :  a  UR                  R                  [        R$                  " S5      :X  ax  UR                  R                  [         R"                  " S5      5      R                  UR                  5      (       a(  [        R$                  " S	5      UR                  l        GM  GM  GM  GM   UR                  UR                  :w  d  GM=  U R'                  U5      (       d  GMV  U R)                  X5      (       d  GMo  UR                  Ul        GM     g)zK
Fixes the enharmonic errors in the OMR by changing the pitch of the note.
blackF   )setIntNflat   sharp   )r1   r   r   stylecolorr%   r    r   r2   r3   intervalTooBig	hasNatAccisEnharmonicr	   
accidental	transposer   Interval
AccidentalhasSharpFlatAccstepEqhasAcc	stepNotEq)r   r#   r$   r7   r9   s       r   r   EnharmonicFixer.fix   s9    	%)\\!Wb!(FLL''8EA "g//00R7;L;L;U;U5U ""71"=~~f%%$$W55.2FLL+ ||gmm3!<<11(2C2CB2G 44@L4OP6;6F6Fv6NFLL3P  5!<<11(2C2CA2F 44@L4OP6;6F6Fw6OFLL3P 6 %%f--$++g2N2N;;v&&.5mm.F.FFLL+.2FLL+%%f--$..2Q2Q <<'--/||..%2B2B72KK!<<11(2C2CB2G 44@L4OP6;6F6Fv6NFLL3P L \\GMM1||..%2B2B62JJ!<<11(2C2CA2F 44@L4OP6;6F6Fw6OFLL3P K 2 ,,'--/,,W55G44&}}C &2r   c                L    UR                   R                  UR                   5      $ )zJ
Returns True if the omrRef is enharmonic to the midiRef, False otherwise
)r	   rN   r"   s      r   rN   EnharmonicFixer.isEnharmonic8  s     }}))&,,77r   c                2    UR                   R                  SL$ )z?
Returns True if the omrRef has an accidental, False otherwise
N)r	   rO   r   r$   s     r   rU   EnharmonicFixer.hasAcc>  s     ||&&d22r   c                x    U R                  U5      =(       a#    UR                  R                  R                  S:H  $ )zF
Returns True if the omrRef has a natural accidental, False otherwise
naturalrU   r	   rO   namer[   s     r   rM   EnharmonicFixer.hasNatAccD  -     {{6"Pv||'>'>'C'Cy'PPr   c                x    U R                  U5      =(       a#    UR                  R                  R                  S:g  $ )zL
Returns True if the omrRef has a sharp or flat accidental, False otherwise
r^   r_   r[   s     r   rS   EnharmonicFixer.hasSharpFlatAccJ  rb   r   c                4    UR                   UR                   :H  $ )z6
Returns True if the steps are equal, False otherwise
stepr"   s      r   rT   EnharmonicFixer.stepEqP       ||v{{**r   c                4    UR                   UR                   :g  $ )z:
Returns True if the steps are not equal, False otherwise
rf   r"   s      r   rV   EnharmonicFixer.stepNotEqV  ri   r   c                N    [         R                  " X5      R                  U:  a  gg)z
Returns True if the intervalClass between the two notes is greater than setInt.

Note that intervalClass and not actual interval size is used.
TF)r   notesToChromaticintervalClass)r   r#   r$   rC   s       r   rL   EnharmonicFixer.intervalTooBig\  s#     $$W5CCfLr   r   )rB   )r'   r(   r)   r*   r+   r   rN   rU   rM   rS   rT   rV   rL   r,   r;   r<   s   @r   r>   r>   G   s;    fNF-R83QQ++ r   r>   c                  j   ^  \ rS rSrSrSU 4S jjrSS jrSS.     SS jjrSSS	.SS
 jjrSr	U =r
$ )OrnamentFixerif  a  
Fixes missed ornaments in OMR using expanded ornaments in MIDI
initialized with self.changes -- a list of tuples in this form:
(MIDIReference, OMRReference, op)
MIDIReference and OMRReference are actual note/rest/chord object in some stream
op is a ChangeOp that relates the two references

recognizers can be a single recognizer or list of recognizers,
but self.recognizers is always a list.
recognizers take in stream of busy notes and optional stream of simple note(s)
and return False or an instance of the ornament recognized
c                z   > [         TU ]  XU5        [        U[        5      (       d	  U/U l        OX@l        XPl        g r   )r1   r   r    listrecognizersmarkChangeColor)r   r   r   r   rt   ru   r9   s         r   r   OrnamentFixer.__init__s  s5    i8+t,, +}D*.r   c                ^    U R                    H  nUR                  XS9nU(       d  M  Us  $    g)a  
Finds an ornament in busyNotes based from simpleNote
using provided recognizers.

:param busyNotes: stream of notes
:param simpleNotes: stream of notes

Tries the recognizers in order, returning the result of the first
one to successfully recognize an ornament.
)simpleNotesN)rt   	recognize)r   	busyNotesrx   rornaments        r   findOrnamentOrnamentFixer.findOrnament{  s3     !!A{{9{FHx " r   Fshowc                   [        S UR                   5       5      (       d>  UR                  R                  U5        U(       a  U R                  UR                  l        gg)aO  
Adds the ornament to the selectedNote when selectedNote has no ornaments already.

* selectedNote: Note.note to add ornament to
* ornament: Expressions.ornament to add to note
* show: True when note should be colored blue

Returns True if added successfully, or False if there was already an
ornament on the note and it wasn't added.
c              3  V   #    U  H  n[        U[        R                  5      v   M!     g 7fr   )r    r   Ornament).0es     r   	<genexpr>,OrnamentFixer.addOrnament.<locals>.<genexpr>  s"     Y@X1:a!5!566@Xs   ')TF)anyr   appendru   rJ   rK   )r   selectedNoter|   r   s       r   addOrnamentOrnamentFixer.addOrnament  sL     Y@X@XYYY$$++H5+/+?+?""(r   T)r   inPlacec               `   U R                   nSn/ n/ nU(       dZ  [        U R                  5      n[        U R                  5      n[        R
                  " XxS9nUR                  5         UR                   nU H  u  pnU[        R                  R                  L d  U[        R                  R                  L a  MB  X;   a  MI  [        XR                  5      nSnU H  nX;   d  M
  Sn  O   U(       a  M{  U R                  U[        U
5      /5      nU(       d  M  Xl-  nUR                  U
5        U R                  XUS9  M     U(       a4  U R                  R                  5         U R                  R                  5         U(       d.  Ub+  [!        UR                   UR"                  UR$                  5      $ g)z
Corrects missed ornaments in omrStream according to midiStream
:param show: Whether to show results
:param inPlace: Whether to make changes to own omr stream or
return a new OrnamentFixer with changes
NsourceStreamtargetStreamFTr   )r   r   r   r   r   StreamAligneralignr2   r3   DeletiongetNotesWithinDurationr   r}   r   r   r   
TrillFixerr   r   )r   r   r   r   saomrNotesLabeledOrnament midiNotesAlreadyFixedForOrnamentomrStreamCopymidiStreamCopymidiNoteRef
omrNoteRefchangerz   busyNoteAlreadyUsedbusyNoteornamentFounds                   r   r   OrnamentFixer.fix  sq    ,,)-"$+-($T^^4M%doo6N&&M_BHHJjjG/6+KV**333vARARA[A[7[ 4.{<O<OPI"'%?*.' & # !--i(::N9OPM }0=0'..z:   F1 074 NN!OO  "2>bjj"//2??KKr   )ru   rt   )blue)returnzexpressions.Ornament | None)r   z	note.Noter|   zexpressions.Ornamentr   bool)r   zOMRMidiFixer | None)r'   r(   r)   r*   r+   r   r}   r   r   r,   r;   r<   s   @r   rq   rq   f  sG    /* 	"+2 $(	,   5 5r   rq   c                <   U(       a  X l         [        R                  " 5       nU R                  R                  UR                  :  a  U$ UR                  U R                  R                  -
  nU R                  SSS9nUR                  [        U 5      5        U(       a  XER                  R                  :  af  UnUR                  SSS9nXFR                  R                  -  nUR                  [        U5      5        U(       a  XER                  R                  :  a  Mf  U$ )a{  
Returns maximal stream of deepcopies of notes, rests, and chords following
(and including) startingNote which occupy no more than totalDuration combined.

* startingGeneralNote is a GeneralNote (could be a note, rest, or chord)
* totalDuration is a duration
* referenceStream is optionally a stream which the startingGeneralNote's
    active site should be set to when provided
GeneralNoteT)activeSiteOnly)
activeSiter
   Streamr   quarterLengthnextr   r   )startingGeneralNotetotalDurationreferenceStreamnotesdurationQlLeftnextGeneralNotecurrentGeneralNotes          r   r   r     s     )8&MMOE ##11M4O4OO"003F3O3O3]3]]N)..}T.RO	LL-./
n0H0H0V0VV,,11-PT1U55CCCX012 n0H0H0V0VV Lr   c                  ,   ^  \ rS rSrSrU 4S jrSrU =r$ )r   i  a!  
Fixes missed trills in OMR using expanded ornaments in MIDI.
initialized with self.changes -- a list of tuples in this form:
(MIDIReference, OMRReference, op)
MIDIReference and OMRReference are actual note/rest/chord object in some stream
op is a ChangeOp that relates the two references
c                   > [         R                  " 5       n[         R                  " 5       nSUl        XE/n[        TU ]  XX65        g )NT)r   TrillRecognizercheckNachschlagr1   r   )r   r   r   r   defaultOrnamentRecognizernachschlagOrnamentRecognizerrt   r9   s          r   r   TrillFixer.__init__  sA    $6$F$F$H!'9'I'I'K$7;$40OiEr   r   r'   r(   r)   r*   r+   r   r,   r;   r<   s   @r   r   r     s    F Fr   r   c                  ,   ^  \ rS rSrSrU 4S jrSrU =r$ )	TurnFixeri  a/  
Fixes missed turns/inverted turns in OMR using expanded ornaments in MIDI.
initialized with self.changes -- a list of tuples in this form:
(MIDIReference, OMRReference, op)
MIDIReference and OMRReference are actual note/rest/chord object in some stream
op is a ChangeOp that relates the two references
c                P   > [         R                  " 5       n[        TU ]  XX45        g r   )r   TurnRecognizerr1   r   )r   r   r   r   
recognizerr9   s        r   r   TurnFixer.__init__  s     '668
iDr   r   r   r<   s   @r   r   r     s    E Er   r   c                  8    \ 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   [        U5      [        U5      :w  a  SnSU4$ [        [        U5      5       H}  n[        X   R                  5      [        X$   R                  5      :w  a*  SU SX   R                   SX$   R                   S3nSU4s  $ X   X$   :w  d  Mi  SU SX    SX$    S3nSU4s  $    g	)
z
Returns a tuple of (bool, reason) where the first element is
whether the measures are equal and the second (`reason`) is a string
explaining why they are unequal.

Reason is an empty string if the measures are equal.
znot equal lengthFzExpressions z
 unequal (z != )z	Elements z are unequal ()T )lenranger   )r   m1m2msgis        r   measuresEqualTest.measuresEqual  s     r7c"g$C#:s2wA25$$%RU->->)??$QCz"%2C2C1DDIZIZH[[\]cz!u~!!N25'beWAFcz!   r   c                   US   nUS   nUS   nUS   n[         R                  " X4S9nUR                  5         [        U5      nSn	U R	                  U R                  XR                  5      S   U	5        U" UR                  UR                  UR                  5      n
Sn	U R	                  U R                  XR                  5      S   U	5        U
R                  S	S
9nSn	U R                  XR                  5      u  pU R	                  XU	-   U-   5        Sn	U R                  XR                  5      u  pU R	                  XU	-   U-   5        Sn	U R                  UR                  U5      u  pU R	                  XU	-   U-   5        U
R                  SS
9nU R                  X5        Sn	U R                  XZR                  5      u  pU R	                  XU	-   U-   5        Sn	U R                  XS5      u  pU R	                  XU	-   U-   5        g)z
testCase is a dictionary with the following keys

returnDict = {
    'name': string,
    'midi': measure stream,
    'omr': measure stream,
    'expected': fixed measure stream,
}

testFixer is an OMRMidiFixer
omrmidiexpectedr`   r   z5Expect no changes from creating and aligning aligner.r   z&Expect no changes from creating fixer.F)r   zB. Expect no changes to aligner source stream, but unequal because z=. Expect no changes to fixer omr stream, but unequal because z8. Appropriate changes in new fixer, but unequal because Tz<. Expect changes in fixer's omr stream, but unequal because z=. Expect changes in original omr stream, but unequal because N)r   r   r   r   
assertTruer   r   r   r   r   r   assertIsNone)r   testCase	testFixerr   r   expectedOmrtestingNamer   omrCopyassertionCheckfixernotInPlaceResultisEqualreasonfixerInPlaceResults                  r   checkFixerHelperTest.checkFixerHelper-  s    uoz*v& ""G

3-P**7OODQGX "**boorGA**7OODQGX !99U93],,WooF~!=!FGX,,WooF~!=!FGS,,-=-G-GU~!=!FG #YYtY4,:W,,[//J~!=!FGX,,[>~!=!FGr   c                   [         R                  " S5      n[        R                  " S5      Ul        [        R
                  " 5       nUR                  U5        [        U[        R                  " S5      5      nU R                  U[        R
                  5        U R                  U/[        UR                  5      S5        [        U[        R                  " S5      5      nU R                  U/[        UR                  5      S5        [        U[        R                  " S5      5      nU R                  / [        UR                  5      S5        [        R                  " 5       n[         R                  " S5      n[        R                  " S5      Ul        [         R                  " S	5      n[        R                  " S5      Ul        UR                  XU/5        [        U[        R                  " S5      5      nU R                  U/[        UR                  5      S5        [        U[        R                  " S5      5      nU R                  XU/[        UR                  5      S
5        [        U[        R                  " S5      5      nU R                  XU/[        UR                  5      S5        [        U[        R                  " S5      5      nU R                  X/[        UR                  5      S5        [        U[        R                  " S5      5      nU R                  X/[        UR                  5      S5        [        U[        R                  " S5      US9nU R                  U/[        UR                  5      S5        [        R                  " 5       nSUl        [         R                  " 5       n[        R                  " S5      Ul        UR                  X/5        [        U[        R                  " S5      5      nSn	U R                  X/[        UR                  5      U	5        [        U[        R                  " S5      US9nU R                  XU/[        UR                  5      S5        g )NCquarterz$starting note occupies full durationhalfz'starting note occupies partial durationeighthzstarting note too longDEzall notes fill up full durationwholez"all notes fill up partial durationg      ?z some notes fill up full durationg      ?z#some notes fill up partial duration)r   z(partial fill up from reference stream m1m3z#note and rest fill up full durationz fill up from reference stream m2)r   r!   r   Durationr
   r   r   r   assertIsInstanceassertListEqualrs   r   r5   idRestnotesAndRests)
r   n1r   resultr   n2n3r   r1r   s
             r   testGetNotesWithinDurationTest.testGetNotesWithinDurationf  s>   YYs^''	2]]_
		"'H,=,=i,HIffmm4bT4#57]^'H,=,=f,EFbT4#57`a'H,=,=h,GHRfll!35MN^^YYs^''1YYs^''1
		22,'H,=,=i,HIbT4#57]^'H,=,=f,EFbb\4+=?`a'H,=,=g,FGbb\4+=?cd'H,=,=c,BCbXtFLL'9;]^'H,=,=d,CDbXtFLL'9;`a (H,=,=f,EWYZbT4#57ab^^YY[''	2
		2('H,=,=f,EF3bXtF,@,@'A3G (H,=,=f,EWYZbb\4+=?abr   c                    S nS nS nS nS nU" 5       U" 5       U" 5       U" 5       U" 5       /nU H  nU R                  U[        5        M     g )Nc            
     <   [         R                  " S5      n [         R                  " S5      n[        R                  " S5      nXl         [        R                  " S5      nXl         [        R                  " S5      nXl         X4[	        U5      [	        U5      /n[         R                  " S5      n[        R                  " S5      nXl         [        R                  " S5      nXhl         [        R                  " S5      n	Xil         X[	        U	5      [	        U5      [	        U	5      [	        U5      [	        U	5      [	        U5      /n
[
        R                  " 5       nUR                  U5        UR                  U
5        [
        R                  " 5       nUR                  X'/5        [
        R                  " 5       n[	        U5      n[        R                  " 5       n[        R                  " S5      Ul        UR                  Ul        UR                  R                  U5        [	        U5      n[        R                  " 5       n[        R                  " S	5      Ul        UR                  Ul        UR                  R                  U5        UR                  UU/5        S
UUUS.nU$ )
Returns a dictionary with the following keys

returnDict = {
    'name': string,
    'midi': measure stream,
    'omr': measure stream,
    'expected': measure stream,
}
r         ?GAg      ?B3r   zm-2M2zDouble Trill Measurer`   r   r   r   )r   r   r   r!   r   r
   r5   r   r   Trillr   rQ   sizer   )noteDurationtrill1NoteDurationn0r   r   trill1trill2NoteDurationr   n4n5trill2midiMeasure
omrMeasureexpectedFixedOmrMeasuren0WithTrilln0Trilln1WithTrilln1Trill
returnDicts                      r   createDoubleTrillMeasure5Test.testTrillFixer.<locals>.createDoubleTrillMeasure  s    $,,Y7L "*!2!23!73B&K3B,K3B,KhrlHRL9F "*!2!25!94B&K4B,K3B,KhrlHRLrlHRL(2,NF !..*Kv&v&)Jrh'&,nn&6#"2,K!'')G#,,U3GL$6$D$DG!##**73"2,K!'')G#,,T2GL$6$D$DG!##**73#**K+EF /#!3	J r   c                    [         R                  " S5      n [        R                  " S5      nXl         [        R                  " S5      n[         R                  " S5      Ul         [        R                  " S5      n[         R                  " S5      Ul         X#[	        U5      [	        U5      /n[
        R                  " 5       nUR                  U5        [
        R                  " 5       nUR                  U5        SUU[	        U5      S.nU$ )r   r   r   r  r  z*Non-Trill Measure Wrong Oscillate Intervalr  r   r   r   r!   r   r
   r5   r   r	  r  r   r   nonTrillr  r  r  s           r   createWrongTrillMeasure4Test.testTrillFixer.<locals>.createWrongTrillMeasure  s     $,,Y7L3B&K3B"++C0BK3B"++C0BKhrl;H ..*Kx()Jb! E#!$Z0	J r   c                    [         R                  " S5      n [        R                  " S5      nXl         [        R                  " S5      n[         R                  " S5      Ul         [        R                  " S5      n[         R                  " S5      Ul         X#[	        U5      [	        U5      /n[
        R                  " 5       nUR                  U5        [
        R                  " 5       nUR                  U5        SUU[	        U5      S.nU$ )r   r   r  r   r  r   zNon-Trill Measure Wrong Notesr  r  r  s           r   createNonTrillMeasure2Test.testTrillFixer.<locals>.createNonTrillMeasure  s     $,,Y7L3B&K3B"++C0BK3B"++C0BKhrl;H ..*Kx()Jb! 8#!$Z0	J r   c                 `   [         R                  " S5      n [         R                  " S5      n[        R                  " S5      nXl         [        R                  " S5      nXl         [        R                  " S5      nXl         [        R                  " S5      nXl         X4[	        U5      [	        U5      /n[	        U5      [	        U5      [	        U5      U/nXg-   n[
        R                  " 5       n	U	R                  U5        [
        R                  " 5       n
U
R                  U5        [        R                  " 5       nSUl
        UR                  Ul        [
        R                  " 5       n[	        U5      nUR                  R                  [	        U5      5        UR                  U5        SU	U
US.nU$ )	r   r         ?r   Fr   TzNachschlag Trillr  )r   r   r   r!   r   r
   r5   r   r   r  
nachschlagr   )r	  trillDurationr  tn1tn2tn3firstHalfTrillsecondHalfTrillexpandedTrillr  r  nachschlagTrillr  noteWithTrillr  s                  r   createNachschlagTrillMeasure9Test.testTrillFixer.<locals>.createNachschlagTrillMeasure#  sT    $,,Y7L$--d3M3B&K))C.C(L))C.C(L))C.C(L!x}EN'}hsmXc]CPO*<M ..*K}-)Jb!)//1O)-O&,9,G,GO)&,nn&6#$RLM%%,,Xo-FG#**=9 +#!3	J r   c                 n   [         R                  " S5      n [         R                  " S5      n[        R                  " S5      nXl         [        R
                  " 5       nUR                  Ul        UR                  R                  U5        [        R                  " S5      nXl         [        R                  " S5      nXl         XE[        U5      [        U5      /n[        R                  " 5       nUR                  U5        [        R                  " 5       nUR                  U5        SUU[        U5      S.n	U	$ )r   r   r%  r&  r  zOMR with Trill Notationr  )r   r   r   r!   r   r  r   r   r   r
   r5   )
r	  r(  r0  trillr)  r*  r.  r  r  r  s
             r   createMeasureWithTrillAlready:Test.testTrillFixer.<locals>.createMeasureWithTrillAlreadyT  s     $,,Y7L$--d3M IIcNM%1"%%'E"/"="=E%%,,U3))C.C(L))C.C(L x}hsmDM ..*K}-)Jm, 2#!$Z0	J r   )r   r   )r   r  r  r"  r1  r5  testConditionsr   s           r   testTrillFixerTest.testTrillFixer  sc    <	|!	F"	H/	b%	P %&#%!#(*)+
 'H!!(J7 'r   c                |    S nS nS nU" 5       U" 5       U" 5       /nU H  nU R                  U[        5        M     g )Nc                 x   [         R                  " 5       n [        R                  " S5      n[        R
                  " S5      Ul        U R                  U5        [         R                  " 5       n[        U5      nUR                  R                  [        R                  " 5       5        UR                  U5        [         R                  " 5       n[        R                  " S5      [        R                  " S5      [        R                  " S5      [        R                  " S5      /nUR                  U5        SUU US.nU$ )r   r&  r   r  r   zSingle Turn Measurer  )r
   r5   r   r!   r   r   r   r   r   r   Turn)r  omrNoter  expectedOmrNoter  turnr  s          r   createSingleTurnMeasure3Test.testTurnFixer.<locals>.createSingleTurnMeasure  s      )JiinG'009Gg&&,mmo#&w/O''..{/?/?/AB#**?; ..*KIIcNDIIcNDIIcNDIIcNSDt$ .#!3	J r   c                    [         R                  " 5       n [        R                  " S5      n[        R                  " S5      n[        R                  " S5      nU R	                  XU/5        [         R
                  " 5       n[        U5      nUR                  R	                  [        R                  " 5       5        [        U5      nUR                  R	                  [        R                  " 5       5        UR	                  U[        U5      U/5        [         R                  " 5       n[        R                  " S5      [        R                  " S5      [        R                  " S5      [        R                  " S5      /n[        R                  " S5      [        R                  " S5      [        R                  " S5      [        R                  " S5      /n	U H  n
[        R                  " S5      U
l	        M      U	 H  n
[        R                  " S5      U
l	        M      UR	                  / UQ[        U5      PU	Q5        S	UU US
.nU$ )r   zB-r  r  C5zG#zA#Br  z>Inverted turns with accidentals separated By non-ornament Noter  )r
   r5   r   r!   r   r   r   r   InvertedTurnr   r   )r  omrNote1
middleNoteomrNote2r  expectOmrNote1expectOmrNote2r  turn1turn2nr  s               r   createDoubleInvertedTurnMeasure;Test.testTurnFixer.<locals>.createDoubleInvertedTurnMeasure  s     )JyyH3JyyHxX>? '-mmo#%h/N&&--k.F.F.HI%h/N&&--k.F.F.HI#**NHZ<PR`+ab ..*KYYs^TYYt_diiotyyQUWEYYt_diiotyy~tyyQUWE%..s3
 %..s3
 EE(<EuEF Y#!3	J r   c                    [         R                  " 5       n [        R                  " S5      n[        R
                  " S5      Ul        U R                  U5        [         R                  " 5       n[        R                  " S5      [        R                  " S5      [        R                  " S5      [        R                  " S5      /nUR                  U5        SUU [        U 5      S.nU$ )r   r  r   rD  r  r&  zNon-Turn Measurer  )r
   r5   r   r!   r   r   r   r   )r  r=  r  r?  r  s        r   createNonTurnMeasure0Test.testTurnFixer.<locals>.createNonTurnMeasure  s      )JiinG'009Gg& ..*KIIcNDIIcNDIIcNDIIcNSDt$ +#!$Z0	J r   )r   r   )r   r@  rN  rQ  r7  r   s         r   testTurnFixerTest.testTurnFixer  sJ    	B(	T	8 239;.02 'H!!(I6 'r   r   N)r'   r(   r)   r*   r   r   r   r   r8  rS  r,   r   r   r   r   r     s'    %(7Hr5cng8Rm7r   r   __main__r   )
__future__r   copyr   unittestmusic21r   r   r   r   r	   r
   music21.alpha.analysisr   r   r   r.   r>   rq   r   r   r   TestCaser   r'   mainTestr   r   r   <module>r]     s    #         * 5 &%, %4]l ]~qL qf@F F
E 
E_78 _7D zT r   