o
    siB                     @   sP   d Z ddlZddlZddlZddlmZ dddZdd	 ZdddZ	dd Z
dS )aT  
The goal of a tempo estimation algorithm is to automatically detect the tempo
of a piece of music, measured in beats per minute (BPM).

See http://www.music-ir.org/mirex/wiki/2014:Audio_Tempo_Estimation for a
description of the task and evaluation criteria.

Conventions
-----------

Reference and estimated tempi should be positive, and provided in ascending
order as a numpy array of length 2.

The weighting value from the reference must be a float in the range [0, 1].

Metrics
-------
* :func:`mir_eval.tempo.detection`: Relative error, hits, and weighted
  precision of tempo estimation.

    N   )utilTc                 C   sh   | j dkr	tdtt| rt| dk r td|  d|r0t| dkr2td| dS dS )a  Check that there are two non-negative tempi.
    For a reference value, at least one tempo has to be greater than zero.

    Parameters
    ----------
    tempi : np.ndarray
        length-2 array of tempo, in bpm
    reference : bool
        indicates a reference value
       z"tempi must have exactly two valuesr   ztempi=z must be non-negative numbersz8reference tempi={} must have one value greater than zeroN)size
ValueErrornpallisfiniteanyformat)tempi	reference r   B/home/ubuntu/.local/lib/python3.10/site-packages/mir_eval/tempo.pyvalidate_tempi   s   
r   c                 C   s4   t | dd t |dd |dk s|dkrtddS )a\  Check that the input annotations to a metric look like valid tempo
    annotations.

    Parameters
    ----------
    reference_tempi : np.ndarray
        reference tempo values, in bpm
    reference_weight : float
        perceptual weight of slow vs fast in reference
    estimated_tempi : np.ndarray
        estimated tempo values, in bpm

    T)r   Fr   r   z)Reference weight must lie in range [0, 1]N)r   r   )reference_tempireference_weightestimated_tempir   r   r   validate4   s
   r   {Gz?c                 C   s   t | || |dk s|dkrtd||dkrtd ddg}t| D ]\}}|dkrDt|}tt	|| | }||k||< q&||d  d| |d   }	t
t|}
t
t|}|	|
|fS )aD  Compute the tempo detection accuracy metric.

    Parameters
    ----------
    reference_tempi : np.ndarray, shape=(2,)
        Two non-negative reference tempi
    reference_weight : float > 0
        The relative strength of ``reference_tempi[0]`` vs
        ``reference_tempi[1]``.
    estimated_tempi : np.ndarray, shape=(2,)
        Two non-negative estimated tempi.
    tol : float in [0, 1]:
        The maximum allowable deviation from a reference tempo to
        count as a hit.
        ``|est_t - ref_t| <= tol * ref_t``
        (Default value = 0.08)

    Returns
    -------
    p_score : float in [0, 1]
        Weighted average of recalls:
        ``reference_weight * hits[0] + (1 - reference_weight) * hits[1]``
    one_correct : bool
        True if at least one reference tempo was correctly estimated
    both_correct : bool
        True if both reference tempi were correctly estimated

    Raises
    ------
    ValueError
        If the input tempi are ill-formed

        If the reference weight is not in the range [0, 1]

        If ``tol < 0`` or ``tol > 1``.
    r   r   z2invalid tolerance {}: must lie in the range [0, 1]g        z:A tolerance of 0.0 may not lead to the results you expect.Fg      ?)r   r   r   warningswarn	enumeratefloatr   minabsboolmax)r   r   r   tolhitsiref_tf_ref_trelative_errorp_scoreone_correctboth_correctr   r   r   	detectionI   s$   %

r'   c                 K   s6   t  }tjt| ||fi |\|d< |d< |d< |S )a  Compute all metrics for the given reference and estimated annotations.

    Parameters
    ----------
    reference_tempi : np.ndarray, shape=(2,)
        Two non-negative reference tempi
    reference_weight : float > 0
        The relative strength of ``reference_tempi[0]`` vs
        ``reference_tempi[1]``.
    estimated_tempi : np.ndarray, shape=(2,)
        Two non-negative estimated tempi.
    **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P-scorezOne-correctzBoth-correct)collectionsOrderedDictr   filter_kwargsr'   )r   r   r   kwargsscoresr   r   r   evaluate   s   r-   )T)r   )__doc__r   numpyr   r(    r   r   r   r'   r-   r   r   r   r   <module>   s    

A