o
    sieB                     @   s   d Z ddlZddlZddlZddlmZ ddlZdZ	dZ
dZdd	 Zd
d ZdddZdd Zdd Zd ddZdd Zdd Zdd Zdd ZdS )!a  
The goal of multiple f0 (multipitch) estimation and tracking is to identify
all of the active fundamental frequencies in each time frame in a complex music
signal.

Conventions
-----------
Multipitch estimates are represented by a timebase and a corresponding list
of arrays of frequency estimates. Frequency estimates may have any number of
frequency values, including 0 (represented by an empty array). Time values are
in units of seconds and frequency estimates are in units of Hz.

The timebase of the estimate time series should ideally match the timebase of
the reference time series, but if this is not the case, the estimate time
series is resampled using a nearest neighbor interpolation to match the
estimate. Time values in the estimate time series that are outside of the range
of the reference time series are given null (empty array) frequencies.

By default, a frequency is "correct" if it is within 0.5 semitones of a
reference frequency. Frequency values are compared by first mapping them to
log-2 semitone space, where the distance between semitones is constant.
Chroma-wrapped frequency values are computed by taking the log-2 frequency
values modulo 12 to map them down to a single octave. A chroma-wrapped
frequency estimate is correct if it's single-octave value is within 0.5
semitones of the single-octave reference frequency.

The metrics are based on those described in
[#poliner2007]_ and [#bay2009]_.

Metrics
-------
* :func:`mir_eval.multipitch.metrics`: Precision, Recall, Accuracy,
  Substitution, Miss, False Alarm, and Total Error scores based both on raw
  frequency values and values mapped to a single octave (chroma).

References
----------
.. [#poliner2007] G. E. Poliner, and D. P. W. Ellis, "A Discriminative
   Model for Polyphonic Piano Transription", EURASIP Journal on Advances in
   Signal Processing, 2007(1):154-163, Jan. 2007.
.. [#bay2009] Bay, M., Ehmann, A. F., & Downie, J. S. (2009). Evaluation of
   Multiple-F0 Estimation and Tracking Systems. In ISMIR (pp. 315-320).
    N   )utilg     L@g     @g      4@c                 C   s   t j| td t j|td | jdkrtd | jdkr!tdt|dkr,td |jdkr6td |jdkr?tdt|dkrJtd	 | jt|krUtd
|jt|kr`td|D ]}t j	|t
tdd qb|D ]}t j	|t
tdd qpdS )ap  Check that the time and frequency inputs are well-formed.

    Parameters
    ----------
    ref_time : np.ndarray
        reference time stamps in seconds
    ref_freqs : list of np.ndarray
        reference frequencies in Hz
    est_time : np.ndarray
        estimate time stamps in seconds
    est_freqs : list of np.ndarray
        estimated frequencies in Hz
    )max_timer   zReference times are empty.r   z&Reference times have invalid dimensionz Reference frequencies are empty.zEstimated times are empty.z&Estimated times have invalid dimensionz Estimated frequencies are empty.z5Reference times and frequencies have unequal lengths.z4Estimate times and frequencies have unequal lengths.F)max_freqmin_freqallow_negativesN)r   validate_eventsMAX_TIMEsizewarningswarnndim
ValueErrorlenvalidate_frequenciesMAX_FREQMIN_FREQ)ref_time	ref_freqsest_time	est_freqsfreq r   G/home/ubuntu/.local/lib/python3.10/site-packages/mir_eval/multipitch.pyvalidate9   s6   







r   c                    s   |j dkrg S | j dkrtg gt| S t|}td|}tjj| |ddd|d|}|tg g   fdd|t	D }|S )a(  Resamples multipitch time series to a new timescale using nearest
    neighbor interpolation. Values in ``target_times`` outside the range
    of ``times`` return no pitch estimate.

    Parameters
    ----------
    times : np.ndarray
        Array of time stamps
    frequencies : list of np.ndarray
        List of np.ndarrays of frequency values
    target_times : np.ndarray
        Array of target time stamps

    Returns
    -------
    frequencies_resampled : list of numpy arrays
        Frequency list of lists resampled to new timebase
    r   nearestFT)kindbounds_errorassume_sorted
fill_valuec                    s   g | ]} | qS r   r   ).0i	freq_valsr   r   
<listcomp>   s    z'resample_multipitch.<locals>.<listcomp>)
r
   nparrayr   arangescipyinterpolateinterp1dastypeint)timesfrequenciestarget_timesn_timesfrequency_indexnew_frequency_indexfrequencies_resampledr   r"   r   resample_multipitchf   s&   

r4        {@c                    s    fdd| D S )aC  Convert frequencies to continuous MIDI values.

    Parameters
    ----------
    frequencies : list of np.ndarray
        Original frequency values
    ref_frequency : float
        reference frequency in Hz.

    Returns
    -------
    frequencies_midi : list of np.ndarray
        Continuous MIDI frequency values.
    c                    s"   g | ]}d dt |    qS )g     @Q@g      (@)r%   log2r    freqsref_frequencyr   r   r$      s   " z'frequencies_to_midi.<locals>.<listcomp>r   )r.   r:   r   r9   r   frequencies_to_midi   s   r;   c                 C   s   dd | D S )a   Wrap MIDI frequencies to a single octave (chroma).

    Parameters
    ----------
    frequencies_midi : list of np.ndarray
        Continuous MIDI note frequency values.

    Returns
    -------
    frequencies_chroma : list of np.ndarray
        Midi values wrapped to one octave.

    c                 S   s   g | ]}t |d qS )   )r%   modr7   r   r   r   r$      s    z"midi_to_chroma.<locals>.<listcomp>r   )frequencies_midir   r   r   midi_to_chroma   s   r?   c                 C   s   t dd | D S )zCompute the number of frequencies for each time point.

    Parameters
    ----------
    frequencies : list of np.ndarray
        Frequency values

    Returns
    -------
    num_freqs : np.ndarray
        Number of frequencies at each time point.
    c                 S   s   g | ]}|j qS r   )r
   )r    fr   r   r   r$      s    z%compute_num_freqs.<locals>.<listcomp>)r%   r&   )r.   r   r   r   compute_num_freqs   s   rA         ?Fc           
      C   sh   t | }t|f}tt| |D ] \}\}}|r$tj|||tjd}	nt|||}	t |	||< q|S )a  Compute the number of true positives in an estimate given a reference.
    A frequency is correct if it is within a quartertone of the
    correct frequency.

    Parameters
    ----------
    ref_freqs : list of np.ndarray
        reference frequencies (MIDI)
    est_freqs : list of np.ndarray
        estimated frequencies (MIDI)
    window : float
        Window size, in semitones
    chroma : bool
        If True, computes distances modulo n.
        If True, ``ref_freqs`` and ``est_freqs`` should be wrapped modulo n.

    Returns
    -------
    true_positives : np.ndarray
        Array the same length as ref_freqs containing the number of true
        positives.

    )distance)r   r%   zeros	enumeratezipr   match_events_outer_distance_mod_n)
r   r   windowchroman_framestrue_positivesr!   	ref_frame	est_framematchingr   r   r   compute_num_true_positives   s   
rP   c           
      C   s   t |  }| }|dkr||  }ntd d}| }|dkr+||  }ntd d}|| |   }|dkrC|| }	nd}	|||	fS )ak  Compute accuracy metrics.

    Parameters
    ----------
    true_positives : np.ndarray
        Array containing the number of true positives at each time point.
    n_ref : np.ndarray
        Array containing the number of reference frequencies at each time
        point.
    n_est : np.ndarray
        Array containing the number of estimate frequencies at each time point.

    Returns
    -------
    precision : float
        ``sum(true_positives)/sum(n_est)``
    recall : float
        ``sum(true_positives)/sum(n_ref)``
    acc : float
        ``sum(true_positives)/sum(n_est + n_ref - true_positives)``

    r   z#Estimate frequencies are all empty.        $Reference frequencies are all empty.)floatsumr   r   )
rL   n_refn_esttrue_positive_sum	n_est_sum	precision	n_ref_sumrecall	acc_denomaccr   r   r   compute_accuracy   s    



r^   c           
      C   s   t | }|dkrtd dS tj||gdd|   | }|| }d||dk < | | }|| }d||dk < | | }tj||gdd|   | }	||||	fS )a?  Compute error score metrics.

    Parameters
    ----------
    true_positives : np.ndarray
        Array containing the number of true positives at each time point.
    n_ref : np.ndarray
        Array containing the number of reference frequencies at each time
        point.
    n_est : np.ndarray
        Array containing the number of estimate frequencies at each time point.

    Returns
    -------
    e_sub : float
        Substitution error
    e_miss : float
        Miss error
    e_fa : float
        False alarm error
    e_tot : float
        Total error

    r   rR   )rQ   rQ   rQ   rQ   )axis)rS   rT   r   r   r%   minmax)
rL   rU   rV   rZ   e_sube_miss_numeratore_misse_fa_numeratore_fae_totr   r   r   compute_err_score)  s   
rh   c                 K   s  t | ||| |j| jkst|| std t||| }t|}t|}t|}t|}t	|}	t	|}
t
jt||fi |}t
jt||fddi|}t||	|
\}}}t||	|
\}}}}t||	|
\}}}t||	|
\}}}}||||||||||||||fS )a  Compute multipitch metrics. All metrics are computed at the 'macro' level
    such that the frame true positive/false positive/false negative rates are
    summed across time and the metrics are computed on the combined values.

    Examples
    --------
    >>> ref_time, ref_freqs = mir_eval.io.load_ragged_time_series(
    ...     'reference.txt')
    >>> est_time, est_freqs = mir_eval.io.load_ragged_time_series(
    ...     'estimated.txt')
    >>> metris_tuple = mir_eval.multipitch.metrics(
    ...     ref_time, ref_freqs, est_time, est_freqs)

    Parameters
    ----------
    ref_time : np.ndarray
        Time of each reference frequency value
    ref_freqs : list of np.ndarray
        List of np.ndarrays of reference frequency values
    est_time : np.ndarray
        Time of each estimated frequency value
    est_freqs : list of np.ndarray
        List of np.ndarrays of estimate frequency values
    **kwargs
        Additional keyword arguments which will be passed to the
        appropriate metric or preprocessing functions.

    Returns
    -------
    precision : float
        Precision (TP/(TP + FP))
    recall : float
        Recall (TP/(TP + FN))
    accuracy : float
        Accuracy (TP/(TP + FP + FN))
    e_sub : float
        Substitution error
    e_miss : float
        Miss error
    e_fa : float
        False alarm error
    e_tot : float
        Total error
    precision_chroma : float
        Chroma precision
    recall_chroma : float
        Chroma recall
    accuracy_chroma : float
        Chroma accuracy
    e_sub_chroma : float
        Chroma substitution error
    e_miss_chroma : float
        Chroma miss error
    e_fa_chroma : float
        Chroma false alarm error
    e_tot_chroma : float
        Chroma total error

    zLEstimate times not equal to reference times. Resampling to common time base.rJ   T)r   r
   r%   allcloser   r   r4   r;   r?   rA   r   filter_kwargsrP   r^   rh   )r   r   r   r   kwargsref_freqs_midiest_freqs_midiref_freqs_chromaest_freqs_chromarU   rV   rL   true_positives_chromarY   r[   accuracyrb   rd   rf   rg   precision_chromarecall_chromaaccuracy_chromae_sub_chromae_miss_chromae_fa_chromae_tot_chromar   r   r   metrics]  sb   <	
ry   c                 K   sz   t  }tjt| |||fi |\|d< |d< |d< |d< |d< |d< |d< |d< |d	< |d
< |d< |d< |d< |d< |S )a  Evaluate two multipitch (multi-f0) transcriptions, where the first is
    treated as the reference (ground truth) and the second as the estimate to
    be evaluated (prediction).

    Examples
    --------
    >>> ref_time, ref_freq = mir_eval.io.load_ragged_time_series('ref.txt')
    >>> est_time, est_freq = mir_eval.io.load_ragged_time_series('est.txt')
    >>> scores = mir_eval.multipitch.evaluate(ref_time, ref_freq,
    ...                                       est_time, est_freq)

    Parameters
    ----------
    ref_time : np.ndarray
        Time of each reference frequency value
    ref_freqs : list of np.ndarray
        List of np.ndarrays of reference frequency values
    est_time : np.ndarray
        Time of each estimated frequency value
    est_freqs : list of np.ndarray
        List of np.ndarrays of estimate frequency values
    **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.

    	PrecisionRecallAccuracyzSubstitution Errorz
Miss ErrorzFalse Alarm ErrorzTotal ErrorzChroma PrecisionzChroma RecallzChroma AccuracyzChroma Substitution ErrorzChroma Miss ErrorzChroma False Alarm ErrorzChroma Total Error)collectionsOrderedDictr   rj   ry   )r   r   r   r   rk   scoresr   r   r   evaluate  s$   !r   )r5   )rB   F)__doc__numpyr%   r}   scipy.interpolater(    r   r   r	   r   r   r   r4   r;   r?   rA   rP   r^   rh   ry   r   r   r   r   r   <module>   s(    ,-
6
*04 