o
    siֶ                     @   s   d Z ddlZddlZddlZddlZddlZddlZddl	m
Z
 dd Zdd Z	d+ddZd,ddZ		
d-ddZ		
d-ddZdd Zdd Z	d.ddZd/ddZdd Zdd  Zd!d" Z	d.d#d$Z		
	d0d%d&Z		
d-d'd(Zd)d* ZdS )1a  
Evaluation criteria for structural segmentation fall into two categories:
boundary annotation and structural annotation.  Boundary annotation is the task
of predicting the times at which structural changes occur, such as when a verse
transitions to a refrain.  Metrics for boundary annotation compare estimated
segment boundaries to reference boundaries.  Structural annotation is the task
of assigning labels to detected segments.  The estimated labels may be
arbitrary strings - such as A, B, C, - and they need not describe functional
concepts.  Metrics for structural annotation are similar to those used for
clustering data.

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

Both boundary and structural annotation metrics require two dimensional arrays
with two columns, one for boundary start times and one for boundary end times.
Structural annotation further require lists of reference and estimated segment
labels which must have a length which is equal to the number of rows in the
corresponding list of boundary edges.  In both tasks, we assume that
annotations express a partitioning of the track into intervals.  The function
:func:`mir_eval.util.adjust_intervals` can be used to pad or crop the segment
boundaries to span the duration of the entire track.


Metrics
-------

* :func:`mir_eval.segment.detection`: An estimated boundary is considered
  correct if it falls within a window around a reference boundary
  [#turnbull2007]_
* :func:`mir_eval.segment.deviation`: Computes the median absolute time
  difference from a reference boundary to its nearest estimated boundary, and
  vice versa [#turnbull2007]_
* :func:`mir_eval.segment.pairwise`: For classifying pairs of sampled time
  instants as belonging to the same structural component [#levy2008]_
* :func:`mir_eval.segment.rand_index`: Clusters reference and estimated
  annotations and compares them by the Rand Index
* :func:`mir_eval.segment.ari`: Computes the Rand index, adjusted for chance
* :func:`mir_eval.segment.nce`: Interprets sampled reference and estimated
  labels as samples of random variables :math:`Y_R, Y_E` from which the
  conditional entropy of :math:`Y_R` given :math:`Y_E` (Under-Segmentation) and
  :math:`Y_E` given :math:`Y_R` (Over-Segmentation) are estimated
  [#lukashevich2008]_
* :func:`mir_eval.segment.mutual_information`: Computes the standard,
  normalized, and adjusted mutual information of sampled reference and
  estimated segments
* :func:`mir_eval.segment.vmeasure`: Computes the V-Measure, which is similar
  to the conditional entropy metrics, but uses the marginal distributions
  as normalization rather than the maximum entropy distribution
  [#rosenberg2007]_


References
----------
    .. [#turnbull2007] Turnbull, D., Lanckriet, G. R., Pampalk, E.,
        & Goto, M.  A Supervised Approach for Detecting Boundaries in Music
        Using Difference Features and Boosting. In ISMIR (pp. 51-54).

    .. [#levy2008] Levy, M., & Sandler, M.
        Structural segmentation of musical audio by constrained clustering.
        IEEE transactions on audio, speech, and language processing, 16(2),
        318-326.

    .. [#lukashevich2008] Lukashevich, H. M.
        Towards Quantitative Measures of Evaluating Song Segmentation.
        In ISMIR (pp. 375-380).

    .. [#rosenberg2007] Rosenberg, A., & Hirschberg, J.
        V-Measure: A Conditional Entropy-Based External Cluster Evaluation
        Measure.
        In EMNLP-CoNLL (Vol. 7, pp. 410-420).
    N   )utilc                 C   sV   |rd}nd}t | |k rtd t ||k rtd | |fD ]}t| q!dS )a  Check that the input annotations to a segment boundary estimation
    metric (i.e. one that only takes in segment intervals) look like valid
    segment times, and throws helpful errors if not.

    Parameters
    ----------
    reference_intervals : np.ndarray, shape=(n, 2)
        reference segment intervals, in the format returned by
        :func:`mir_eval.io.load_intervals` or
        :func:`mir_eval.io.load_labeled_intervals`.
    estimated_intervals : np.ndarray, shape=(m, 2)
        estimated segment intervals, in the format returned by
        :func:`mir_eval.io.load_intervals` or
        :func:`mir_eval.io.load_labeled_intervals`.
    trim : bool
        will the start and end events be trimmed?
       r   Reference intervals are empty.Estimated intervals are empty.N)lenwarningswarnr   validate_intervals)reference_intervalsestimated_intervalstrimmin_size	intervals r   D/home/ubuntu/.local/lib/python3.10/site-packages/mir_eval/segment.pyvalidate_boundaryV   s   

r   c                 C   s   | |f||ffD ]'\}}t | |jd t|krtd|jdkr/t| ds/tdq| jdkr:t	
d |jdkrDt	
d | jdkr\|jdkr^t|  | s`tddS dS dS )	ax  Check that the input annotations to a structure estimation metric (i.e.
    one that takes in both segment boundaries and their labels) look like valid
    segment times and labels, and throws helpful errors if not.

    Parameters
    ----------
    reference_intervals : np.ndarray, shape=(n, 2)
        reference segment intervals, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    reference_labels : list, shape=(n,)
        reference segment labels, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    estimated_intervals : np.ndarray, shape=(m, 2)
        estimated segment intervals, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    estimated_labels : list, shape=(m,)
        estimated segment labels, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.

    r   z3Number of intervals does not match number of labels        z#Segment intervals do not start at 0r   r   zEnd times do not matchN)r   r
   shaper   
ValueErrorsizenpallcloseminr   r	   max)r   reference_labelsr   estimated_labelsr   labelsr   r   r   validate_structurey   s&   





r         ?      ?Fc                 C   s   t | || t| }t|}|r|dd }|dd }t|dks*t|dkr,dS t|||}tt|t| }tt|t| }	tj||	|d}
||	|
fS )a=	  Boundary detection hit-rate.

    A hit is counted whenever an reference boundary is within ``window`` of a
    estimated boundary.  Note that each boundary is matched at most once: this
    is achieved by computing the size of a maximal matching between reference
    and estimated boundary points, subject to the window constraint.

    Examples
    --------
    >>> ref_intervals, _ = mir_eval.io.load_labeled_intervals('ref.lab')
    >>> est_intervals, _ = mir_eval.io.load_labeled_intervals('est.lab')
    >>> # With 0.5s windowing
    >>> P05, R05, F05 = mir_eval.segment.detection(ref_intervals,
    ...                                            est_intervals,
    ...                                            window=0.5)
    >>> # With 3s windowing
    >>> P3, R3, F3 = mir_eval.segment.detection(ref_intervals,
    ...                                         est_intervals,
    ...                                         window=3)
    >>> # Ignoring hits for the beginning and end of track
    >>> P, R, F = mir_eval.segment.detection(ref_intervals,
    ...                                      est_intervals,
    ...                                      window=0.5,
    ...                                      trim=True)

    Parameters
    ----------
    reference_intervals : np.ndarray, shape=(n, 2)
        reference segment intervals, in the format returned by
        :func:`mir_eval.io.load_intervals` or
        :func:`mir_eval.io.load_labeled_intervals`.
    estimated_intervals : np.ndarray, shape=(m, 2)
        estimated segment intervals, in the format returned by
        :func:`mir_eval.io.load_intervals` or
        :func:`mir_eval.io.load_labeled_intervals`.
    window : float > 0
        size of the window of 'correctness' around ground-truth beats
        (in seconds)
        (Default value = 0.5)
    beta : float > 0
        weighting constant for F-measure.
        (Default value = 1.0)
    trim : boolean
        if ``True``, the first and last boundary times are ignored.
        Typically, these denote start (0) and end-markers.
        (Default value = False)

    Returns
    -------
    precision : float
        precision of estimated predictions
    recall : float
        recall of reference reference boundaries
    f_measure : float
        F-measure (weighted harmonic mean of ``precision`` and ``recall``)
    r   r   r   r   r   beta)r   r   intervals_to_boundariesr   match_eventsfloat	f_measure)r   r   windowr$   r   reference_boundariesestimated_boundariesmatching	precisionrecallr(   r   r   r   	detection   s   ;


r/   c                 C   s   t | || t| }t|}|r|dd }|dd }t|dks*t|dkr0tjtjfS ttj||}t	|j
dd}t	|j
dd}||fS )a  Compute the median deviations between reference
    and estimated boundary times.

    Examples
    --------
    >>> ref_intervals, _ = mir_eval.io.load_labeled_intervals('ref.lab')
    >>> est_intervals, _ = mir_eval.io.load_labeled_intervals('est.lab')
    >>> r_to_e, e_to_r = mir_eval.boundary.deviation(ref_intervals,
    ...                                              est_intervals)

    Parameters
    ----------
    reference_intervals : np.ndarray, shape=(n, 2)
        reference segment intervals, in the format returned by
        :func:`mir_eval.io.load_intervals` or
        :func:`mir_eval.io.load_labeled_intervals`.
    estimated_intervals : np.ndarray, shape=(m, 2)
        estimated segment intervals, in the format returned by
        :func:`mir_eval.io.load_intervals` or
        :func:`mir_eval.io.load_labeled_intervals`.
    trim : boolean
        if ``True``, the first and last intervals are ignored.
        Typically, these denote start (0.0) and end-of-track markers.
        (Default value = False)

    Returns
    -------
    reference_to_estimated : float
        median time from each reference boundary to the
        closest estimated boundary
    estimated_to_reference : float
        median time from each estimated boundary to the
        closest reference boundary
    r   r!   r   axis)r   r   r%   r   r   nanabssubtractoutermedianr   )r   r   r   r*   r+   distestimated_to_referencereference_to_estimatedr   r   r   	deviation   s   #

r:   皙?c                 C   s   t | ||| | jdks|jdkrdS tj| ||dd }t|d }tj|||dd }t|d }tj||}| t	| d }	tj||}
|
 t	| d }t
||
}| t	| d }|| }||	 }tj|||d}|||fS )a  Frame-clustering segmentation evaluation by pair-wise agreement.

    Examples
    --------
    >>> (ref_intervals,
    ...  ref_labels) = mir_eval.io.load_labeled_intervals('ref.lab')
    >>> (est_intervals,
    ...  est_labels) = mir_eval.io.load_labeled_intervals('est.lab')
    >>> # Trim or pad the estimate to match reference timing
    >>> (ref_intervals,
    ...  ref_labels) = mir_eval.util.adjust_intervals(ref_intervals,
    ...                                               ref_labels,
    ...                                               t_min=0)
    >>> (est_intervals,
    ...  est_labels) = mir_eval.util.adjust_intervals(
    ...     est_intervals, est_labels, t_min=0, t_max=ref_intervals.max())
    >>> precision, recall, f = mir_eval.structure.pairwise(ref_intervals,
    ...                                                    ref_labels,
    ...                                                    est_intervals,
    ...                                                    est_labels)

    Parameters
    ----------
    reference_intervals : np.ndarray, shape=(n, 2)
        reference segment intervals, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    reference_labels : list, shape=(n,)
        reference segment labels, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    estimated_intervals : np.ndarray, shape=(m, 2)
        estimated segment intervals, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    estimated_labels : list, shape=(m,)
        estimated segment labels, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    frame_size : float > 0
        length (in seconds) of frames for clustering
        (Default value = 0.1)
    beta : float > 0
        beta value for F-measure
        (Default value = 1.0)

    Returns
    -------
    precision : float > 0
        Precision of detecting whether frames belong in the same cluster
    recall : float > 0
        Recall of detecting whether frames belong in the same cluster
    f : float > 0
        F-measure of detecting whether frames belong in the same cluster

    r   r"   sample_sizer!          @r#   )r   r   r   intervals_to_samplesindex_labelsr   equalr5   sumr   logical_andr(   )r   r   r   r   
frame_sizer$   y_refy_est	agree_refn_agree_ref	agree_estn_agree_estmatches	n_matchesr-   r.   r(   r   r   r   pairwise6  s6   <
rM   c                 C   s   t | ||| | jdks|jdkrdS tj| ||dd }t|d }tj|||dd }t|d }tj||}tj||}	t||	}
t| |	 }t	|t	|d  d }|

 t	| d }|
 d }|| | }|S )aO  (Non-adjusted) Rand index.

    Examples
    --------
    >>> (ref_intervals,
    ...  ref_labels) = mir_eval.io.load_labeled_intervals('ref.lab')
    >>> (est_intervals,
    ...  est_labels) = mir_eval.io.load_labeled_intervals('est.lab')
    >>> # Trim or pad the estimate to match reference timing
    >>> (ref_intervals,
    ...  ref_labels) = mir_eval.util.adjust_intervals(ref_intervals,
    ...                                               ref_labels,
    ...                                               t_min=0)
    >>> (est_intervals,
    ...  est_labels) = mir_eval.util.adjust_intervals(
    ...     est_intervals, est_labels, t_min=0, t_max=ref_intervals.max())
    >>> rand_index = mir_eval.structure.rand_index(ref_intervals,
    ...                                            ref_labels,
    ...                                            est_intervals,
    ...                                            est_labels)

    Parameters
    ----------
    reference_intervals : np.ndarray, shape=(n, 2)
        reference segment intervals, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    reference_labels : list, shape=(n,)
        reference segment labels, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    estimated_intervals : np.ndarray, shape=(m, 2)
        estimated segment intervals, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    estimated_labels : list, shape=(m,)
        estimated segment labels, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    frame_size : float > 0
        length (in seconds) of frames for clustering
        (Default value = 0.1)
    beta : float > 0
        beta value for F-measure
        (Default value = 1.0)

    Returns
    -------
    rand_index : float > 0
        Rand index
    r   r"   r<   r!   r   r>   )r   r   r   r?   r@   r   rA   r5   rC   r   rB   )r   r   r   r   rD   r$   rE   rF   rG   rI   matches_posmatches_negn_pairsn_matches_posn_matches_negrandr   r   r   
rand_index  s4   7rT   c                 C   sh   t j| dd\}}t j|dd\}}|jd }|jd }tjjt |jd ||ff||ft jd S )a  Compute the contingency matrix of a true labeling vs an estimated one.

    Parameters
    ----------
    reference_indices : np.ndarray
        Array of reference indices
    estimated_indices : np.ndarray
        Array of estimated indices

    Returns
    -------
    contingency_matrix : np.ndarray
        Contingency matrix, shape=(#reference indices, #estimated indices)
    .. note:: Based on sklearn.metrics.cluster.contingency_matrix

    Treturn_inverser   )r   dtype)	r   uniquer   scipysparse
coo_matrixonesint64toarray)reference_indicesestimated_indicesref_classesref_class_idxest_classesest_class_idxn_ref_classesn_est_classesr   r   r   _contingency_matrix   s   

rg   c                 C   s  t | }t| }t|}|jd |jd   krdksEn |jd |jd   kr/dksEn |jd |jd   krCt | krGdS  ndS t| |}tdd |jddD }tdd |jddD }tdd | D }|| ttj	
|d	 }	|| d
 }
||	 |
|	  S )ae  Compute the Rand index, adjusted for change.

    Parameters
    ----------
    reference_indices : np.ndarray
        Array of reference indices
    estimated_indices : np.ndarray
        Array of estimated indices

    Returns
    -------
    ari : float
        Adjusted Rand index
    .. note:: Based on sklearn.metrics.cluster.adjusted_rand_score

    r   r   r    c                 s   "    | ]}t jj|d ddV  qdS r   r   )exactNrY   specialcomb).0n_cr   r   r   	<genexpr>>      
z'_adjusted_rand_index.<locals>.<genexpr>r0   c                 s   rh   ri   rk   )rn   n_kr   r   r   rp   A  rq   c                 s   rh   ri   rk   )rn   n_ijr   r   r   rp   E  rq   r   r>   )r   r   rX   r   rg   rB   flattenr'   rY   rl   rm   )r_   r`   	n_samplesra   rc   contingency
sum_comb_c
sum_comb_ksum_comb	prod_comb	mean_combr   r   r   _adjusted_rand_index  s,   

"""


r|   c                 C   st   t | ||| | jdks|jdkrdS tj| ||dd }t|d }tj|||dd }t|d }t||S )a  Compute the Adjusted Rand Index (ARI) for frame clustering segmentation evaluation.

    Examples
    --------
    >>> (ref_intervals,
    ...  ref_labels) = mir_eval.io.load_labeled_intervals('ref.lab')
    >>> (est_intervals,
    ...  est_labels) = mir_eval.io.load_labeled_intervals('est.lab')
    >>> # Trim or pad the estimate to match reference timing
    >>> (ref_intervals,
    ...  ref_labels) = mir_eval.util.adjust_intervals(ref_intervals,
    ...                                               ref_labels,
    ...                                               t_min=0)
    >>> (est_intervals,
    ...  est_labels) = mir_eval.util.adjust_intervals(
    ...     est_intervals, est_labels, t_min=0, t_max=ref_intervals.max())
    >>> ari_score = mir_eval.structure.ari(ref_intervals, ref_labels,
    ...                                    est_intervals, est_labels)

    Parameters
    ----------
    reference_intervals : np.ndarray, shape=(n, 2)
        reference segment intervals, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    reference_labels : list, shape=(n,)
        reference segment labels, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    estimated_intervals : np.ndarray, shape=(m, 2)
        estimated segment intervals, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    estimated_labels : list, shape=(m,)
        estimated segment labels, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    frame_size : float > 0
        length (in seconds) of frames for clustering
        (Default value = 0.1)

    Returns
    -------
    ari_score : float > 0
        Adjusted Rand index between segmentations.

    r   r"   r<   r!   )r   r   r   r?   r@   r|   )r   r   r   r   rD   rE   rF   r   r   r   ariM  s$   2
r}   c                 C   s   |du rt | |t}t|}tj|dd}tj|dd}t||}|dk}|| }t|}	|| }t||  t|  t|  }
||	t|  ||
  }| S )a  Compute the mutual information between two sequence labelings.

    Parameters
    ----------
    reference_indices : np.ndarray
        Array of reference indices
    estimated_indices : np.ndarray
        Array of estimated indices
    contingency : np.ndarray
        Pre-computed contingency matrix.  If None, one will be computed.
        (Default value = None)

    Returns
    -------
    mi : float
        Mutual information
    .. note:: Based on sklearn.metrics.cluster.mutual_info_score

    Nr   r0   r   r   )rg   astyper'   r   rB   r5   log)r_   r`   rv   contingency_sumpipjr5   nnzcontingency_nmlog_contingency_nm	log_outermir   r   r   _mutual_info_score  s$   


,r   c                 C   sn   t | dkrdS tj| ddd }t|tj}||dk }t|}t|| t|t|   S )zCalculate the entropy for a labeling.

    Parameters
    ----------
    labels : list-like
        List of labels.

    Returns
    -------
    entropy : float
        Entropy of the labeling.
    .. note:: Based on sklearn.metrics.cluster.entropy

    r   r    TrU   r   )r   r   rX   bincountr~   float64rB   r   )r   	label_idxr   pi_sumr   r   r   _entropy  s   
$r   c               	      s  t | }t| }t|}|jd |jd   krdks2n |jd |jd   kr0dkr4dS  ndS t| |t}t| ||d}|j\}}t| tj|ddtj	}	tj|ddtj	tj
dtt|	td dd}
d|
d< |
  }tt|	}t |
 }tj|	d }tjd }tj |	 d }tj  d }tj d }tj|
d }tj fdd	|	D d
d}t|d}tt|	||fjt||fd }d}t|D ]s}t|D ]l}t|||f |||f D ]\}|| |||f  }|| ||  ||  ||  | ||  tj|	| | d  tj| | d  tj |	|  |  | d  }t|}||| | | 7 }qqqt| t|}}|| t|||  }|S )a  Compute the mutual information between two sequence labelings, adjusted for
    chance.

    Parameters
    ----------
    reference_indices : np.ndarray
        Array of reference indices
    estimated_indices : np.ndarray
        Array of estimated indices

    Returns
    -------
    ami : float <= 1.0
        Mutual information
    .. note:: Based on sklearn.metrics.cluster.adjusted_mutual_info_score
        and sklearn.metrics.cluster.expected_mutual_info_score

    r   r   r    rv   r0   r'   rW   c                    s    g | ]  fd dD qS )c                    s   g | ]}  | qS r   r   )rn   w)Nvr   r   
<listcomp>  s    z:_adjusted_mutual_info_score.<locals>.<listcomp>.<listcomp>r   )rn   r   b)r   r   r     s     z/_adjusted_mutual_info_score.<locals>.<listcomp>int)r   r   rX   r   rg   r~   r'   r   rB   int32aranger   r   r5   rY   rl   gammalnarraymaximumminimumresizeTrangeexpr   ) r_   r`   ru   ra   rc   rv   r   RCanijsterm1log_ab_outerlog_Nnijgln_agln_bgln_Nagln_Nbgln_Ngln_nijstartendemiijnijterm2glnterm3h_trueh_predamir   r   r   _adjusted_mutual_info_score  s|   

"

&*"
r   c           	      C   s   t | }t |}|jd |jd   krdks.n |jd |jd   kr,dkr0dS  ndS t| |t}t j|dd}t| ||d}t| t|}}|t	t 
|| d }|S )a  Compute the mutual information between two sequence labelings, adjusted for
    chance.

    Parameters
    ----------
    reference_indices : np.ndarray
        Array of reference indices
    estimated_indices : np.ndarray
        Array of estimated indices

    Returns
    -------
    nmi : float <= 1.0
        Normalized mutual information
    .. note:: Based on sklearn.metrics.cluster.normalized_mutual_info_score

    r   r   r    r'   r   r   g|=)r   rX   r   rg   r~   r'   r   r   r   r   sqrt)	r_   r`   ra   rc   rv   r   r   r   nmir   r   r   _normalized_mutual_info_score;  s"   

"
r   c           
      C   s   t | ||| | jdks|jdkrdS tj| ||dd }t|d }tj|||dd }t|d }t||}t||}t||}	|||	fS )a  Frame-clustering segmentation: mutual information metrics.

    Examples
    --------
    >>> (ref_intervals,
    ...  ref_labels) = mir_eval.io.load_labeled_intervals('ref.lab')
    >>> (est_intervals,
    ...  est_labels) = mir_eval.io.load_labeled_intervals('est.lab')
    >>> # Trim or pad the estimate to match reference timing
    >>> (ref_intervals,
    ...  ref_labels) = mir_eval.util.adjust_intervals(ref_intervals,
    ...                                               ref_labels,
    ...                                               t_min=0)
    >>> (est_intervals,
    ...  est_labels) = mir_eval.util.adjust_intervals(
    ...     est_intervals, est_labels, t_min=0, t_max=ref_intervals.max())
    >>> mi, ami, nmi = mir_eval.structure.mutual_information(ref_intervals,
    ...                                                      ref_labels,
    ...                                                      est_intervals,
    ...                                                      est_labels)

    Parameters
    ----------
    reference_intervals : np.ndarray, shape=(n, 2)
        reference segment intervals, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    reference_labels : list, shape=(n,)
        reference segment labels, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    estimated_intervals : np.ndarray, shape=(m, 2)
        estimated segment intervals, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    estimated_labels : list, shape=(m,)
        estimated segment labels, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    frame_size : float > 0
        length (in seconds) of frames for clustering
        (Default value = 0.1)

    Returns
    -------
    MI : float > 0
        Mutual information between segmentations
    AMI : float
        Adjusted mutual information between segmentations.
    NMI : float > 0
        Normalize mutual information between segmentations

    r   r"   r<   r!   )r   r   r   r?   r@   r   r   r   )
r   r   r   r   rD   rE   rF   mutual_infoadj_mutual_infonorm_mutual_infor   r   r   mutual_informatione  s*   8



r   c                 C   s\  t | ||| | jdks|jdkrdS tj| ||dd }t|d }tj|||dd }t|d }t||t}	|	t| }	|	j	dd}
|	j	dd}|

tjj|	dd}|
tjj|	jdd}|rytjj|dd}tjj|
dd}nt|	jd }t|	jd }d	}|dkrd
||  }d	}|dkrd
||  }tj|||d}|||fS )ak
  Frame-clustering segmentation: normalized conditional entropy

    Computes cross-entropy of cluster assignment, normalized by the
    max-entropy.

    Examples
    --------
    >>> (ref_intervals,
    ...  ref_labels) = mir_eval.io.load_labeled_intervals('ref.lab')
    >>> (est_intervals,
    ...  est_labels) = mir_eval.io.load_labeled_intervals('est.lab')
    >>> # Trim or pad the estimate to match reference timing
    >>> (ref_intervals,
    ...  ref_labels) = mir_eval.util.adjust_intervals(ref_intervals,
    ...                                               ref_labels,
    ...                                               t_min=0)
    >>> (est_intervals,
    ...  est_labels) = mir_eval.util.adjust_intervals(
    ...     est_intervals, est_labels, t_min=0, t_max=ref_intervals.max())
    >>> S_over, S_under, S_F = mir_eval.structure.nce(ref_intervals,
    ...                                               ref_labels,
    ...                                               est_intervals,
    ...                                               est_labels)

    Parameters
    ----------
    reference_intervals : np.ndarray, shape=(n, 2)
        reference segment intervals, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    reference_labels : list, shape=(n,)
        reference segment labels, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    estimated_intervals : np.ndarray, shape=(m, 2)
        estimated segment intervals, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    estimated_labels : list, shape=(m,)
        estimated segment labels, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    frame_size : float > 0
        length (in seconds) of frames for clustering
        (Default value = 0.1)
    beta : float > 0
        beta for F-measure
        (Default value = 1.0)
    marginal : bool
        If `False`, normalize conditional entropy by uniform entropy.
        If `True`, normalize conditional entropy by the marginal entropy.
        (Default value = False)

    Returns
    -------
    S_over
        Over-clustering score:

        - For `marginal=False`, ``1 - H(y_est | y_ref) / log(|y_est|)``

        - For `marginal=True`, ``1 - H(y_est | y_ref) / H(y_est)``

        If `|y_est|==1`, then `S_over` will be 0.
    S_under
        Under-clustering score:

        - For `marginal=False`, ``1 - H(y_ref | y_est) / log(|y_ref|)``

        - For `marginal=True`, ``1 - H(y_ref | y_est) / H(y_ref)``

        If `|y_ref|==1`, then `S_under` will be 0.
    S_F
        F-measure for (S_over, S_under)
    r   r"   r<   r!   r0   r   r   )baser   r    r#   )r   r   r   r?   r@   rg   r~   r'   r   rB   dotrY   statsentropyr   r   log2r   r(   )r   r   r   r   rD   r$   marginalrE   rF   rv   p_estp_reftrue_given_estpred_given_refz_refz_estscore_under
score_overr(   r   r   r   nce  sH   O
r   c              	   C   s   t | |||||ddS )aI	  Frame-clustering segmentation: v-measure

    Computes cross-entropy of cluster assignment, normalized by the
    marginal-entropy.

    This is equivalent to `nce(..., marginal=True)`.

    Examples
    --------
    >>> (ref_intervals,
    ...  ref_labels) = mir_eval.io.load_labeled_intervals('ref.lab')
    >>> (est_intervals,
    ...  est_labels) = mir_eval.io.load_labeled_intervals('est.lab')
    >>> # Trim or pad the estimate to match reference timing
    >>> (ref_intervals,
    ...  ref_labels) = mir_eval.util.adjust_intervals(ref_intervals,
    ...                                               ref_labels,
    ...                                               t_min=0)
    >>> (est_intervals,
    ...  est_labels) = mir_eval.util.adjust_intervals(
    ...     est_intervals, est_labels, t_min=0, t_max=ref_intervals.max())
    >>> V_precision, V_recall, V_F = mir_eval.structure.vmeasure(ref_intervals,
    ...                                                          ref_labels,
    ...                                                          est_intervals,
    ...                                                          est_labels)

    Parameters
    ----------
    reference_intervals : np.ndarray, shape=(n, 2)
        reference segment intervals, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    reference_labels : list, shape=(n,)
        reference segment labels, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    estimated_intervals : np.ndarray, shape=(m, 2)
        estimated segment intervals, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    estimated_labels : list, shape=(m,)
        estimated segment labels, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    frame_size : float > 0
        length (in seconds) of frames for clustering
        (Default value = 0.1)
    beta : float > 0
        beta for F-measure
        (Default value = 1.0)

    Returns
    -------
    V_precision
        Over-clustering score:
        ``1 - H(y_est | y_ref) / H(y_est)``

        If `|y_est|==1`, then `V_precision` will be 0.
    V_recall
        Under-clustering score:
        ``1 - H(y_ref | y_est) / H(y_ref)``

        If `|y_ref|==1`, then `V_recall` will be 0.
    V_F
        F-measure for (V_precision, V_recall)
    T)rD   r$   r   )r   )r   r   r   r   rD   r$   r   r   r   vmeasureL  s   Fr   c                 K   s  t j| |dd\} }t j||d|  d\}}t }d|d< t jt| |fi |\|d< |d< |d< d	|d< t jt| |fi |\|d
< |d< |d< t jt| |fi |\|d< |d< t jt| |||fi |\|d< |d< |d< t jt	| |||fi ||d< t jt
| |||fi ||d< t jt| |||fi |\|d< |d< |d< t jt| |||fi |\|d< |d< |d< t jt| |||fi |\|d< |d< |d< |S )aY  Compute all metrics for the given reference and estimated annotations.

    Examples
    --------
    >>> (ref_intervals,
    ...  ref_labels) = mir_eval.io.load_labeled_intervals('ref.lab')
    >>> (est_intervals,
    ...  est_labels) = mir_eval.io.load_labeled_intervals('est.lab')
    >>> scores = mir_eval.segment.evaluate(ref_intervals, ref_labels,
    ...                                    est_intervals, est_labels)

    Parameters
    ----------
    ref_intervals : np.ndarray, shape=(n, 2)
        reference segment intervals, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    ref_labels : list, shape=(n,)
        reference segment labels, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    est_intervals : np.ndarray, shape=(m, 2)
        estimated segment intervals, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    est_labels : list, shape=(m,)
        estimated segment labels, in the format returned by
        :func:`mir_eval.io.load_labeled_intervals`.
    **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.
    r   )r   t_min)r   r   t_maxr   r)   zPrecision@0.5z
Recall@0.5zF-measure@0.5g      @zPrecision@3.0z
Recall@3.0zF-measure@3.0zRef-to-est deviationzEst-to-ref deviationzPairwise PrecisionzPairwise RecallzPairwise F-measurez
Rand IndexzAdjusted Rand IndexzMutual InformationzAdjusted Mutual InformationzNormalized Mutual InformationzNCE Overz	NCE UnderzNCE F-measurezV PrecisionzV Recallz	V-measure)r   adjust_intervalsr   collectionsOrderedDictfilter_kwargsr/   r:   rM   rT   r}   r   r   r   )ref_intervals
ref_labelsest_intervals
est_labelskwargsscoresr   r   r   evaluate  s   %

	




	

r   )r   r    F)F)r;   r    )r;   )N)r;   r    F)__doc__r   r   numpyr   scipy.statsrY   scipy.sparsescipy.special r   r   r   r/   r:   rM   rT   rg   r|   r}   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sL   I#0

T?
l
c5

L+]/
`
 
Q