o
    si                     @   s   d Z ddlZddlmZ i dddddddd	d
dddddddddddddddddddddddddd diZd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Z	dS )+a  
Key Detection involves determining the underlying key (distribution of notes
and note transitions) in a piece of music.  Key detection algorithms are
evaluated by comparing their estimated key to a ground-truth reference key and
reporting a score according to the relationship of the keys.

Conventions
-----------
Keys are represented as strings of the form ``'(key) (mode)'``, e.g. ``'C#
major'`` or ``'Fb minor'``.  The case of the key is ignored.  Note that certain
key strings are equivalent, e.g. ``'C# major'`` and ``'Db major'``.  The mode
may only be specified as either ``'major'`` or ``'minor'``, no other mode
strings will be accepted.

Metrics
-------
* :func:`mir_eval.key.weighted_score`: Heuristic scoring of the relation of two
  keys.
    N   )utilczc#dbd   zd#   ebe   f   zf#   gbg   zg#   aba	   za#
   bbb   xc                 C   s   t |  dkrt |  r|  dkstd| |  dkrM|  \} }|  dkr4td||  tvrAtd| |dvrOtd| dd	S d	S )
a  Check that a key is well-formatted, e.g. in the form ``'C# major'``.
    The Key can be 'X' if it is not possible to categorize the Key and mode
    can be 'other' if it can't be categorized as major or minor.

    Parameters
    ----------
    key : str
        Key to verify
    r   r   z-'{}' is not in the form '(key) (mode)' or 'X'z9Mode {} is invalid; 'X' (Uncategorized) doesn't have modezDKey {} is invalid; should be e.g. D or C# or Eb or X (Uncategorized))majorminorotherzMode 'z1' is invalid; must be 'major', 'minor' or 'other'N)lensplitlower
ValueErrorformatKEY_TO_SEMITONEkeymode r'   @/home/ubuntu/.local/lib/python3.10/site-packages/mir_eval/key.pyvalidate_key.   s(   (

r)   c                 C   s   | |fD ]}t | qdS )zCheck that the input annotations to a metric are valid key strings and
    throws helpful errors if not.

    Parameters
    ----------
    reference_key : str
        Reference key string.
    estimated_key : str
        Estimated key string.
    N)r)   )reference_keyestimated_keyr%   r'   r'   r(   validateM   s   
r,   c                 C   s.   |   dkr|  \} }nd}t|    |fS )a~  Split a key string (of the form, e.g. ``'C# major'``), into a tuple of
    ``(key, mode)`` where ``key`` is is an integer representing the semitone
    distance from C.

    Parameters
    ----------
    key : str
        String representing a key.

    Returns
    -------
    key : int
        Number of semitones above C.
    mode : str
        String representing the mode.
    r   N)r    r   r#   r$   r'   r'   r(   split_key_string\   s   r-   c                 C   s   t | | t| \} }t|\}}| |kr||krdS | du s#|du r%dS ||kr3||  d dkr3dS ||  kr=dkrIn n
||  d dkrId	S ||  krSd
kr_n n
||  d dkr_d	S ||kri| |kridS dS )a  Compute a heuristic score which is weighted according to the
    relationship of the reference and estimated key, as follows:

    +------------------------------------------------------+-------+
    | Relationship                                         | Score |
    +------------------------------------------------------+-------+
    | Same key and mode                                    | 1.0   |
    +------------------------------------------------------+-------+
    | Estimated key is a perfect fifth above reference key | 0.5   |
    +------------------------------------------------------+-------+
    | Relative major/minor (same key signature)            | 0.3   |
    +------------------------------------------------------+-------+
    | Parallel major/minor (same key)                      | 0.2   |
    +------------------------------------------------------+-------+
    | Other                                                | 0.0   |
    +------------------------------------------------------+-------+

    Examples
    --------
    >>> ref_key = mir_eval.io.load_key('ref.txt')
    >>> est_key = mir_eval.io.load_key('est.txt')
    >>> score = mir_eval.key.weighted_score(ref_key, est_key)

    Parameters
    ----------
    reference_key : str
        Reference key string.
    estimated_key : str
        Estimated key string.

    Returns
    -------
    score : float
        Score representing how closely related the keys are.
    g      ?Ng           r   g      ?r   r   g333333?r   r   g?)r,   r-   )r*   r+   reference_modeestimated_moder'   r'   r(   weighted_scoret   s$   
$r1   c                 K   s   t  }tt| ||d< |S )a  Compute all metrics for the given reference and estimated annotations.

    Examples
    --------
    >>> ref_key = mir_eval.io.load_key('reference.txt')
    >>> est_key = mir_eval.io.load_key('estimated.txt')
    >>> scores = mir_eval.key.evaluate(ref_key, est_key)

    Parameters
    ----------
    reference_key : str
        Reference key string.
    estimated_key : str
        Estimated key string.
    **kwargs
        Additional keyword arguments which will be passed to the
        appropriate metric or preprocessing functions.

    Returns
    -------
    scores : dict
        Dictionary of scores, where the key is the metric name (str) and
        the value is the (float) score achieved.
    zWeighted Score)collectionsOrderedDictr   filter_kwargsr1   )r*   r+   kwargsscoresr'   r'   r(   evaluate   s
   r7   )
__doc__r2    r   r#   r)   r,   r-   r1   r7   r'   r'   r'   r(   <module>   sZ    	
D