§
    „Øj4  ã                  ó”   — d Z ddlmZ ddlmZ ddlmZ dZ G d„ d¦  «        Z	 	 dd	„Z	d
„ Z
edk    rddlZ ej        ¦   «          dS dS )z™
This module takes two XML files and displays the number of measures that
differ between the two before and after running the combined correction models
é    )Úannotations)Ú
correctors)Ú	converterFc                  ó†   — e Zd ZdZdd„Zed„ ¦   «         Zej        d„ ¦   «         Zd„ Zd„ Z	d„ Z
d	„ Zd
„ Zd„ Zd„ Zd„ Zd„ ZdS )ÚOmrGroundTruthPairzÝ
    Object for making comparisons between an OMR score and the GroundTruth

    Takes in a path to the OMR and a path to the groundTruth
    (or a pair of music21.stream.Score objects).

    See below for examples.

    Nc                óN  — d | _         d | _        t          |d¦  «        r|j        | _        || _        n|| _        d | _        |                      ¦   «         | _        t          |d¦  «        r|j        | _        || _	        n|| _        d | _	        |  
                    ¦   «         | _        d S )NÚfilePath)Ú_overriddenDebugÚnumberOfDifferencesÚhasattrr	   ÚomrPathÚomrM21ScoreÚgetOmrScoreÚomrScoreÚ
groundPathÚgroundM21ScoreÚgetGroundScoreÚgroundScore)ÚselfÚomrÚgrounds      ú‹/Users/tedpeters/Documents/Projects/Claude Projects/Misc Tools/notename-sheets/.venv/lib/python3.11/site-packages/music21/omr/evaluators.pyÚ__init__zOmrGroundTruthPair.__init__"   s©   € Ø $ˆÔØ#'ˆÔ Ý�3˜
Ñ#Ô#ð 	$Øœ<ˆDŒLØ"ˆDÔÐàˆDŒLØ#ˆDÔà×(Ò(Ñ*Ô*ˆŒå�6˜:Ñ&Ô&ð 	'Ø$œoˆDŒOØ"(ˆDÔÐà$ˆDŒOØ"&ˆDÔà×.Ò.Ñ0Ô0ˆÔÐÐó    c                ó,   — | j         €t          S | j         S )z_
        Returns either the debug value set for this
        evaluator, or globalDebug
        )r
   ÚglobalDebug©r   s    r   ÚdebugzOmrGroundTruthPair.debug7   s   € ð Ô Ð(ÝÐàÔ(Ð(r   c                ó   — || _         d S )N)r
   )r   ÚnewDebugs     r   r   zOmrGroundTruthPair.debugB   s   € à (ˆÔÐÐr   c                ój   — |                       ¦   «         | _        |                      ¦   «         | _        dS )z$
        Parse both scores.
        N)r   r   r   r   r   s    r   ÚparseAllzOmrGroundTruthPair.parseAllF   s1   € ð ×(Ò(Ñ*Ô*ˆŒØ×.Ò.Ñ0Ô0ˆÔÐÐr   c                ój   — | j                              ¦   «          | j                             ¦   «          dS )z3
        store the Hashes for both scores.
        N)r   ÚgetAllHashesr   r   s    r   ÚhashAllzOmrGroundTruthPair.hashAllM   s3   € ð 	Œ×"Ò"Ñ$Ô$Ð$ØÔ×%Ò%Ñ'Ô'Ð'Ð'Ð'r   c                óª   — | j         rt          d¦  «         | j        st          j        | j        ¦  «        | _        t          j        | j        ¦  «        S )a¦  
        Returns a ScoreCorrector object of the OMR score. does not store it anywhere

         >>> omrPath = omr.correctors.K525omrShortPath
         >>> ground = omr.correctors.K525groundTruthShortPath
         >>> omrGTP = omr.evaluators.OmrGroundTruthPair(omr=omrPath, ground=ground)
         >>> ssOMR = omrGTP.getOmrScore()
         >>> ssOMR
         <music21.omr.correctors.ScoreCorrector object at 0x...>
        zparsing OMR score)r   Úprintr   r   Úparser   r   ÚScoreCorrectorr   s    r   r   zOmrGroundTruthPair.getOmrScoreT   sP   € ð Œ:ð 	'ÝÐ%Ñ&Ô&Ð&àÔð 	=Ý(œ¨t¬|Ñ<Ô<ˆDÔåÔ(¨Ô)9Ñ:Ô:Ð:r   c                óª   — | j         rt          d¦  «         | j        st          j        | j        ¦  «        | _        t          j        | j        ¦  «        S )a”  
        Returns a ScoreCorrector object of the Ground truth score

         >>> omrPath = omr.correctors.K525omrShortPath
         >>> ground = omr.correctors.K525groundTruthShortPath
         >>> omrGTP = omr.evaluators.OmrGroundTruthPair(omr=omrPath, ground=ground)
         >>> ssGT = omrGTP.getGroundScore()
         >>> ssGT
         <music21.omr.correctors.ScoreCorrector object at 0x...>
        zparsing Ground Truth score)r   r'   r   r   r(   r   r   r)   r   s    r   r   z!OmrGroundTruthPair.getGroundScoreg   sQ   € ð Œ:ð 	0ÝÐ.Ñ/Ô/Ð/àÔ"ð 	CÝ"+¤/°$´/Ñ"BÔ"BˆDÔåÔ(¨Ô)<Ñ=Ô=Ð=r   c                ó   — ||k    rdS dS )z\
        define the substitution cost for x and y (2 if x and y are unequal else 0)
        r   é   © )r   ÚxÚys      r   Ú	substCostzOmrGroundTruthPair.substCostŒ   s   € ð �Š6ˆ6Ø�1à�1r   c                ó   — dS )z;
        define the insertion cost for x and y (1)
        é   r-   ©r   r.   s     r   Ú
insertCostzOmrGroundTruthPair.insertCost•   ó	   € ð ˆqr   c                ó   — dS )z:
        define the deletion cost for x and y (1)
        r2   r-   r3   s     r   Ú
deleteCostzOmrGroundTruthPair.deleteCost›   r5   r   c                ó  ‡— t          |¦  «        }t          |¦  «        Šˆfd„t          |dz   ¦  «        D ¦   «         }t          d|dz   ¦  «        D ];}||dz
           d         |                      ||dz
           ¦  «        z   ||         d<   Œ<t          d‰dz   ¦  «        D ];}|d         |dz
           |                      ||dz
           ¦  «        z   |d         |<   Œ<t          d|dz   ¦  «        D ]‘}t          d‰dz   ¦  «        D ]{}t	          ||dz
           |         dz   ||         |dz
           dz   ||dz
           |dz
           |                      ||dz
           ||dz
           ¦  «        z   ¦  «        ||         |<   Œ|Œ’||         ‰         S )zS
        Computes the min edit distance from target to source. Figure 3.25
        c                óH   •— g | ]}d „ t          ‰dz   ¦  «        D ¦   «         ‘ŒS )c                ó   — g | ]}d ‘ŒS )r   r-   )Ú.0Úis     r   ú
<listcomp>z=OmrGroundTruthPair.minEditDist.<locals>.<listcomp>.<listcomp>¨   s   € Ð-Ð-Ð-˜1�QÐ-Ð-Ð-r   r2   )Úrange)r;   ÚjÚms     €r   r=   z2OmrGroundTruthPair.minEditDist.<locals>.<listcomp>¨   s2   ø€ ÐDÐDÐD°!Ð-Ð-¥ a¨!¡e¡¤Ð-Ñ-Ô-ÐDÐDÐDr   r2   r   )Úlenr>   r4   r7   Úminr0   )r   ÚtargetÚsourceÚnÚdistancer<   r?   r@   s          @r   ÚminEditDistzOmrGroundTruthPair.minEditDist¡   s²  ø€ õ �‰KŒKˆÝ�‰KŒKˆàDÐDÐDÐDµu¸QÀ¹U±|´|ÐDÑDÔDˆå�q˜!˜a™%‘”ð 	Qð 	QˆAØ% a¨!¡eœ_¨QÔ/°$·/²/À&ÈÈQÉÄ-Ñ2PÔ2PÑPˆH�QŒK˜‰NˆNå�q˜!˜a™%‘”ð 	Qð 	QˆAØ% aœ[¨¨Q©Ô/°$·/²/À&ÈÈQÉÄ-Ñ2PÔ2PÑPˆH�QŒK˜‰NˆNå�q˜!˜a™%‘”ð 	Xð 	XˆAÝ˜1˜a !™e‘_”_ð Xð X�Ý!$ X¨a°!©e¤_°QÔ%7¸!Ñ%;Ø%-¨a¤[°°Q±Ô%7¸!Ñ%;Ø%-¨a°!©e¤_°Q¸±UÔ%;Ø*.¯.ª.¸ÀÀAÁ¼ÈÈqÐSTÉuÌÑ*VÔ*Vñ&Wñ"Xô "X�˜”˜A‘�ðXð
 ˜Œ{˜1Œ~Ðr   c                ó,  — d| _         | j                             ¦   «         }| j                             ¦   «         }t	          t          |¦  «        ¦  «        D ]8}||         }||         }|                      ||¦  «        }| xj         |z  c_         Œ9| j         S )aÂ  
        Returns the total edit distance as an Int between
        the two scores

        This function is based on James H. Martin's minimum edit distance.

        >>> omrPath = omr.correctors.K525omrShortPath
        >>> ground = omr.correctors.K525groundTruthShortPath
        >>> omrGTP = omr.evaluators.OmrGroundTruthPair(omr=omrPath, ground=ground)
        >>> differences = omrGTP.getDifferences()
        >>> differences
        32
        r   )r   r   r$   r   r>   rA   rG   )r   ÚomrListÚgtListÚpartNumÚomrPartÚgtPartÚmeasureErrorss          r   ÚgetDifferencesz!OmrGroundTruthPair.getDifferences¸   s˜   € ð $%ˆÔ Ø”-×,Ò,Ñ.Ô.ˆØÔ!×.Ò.Ñ0Ô0ˆÝ�S ™\œ\Ñ*Ô*ð 	6ð 	6ˆGØ˜gÔ&ˆGØ˜G”_ˆFØ ×,Ò,¨W°fÑ=Ô=ˆMØÐ$Ô$¨Ñ5Ð$Ô$Ð$ØÔ'Ð'r   )NN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Úpropertyr   Úsetterr"   r%   r   r   r0   r4   r7   rG   rO   r-   r   r   r   r      sò   € € € € € ðð ð1ð 1ð 1ð 1ð* ð)ð )ñ „Xð)ð „\ð)ð )ñ „\ð)ð1ð 1ð 1ð(ð (ð (ð;ð ;ð ;ð&>ð >ð >ðJð ð ðð ð ðð ð ðð ð ð.(ð (ð (ð (ð (r   r   Nc                óª  — |€t           }d}t          | |¬¦  «        }|rt          d¦  «         |€|                     ¦   «         }n|}|rt          d|¦  «         |j        }|}	|rt          d¦  «         g }
d}d}|du rh|	j        |         }|                     ¦   «         }|r0t          d	|¦  «         t          d
|	j        |         j        ¦  «         |                     ¦   «          n¢t          t          |	j        ¦  «        ¦  «        D ]€}|	j        |         }|                     ¦   «         }|t          |¦  «        z  }|                     ¦   «         }|
                     |¦  «         |t          |	j        |         j        ¦  «        z  }Œ�|rLt          d¦  «         t          d¦  «         t          d|
¦  «         t          d¦  «         t          d¦  «         |	                     ¦   «         }|rLt          d¦  «         t          d¦  «         t          d|¦  «         t          d¦  «         t          d¦  «         |	                     |
|¦  «        }|rt          d¦  «         t          |¦  «         |                     ¦   «         }|rIt          d|¦  «         t          d|¦  «         t          d|¦  «         |	j                             ¦   «          ||||dœ}|S )a  
    Get a dictionary showing the efficacy of the omr.correctors.ScoreCorrector on an OMR Score
    by comparing it to the GroundTruth.

    Set debug to True to see a lot of intermediary steps.

    >>> omrFilePath = omr.correctors.K525omrShortPath
    >>> groundTruthFilePath = omr.correctors.K525groundTruthShortPath
    >>> returnDict = omr.evaluators.evaluateCorrectingModel(omrFilePath, groundTruthFilePath)
    >>> for name in sorted(list(returnDict.keys())):
    ...     (name, returnDict[name])
    ('newEditDistance', 20)
    ('numberOfFlaggedMeasures', 13)
    ('originalEditDistance', 32)
    ('totalNumberOfMeasures', 84)
    Nr2   )r   r   zgetting differenceszOriginal edit distancez2Running Horizontal Model (Prior-based-on-distance)r   TzIncorrect measure indices:zHashed notes:z+for each entry in the array below, we have zt[flagged measure part, flagged measure index, source measure part, source measure index, source measure probability]zHORIZONTAL CORRECTING ARRAYz"**********************************z-Running Vertical Model (Prior-based-on-Parts)zVERTICAL CORRECTING MEASURESz]Finding best from Horizontal and Vertical and replacing flagged measures with source measuresz4done replacing flagged measures with source measuresznew edit distancez%number of flagged measures originallyztotal number of measures)ÚoriginalEditDistanceÚnewEditDistanceÚnumberOfFlaggedMeasuresÚtotalNumberOfMeasures)r   r   r'   rO   r   ÚsinglePartsÚgetIncorrectMeasureIndicesÚhashedNotesÚrunHorizontalCorrectionModelr>   rA   ÚappendÚrunVerticalCorrectionModelÚgenerateCorrectedScoreÚscoreÚshow)r   ÚgroundTruthPathr   ÚoriginalDifferencesÚ
runOnePartÚpnÚomrGTPr   Ú
myOmrScoreÚsÚcorrectingArrayHorAllPartÚnumberOfIncorrectMeasuresÚnumberOfTotalMeasuresÚ	scorePartÚincorrectMeasureIndicesÚtempPNÚcorrectingArrayHorOnePartÚcorrectingArrayVertAllPartÚ
priorScoreÚnewNumberOfDifferencesÚ
returnDicts                        r   ÚevaluateCorrectingModelrv   Ñ   sY  € ð& €}Ýˆà	
€Bõ   G°OÐDÑDÔD€FØð %ÝÐ#Ñ$Ô$Ð$ØÐ"Ø$×3Ò3Ñ5Ô5ÐÐà1ÐØð =ÝÐ&Ð(;Ñ<Ô<Ð<à”€JØ€AØð DÝÐBÑCÔCÐCà "ÐØ !ÐØÐà�TÐÐØ”M "Ô%ˆ	Ø"+×"FÒ"FÑ"HÔ"HÐØð 	BÝÐ.Ð0GÑHÔHÐHÝ�/ 1¤=°Ô#4Ô#@ÑAÔAÐAØ×.Ò.Ñ0Ô0Ð0Ð0å�C ¤Ñ.Ô.Ñ/Ô/ð 	Lð 	LˆFØœ fÔ-ˆIØ&/×&JÒ&JÑ&LÔ&LÐ#Ø%­Ð-DÑ)EÔ)EÑEÐ%Ø(1×(NÒ(NÑ(PÔ(PÐ%Ø%×,Ò,Ð-FÑGÔGÐGØ!¥S¨¬°vÔ)>Ô)JÑ%KÔ%KÑKÐ!Ð!àð ?ÝÐ;Ñ<Ô<Ð<Ýð Dñ 	Eô 	Eð 	EåÐ+Ð-FÑGÔGÐGÝÐ2Ñ3Ô3Ð3åÐ=Ñ>Ô>Ð>à!"×!=Ò!=Ñ!?Ô!?Ðàð 1ÝÐ;Ñ<Ô<Ð<Ýð Eñ 	Fô 	Fð 	FåÐ,Ð.HÑIÔIÐIÝÐ2Ñ3Ô3Ð3åð 0ñ 	1ô 	1ð 	1à×)Ò)Ð*CÐE_Ñ`Ô`€Jàð ÝÐDÑEÔEÐEÝˆjÑÔÐà#×2Ò2Ñ4Ô4Ðàð ÝÐ!Ð#9Ñ:Ô:Ð:ÝÐ5Ð7PÑQÔQÐQÝÐ(Ð*?Ñ@Ô@Ð@Ø	Œ�Š‰Œˆà*=Ø%;Ø-FØ+@ðBð B€Jð
 Ðr   c                óò  — t          j        | ¦  «        }|                     ¦   «         }d}d}|j        }t	          |¦  «        D ]±\  }}||                              ¦   «         }t	          |¦  «        D ]‚\  }	}
|	|v rŒ
|dz  }d}t	          |¦  «        D ]\  }}|	|k    rŒ|
|k    rd} nŒ|du r>t          t          |¦  «        ¦  «        D ]!}||k    rŒ	||         |	         }||
k    rd} nŒ"|du r|dz  }ŒƒŒ²||fS )aª  
    Essentially it's the ratio of amount of rhythmic similarity within a piece, which
    gives an upper bound on what the omr.corrector.prior measure should be able to
    achieve for the flagged measures. If a piece has low rhythmic similarity in general, then
    there's no way for a correct match to be found within the unflagged measures in the piece.

    Returns a tuple of the total number of NON-flagged measures and the total number
    of those measures that have a rhythmic match.

    Takes in a stream.Score.

    >>> c = converter.parse(omr.correctors.K525omrShortPath)  # first 21 measures
    >>> totalUnflagged, totalUnflaggedWithMatches = omr.evaluators.autoCorrelationBestMeasure(c)
    >>> (totalUnflagged, totalUnflaggedWithMatches)
    (71, 64)
    >>> print( float(totalUnflaggedWithMatches) / totalUnflagged )
    0.901...

    Schoenberg has low autoCorrelation.

    >>> c = corpus.parse('schoenberg/opus19/movement6')
    >>> totalUnflagged, totalUnflaggedWithMatches = omr.evaluators.autoCorrelationBestMeasure(c)
    >>> (totalUnflagged, totalUnflaggedWithMatches)
    (18, 6)
    >>> print( float(totalUnflaggedWithMatches) / totalUnflagged )
    0.333...

    r   r2   FT)r   r)   r$   r[   Ú	enumerater\   r>   rA   )Ú
inputScoreÚssÚ	allHashesÚtotalMeasuresÚtotalMatchesr[   ÚpNumÚ
pHashArrayÚincorrectIndicesr<   ÚmHashÚmatchr?   ÚnHashÚ	otherPNumÚ	otherHashs                   r   ÚautoCorrelationBestMeasurer†   7  sj  € õ: 
Ô	" :Ñ	.Ô	.€BØ—’Ñ!Ô!€Ià€MØ€Là”.€Kå% iÑ0Ô0ð "ð "ÑˆˆjØ& tÔ,×GÒGÑIÔIÐÝ! *Ñ-Ô-ð 	"ð 	"‰HˆAˆuØÐ$Ð$Ð$Øà˜QÑˆMØˆEõ & jÑ1Ô1ð ð ‘��5Ø˜’6�6ØØ˜E’>�>Ø �EØ�Eð "ð
 ˜ˆ~ˆ~Ý!&¥s¨;Ñ'7Ô'7Ñ!8Ô!8ð ð �IØ  DÒ(Ð(Ø Ø )¨)Ô 4°QÔ 7�IØ  EÒ)Ð)Ø $˜Ø˜ð *ð ˜ˆ}ˆ}Ø Ñ!�øð5	"ð6 ˜<Ð(Ð(r   Ú__main__)NNF)rS   Ú
__future__r   Úmusic21.omrr   Úmusic21r   r   r   rv   r†   rP   ÚmainTestr-   r   r   ú<module>rŒ      sç   ððð ð #Ð "Ð "Ð "Ð "Ð "à "Ð "Ð "Ð "Ð "Ð "Ø Ð Ð Ð Ð Ð à€ðw(ð w(ð w(ð w(ð w(ñ w(ô w(ð w(ðt =AØAFðcð cð cð cðLB)ð B)ð B)ðJ ˆzÒÐØ€N€N€NØ€GÔÑÔÐÐÐð Ðr   