o
    Si3                  
   @   s   d dl mZmZ d dlmZ d dlmZ d dlmZm	Z	m
Z
 d dlZd dlmZ d dlmZ d dlmZmZmZmZ G d	d
 d
Z	ddedede	e dee fddZdS )    )Counterdefaultdict)deepcopy)ceil)ListOptionalTupleN)CutSet)Cut)SecondsTimeSpanifnoneis_module_availablec                   @   sF   e Zd ZdZddefddZddd	Zd
edd fddZdddZ	dS )CutSetStatisticsaJ  
    Low-level utility for creating an overview human-readable description for a CutSet.
    It powers the :meth:`~lhotse.cut.set.CutSet.describe` utility. Unlike `describe`,
    it allows to gather stats for multiple cut sets in parallel and combine and display them later.

    Example workflow (typically, the loop in the second line would be parallelized)::

        >>> cut_sets = [CutSet(...), CutSet(...)]
        >>> stats = [CutSetStatistics().accumulate(cuts) for cuts in cut_sets]
        >>> total_stats = stats[0].combine(*stats[1:])
        >>> total_stats.describe()
    Ffullc                 C   sl   t dstd|| _tt| _t t | _| _g | _	g g | _
| _| jr4tt| _g g | _| _d S d S )NtabulatezSince Lhotse v1.11, this function requires the `tabulate` package to be installed. Please run 'pip install tabulate' to continue.)r   
ValueErrorr   r   intcountersr   
cut_custom
sup_customcut_durationsspeaking_time_durationsspeech_durationslistdurations_by_num_speakerssingle_durationsoverlapped_durations)selfr    r   G/home/ubuntu/.local/lib/python3.10/site-packages/lhotse/cut/describe.py__init__   s   

zCutSetStatistics.__init__otherreturnc              	   G   s   t | }|D ]T}|j|jksJ ddD ]}t||D ]}t|||  t||| 7  < qqd|jr5dnd D ]}t||t|| q8|jrZ|jD ]}|j| |j|  qLq|S )zOCombinemultiple statistics into a new statistics object (does not modify self).zACannot combine statistics gathered with full=True and full=False.)r   r   r   )r   r   r   )r   r   r   )r   r   getattrextendr   )r   r"   lhsrhsattrkr   r   r    combine,   s(   "

zCutSetStatistics.combinecutsc              
   C   sv  dt t dtfdd}|D ]}| j|j t|dr-t|jdD ]}| j	|  d7  < q!| j
d  t|j7  < | j
d	  t|j7  < |jD ]$}| j|j | j
d
  d7  < t|jdD ]}| j|  d7  < q`qH| j|t|dd | jr| j|t|ddd | j|t|ddd | jd | jd  tddD ]}| j| |t|||d qq| S )z1Gather statistics to display later for a cut set.segmentsr#   c                 S   s   t dd | D S )Nc                 s   s    | ]}|j V  qd S )N)duration).0segmentr   r   r    	<genexpr>N   s    zGCutSetStatistics.accumulate.<locals>.total_duration_.<locals>.<genexpr>)sum)r,   r   r   r    total_duration_M   s   z4CutSetStatistics.accumulate.<locals>.total_duration_customr      
recordingsfeaturessupervisions)min_speakers)r8   max_speakers   N   )r   r   floatr   appendr-   hasattrr   r3   r   r   r   has_recordinghas_featurestrimmed_supervisionsr   r   r    find_segments_with_speaker_countr   r   r   r   range)r   r+   r2   ckeysnum_spkr   r   r    
accumulateJ   sV   

	
zCutSetStatistics.accumulateNc              	      s  ddl m } dtdttttf fdd dtdtf fdd}| j}t| }g }|	d	t
|g |	d
||g |	dt|dg |	dt|dg |	dt|dg |	dt|ddg |	dt|dg |	dt|ddg |	dt|ddg |	dt|ddg |	dt|ddg |	dt|dg | j D ]\}}|	|  d|g qtd t||dd | jrtd | j D ]\}}td | d!| d" q| jrtd# | j D ]\}}td | d!| d" qt| j }t| j }	|| }
g }|	d$|||| d%d&g |	d'||	|	| d%d&g |	d(||
|
| d%d&g | jrt| j }t| j }|	d)|||| d%d*|| d%d+g |	d,|||| d%d*|| d%d+g td- t||dd | jsd.S g d/g}| j D ]&\}}t| }|| }|	||||||| d%||	 d%g q|	d0||||	d1d1g td2 t||d3dd4 d.S )5z*Display accumulated statistics in the CLI.r   )r   secondsr#   c                 S   s2   t | d\}} t | d\}} t|t|t| fS )Ni  <   )divmodr   r   )rJ   hoursminutesr   r   r    convert_   s   z+CutSetStatistics.describe.<locals>.convert_c                    s(    | \}}}|dd|dd|dS )N02d:r   )rJ   hmrG   rO   r   r    time_as_str_   s   z/CutSetStatistics.describe.<locals>.time_as_str_zCuts count:zTotal duration (hh:mm:ss)meanz.1fstdminz25%   z50%z75%K   z99%c   z99.5%g     X@z99.9%gX@maxz available:zCut statistics:
fancy_grid)tablefmtzCUT custom fields:z- z (in z cuts)zSUPERVISION custom fields:zTotal speech durationz.2%z of recordingzTotal speaking time durationzTotal silence durationzSingle-speaker durationz (z of speech)zOverlapped speech durationzSpeech duration statistics:N)zNumber of speakerszDuration (hh:mm:ss)zSpeaking time (hh:mm:ss)z% of speechz% of speaking timeTotalz100.00%z1Speech duration statistics by number of speakers:firstrow)headersr^   )r   r   r   r   strr   nparrayr1   r>   lenrV   rW   rX   
percentilemedianr\   r   itemstitleprintr   most_commonr   r   r   r   r   r   r   )r   r   rU   r   	total_sum	cut_statsrF   valtotal_speechtotal_speaking_timetotal_silencespeech_statstotal_singletotal_overlapspeaker_statsrH   	durationsspeaker_sumspeaking_timer   rT   r    describe   s   	



zCutSetStatistics.describe)F)r"   r   r#   r   )r#   N)
__name__
__module____qualname____doc__boolr!   r*   r	   rI   ry   r   r   r   r    r      s    
;r   cutr8   r9   r#   c                 C   s  |du rt d}|dkr||ksJ d| d| d|dkr,|t dkr,td| jgS t| jdkr@|dkr9g S td| jgS g }|d | jD ]}||jdf ||jd	f qJ|| jdf |jd
d d dd t	|D \}}|||d  }d}d}g }	|dd D ]!\}
}||kr||kr|	||
f |dur||rdnd7 }|
}qg }|	D ]%\}}||krq|r|d d |kr|d d |f|d< q|||f qdd |D S )a  
    Given a Cut, find a list of intervals that contain the specified number of speakers.

    :param cuts: the Cut to search.
    :param min_speakers: the minimum number of speakers.
    :param max_speakers: the maximum number of speakers.
    :return: a list of TimeSpans.
    Ninfr   zmin_speakers=z and max_speakers=z are not valid.)        NTFc                 S   s   | d | d d u| d du fS )Nr   r4   Tr   )xr   r   r    <lambda>/  s    z2find_segments_with_speaker_count.<locals>.<lambda>)rF   c                 S   s    g | ]\}}|d  du r|qS )r4   Nr   )r.   itr   r   r    
<listcomp>3  s     z4find_segments_with_speaker_count.<locals>.<listcomp>r4   r   r;   c                 S   s   g | ]	\}}t ||qS r   )r   )r.   startendr   r   r    r   M  s    )
r=   r   r-   re   r7   r>   r   r   sort	enumerate)r   r8   r9   
timestampsr/   cut_start_idxcut_end_idxnum_speakers	seg_start	intervals	timestampis_startmerged_intervalsr   r   r   r   r    rC   	  sF   

rC   )r   N)collectionsr   r   copyr   mathr   typingr   r   r   numpyrc   lhotser	   
lhotse.cutr
   lhotse.utilsr   r   r   r   r   r   rC   r   r   r   r    <module>   s(     ~