o
    pio4                     @   s   d dl mZmZmZmZmZ d dlZd dlZd dl	Z
d dlZd dlmZmZ d dlmZmZ G dd dZdZdZd	ZG d
d deZdZdZd	ZG dd deZddededefddZdS )    )ListUnionOptionalSetTupleN)
AnnotationTimeline)DetailsMetricComponentsc                
       s2  e Zd ZdZedefddZedefddZ fddZ	d	d
 Z
dd Zedd Z	d,deeef deeef dedee fddZd-dedejfddZdd Zdd Zdedeeef fdd Zd!d" Zdeeef deeef defd#d$Zd%efd&d'Zd.d)edeeeeef f fd*d+Z   Z!S )/
BaseMetricz
    :class:`BaseMetric` is the base class for most pyannote evaluation metrics.

    Attributes
    ----------
    name : str
        Human-readable name of the metric (eg. 'diarization error rate')
    returnc                 C      t | jd )Nz\ is missing a 'metric_name' class method. It should return the name of the metric as string.NotImplementedError__name__cls r   I/home/ubuntu/.local/lib/python3.10/site-packages/pyannote/metrics/base.pymetric_name1      zBaseMetric.metric_namec                 C   r   )Nzh is missing a 'metric_components' class method. It should return the list of names of metric components.r   r   r   r   r   metric_components8   r   zBaseMetric.metric_componentsc                    s6   t t|   | j | _t| j | _| 	  d S N)
superr   __init__	__class__r   metric_name_setr   components_reset)selfkwargsr   r   r   r   ?   s   zBaseMetric.__init__c                 C   s   dd | j D S )Nc                 S   s   i | ]}|d qS )        r   ).0valuer   r   r   
<dictcomp>F   s    z.BaseMetric.init_components.<locals>.<dictcomp>)r   r    r   r   r   init_componentsE   s   zBaseMetric.init_componentsc                 C   s*   t  | _t | _| jD ]}d| j|< qdS )z.Reset accumulated components and metric valuesr#   N)dictaccumulated_listresults_r   )r    r%   r   r   r   r   H   s
   
zBaseMetric.resetc                 C   s   |   S )zMetric name.)r   r'   r   r   r   nameO   s   zBaseMetric.nameFN	reference
hypothesisdetaileduric                 K   sx   | j ||fi |}| ||| j< |pt|dd}| j||f | jD ]}| j|  || 7  < q%|r7|S || j S )a  Compute metric value and accumulate components

        Parameters
        ----------
        reference : type depends on the metric
            Manual `reference`
        hypothesis : type depends on the metric
            Evaluated `hypothesis`
        uri : optional
            Override uri.
        detailed : bool, optional
            By default (False), return metric value only.
            Set `detailed` to True to return dictionary where keys are
            components names and values are component values

        Returns
        -------
        value : float (if `detailed` is False)
            Metric value
        components : dict (if `detailed` is True)
            `components` updated with metric value
        r1   NA)compute_componentscompute_metricr   getattrr,   appendr   r*   )r    r.   r/   r0   r1   r!   
componentsr-   r   r   r   __call__W   s   

zBaseMetric.__call__displayc                 C   s  g }g }d|   v }| jD ]V\}}i }|r|d }| D ];\}	}
|	| jkr/d|
 ||	df< q|	dkr:|
||	df< q|
||	df< |rX|dkrQd|
 | ||	df< qtj||	df< q|| || qi }| j}|ro|d }| D ];\}	}
|	| jkrd|
 ||	df< qs|	dkr|
||	df< qs|
||	df< |r|dkrd|
 | ||	df< qstj||	df< qsdt|  || jdf< || |d t	
|}||d< |d}t	j|j|_|| jg|     }|rt|jdd	d
dd d |S )ak  Evaluation report

        Parameters
        ----------
        display : bool, optional
            Set to True to print the report to stdout.

        Returns
        -------
        report : pandas.DataFrame
            Dataframe with one column per metric component, one row per
            evaluated item, and one final row for accumulated results.
        totald   % r   TOTALitemTFrightc                 S   
   d | S Nz{0:.2f}formatfr   r   r   <lambda>      
 z#BaseMetric.report.<locals>.<lambda>)indexsparsifyjustifyfloat_format)r   r,   itemsr-   npnanr6   r*   abspd	DataFrame	set_index
MultiIndexfrom_tuplescolumnsprint	to_string)r    r9   reporturispercentr1   r7   rowr:   keyr%   dfr   r   r   rY      sj   






	zBaseMetric.reportc                 C   s   | j dd}|jddd dS )NF)r9   c                 S   rA   rB   rC   rE   r   r   r   rG      rH   z$BaseMetric.__str__.<locals>.<lambda>)rJ   rL   )rY   rX   )r    rY   r   r   r   __str__   s   zBaseMetric.__str__c                 C   s   |  | jS )z0Compute metric value from accumulated components)r4   r*   r'   r   r   r   __abs__   s   zBaseMetric.__abs__	componentc                 C   s$   |t dddkrt| jS | j| S )a  Get value of accumulated `component`.

        Parameters
        ----------
        component : str
            Name of `component`

        Returns
        -------
        value : type depends on the metric
            Value of accumulated `component`

        N)slicer)   r*   )r    ra   r   r   r   __getitem__   s   

zBaseMetric.__getitem__c                 c   s     | j D ]	\}}||fV  qdS )z*Iterator over the accumulated (uri, value)N)r,   )r    r1   ra   r   r   r   __iter__   s   zBaseMetric.__iter__c                 K      t | jjd )a  Compute metric components

        Parameters
        ----------
        reference : type depends on the metric
            Manual `reference`
        hypothesis : same as `reference`
            Evaluated `hypothesis`

        Returns
        -------
        components : dict
            Dictionary where keys are component names and values are component
            values

        z is missing a 'compute_components' method.It should return a dictionary where keys are component names and values are component values.r   r   r   )r    r.   r/   r!   r   r   r   r3      s   
zBaseMetric.compute_componentsr7   c                 C   re   )aA  Compute metric value from computed `components`

        Parameters
        ----------
        components : dict
            Dictionary where keys are components names and values are component
            values

        Returns
        -------
        value : type depends on the metric
            Metric value
        z is missing a 'compute_metric' method. It should return the actual value of the metric based on the precomputed component dictionary given as input.rf   )r    r7   r   r   r   r4     s   
zBaseMetric.compute_metric?alphac                    sn    fdd j D }t|dkrtdt|dkr-td |d  } }}|||ffS tjj||dd S )aP  Compute confidence interval on accumulated metric values

        Parameters
        ----------
        alpha : float, optional
            Probability that the returned confidence interval contains
            the true metric value.

        Returns
        -------
        (center, (lower, upper))
            with center the mean of the conditional pdf of the metric value
            and (lower, upper) is a confidence interval centered on the median,
            containing the estimate to a probability alpha.

        See Also:
        ---------
        scipy.stats.bayes_mvs

        c                    s   g | ]	\}}| j  qS r   )r   )r$   _rr'   r   r   
<listcomp>?  s    z2BaseMetric.confidence_interval.<locals>.<listcomp>r   zFPlease evaluate a bunch of files before computing confidence interval.   zCCannot compute a reliable confidence interval out of just one file.)rh   )r,   len
ValueErrorwarningswarnscipystats	bayes_mvs)r    rh   valuescenterlowerupperr   r'   r   confidence_interval(  s   
zBaseMetric.confidence_interval)FN)F)rg   )"r   
__module____qualname____doc__classmethodstrr   r
   r   r   r(   r   propertyr-   r   r   r   boolr   r8   rQ   rR   rY   r_   r`   floatr	   rc   rd   r3   r4   r   rx   __classcell__r   r   r"   r   r   '   sF    	
	

-T


r   	precisionz# retrievedz# relevant retrievedc                   @   @   e Zd ZdZedd ZedefddZdede	fdd	Z
d
S )	PrecisionaU  
    :class:`Precision` is a base class for precision-like evaluation metrics.

    It defines two components '# retrieved' and '# relevant retrieved' and the
    compute_metric() method to compute the actual precision:

        Precision = # retrieved / # relevant retrieved

    Inheriting classes must implement compute_components().
    c                 C      t S r   )PRECISION_NAMEr   r   r   r   r   ^     zPrecision.metric_namer   c                 C      t tgS r   )PRECISION_RETRIEVEDPRECISION_RELEVANT_RETRIEVEDr   r   r   r   r   b     zPrecision.metric_componentsr7   c                 C   4   |t  }|t }|dkr|dkrdS td|| S )z#Compute precision from `components`r#   r         ?r=   )r   r   rn   r    r7   	numeratordenominatorr   r   r   r4   f     zPrecision.compute_metricNr   ry   rz   r{   r|   r   r
   r   r	   r   r4   r   r   r   r   r   R      
r   recallz
# relevantc                   @   r   )RecallaG  
    :class:`Recall` is a base class for recall-like evaluation metrics.

    It defines two components '# relevant' and '# relevant retrieved' and the
    compute_metric() method to compute the actual recall:

        Recall = # relevant retrieved / # relevant

    Inheriting classes must implement compute_components().
    c                 C   r   r   )RECALL_NAMEr   r   r   r   r     r   zRecall.metric_namer   c                 C   r   r   )RECALL_RELEVANTRECALL_RELEVANT_RETRIEVEDr   r   r   r   r     r   zRecall.metric_componentsr7   c                 C   r   )z Compute recall from `components`r#   r   r   r=   )r   r   rn   r   r   r   r   r4     r   zRecall.compute_metricNr   r   r   r   r   r   x  r   r   r   r   c                 C   s4   | | dkrdS d||  |  | || |  |  S )u   Compute f-measure

    f-measure is defined as follows:
        F(P, R, b) = (1+b²).P.R / (b².P + R)

    where P is `precision`, R is `recall` and b is `beta`
    r#   r   rl   r   )r   r   betar   r   r   	f_measure  s   $r   )r   )typingr   r   r   r   r   ro   numpyrN   pandasrQ   scipy.statsrq   pyannote.corer   r   pyannote.metrics.typesr	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s&     (!!