
     im                     L   d Z ddlmZ ddlZddlmZ ddlmZ ddl	m
Z
 ddlmZ ddlmZ dd	lmZ dd
lmZmZ ddlmZ ddlmZmZmZ ddlmZmZ ddlmZ ddlm Z  ddl!m"Z"  G d de      Z# G d de#      Z$ G d de#      Z% G d de#      Z& G d de#      Z' G d de      Z(y)zClustering pipelines    )EnumN)	rearrange)	AudioFile)PLDA)oracle_segmentation)	permutate)cluster_vbx)SlidingWindowSlidingWindowFeature)Pipeline)CategoricalIntegerUniform)fclusterlinkage)linear_sum_assignment)cdist)KMeansc                       e Zd Z	 	 ddedef fdZ	 	 	 ddededz  dedz  dedz  fd	Z	 	 dd
ej                  de
dz  dedeej                  ej                  ej                  f   fdZdej                  dej                  fdZ	 dd
ej                  dej                  dej                  dej                  def
dZ	 	 	 	 dd
ej                  de
dz  dedz  dedz  dedz  dej                  fdZ xZS )BaseClusteringmetricconstrained_assignmentc                 >    t         |           || _        || _        y )N)super__init__r   r   selfr   r   	__class__s      x/Volumes/fast/ai/experiments/voice-extract-mac/.venv/lib/python3.12/site-packages/pyannote/audio/pipelines/clustering.pyr   zBaseClustering.__init__-   s    
 	&<#    Nnum_embeddingsnum_clustersmin_clustersmax_clustersc                     |xs |xs d}t        dt        ||            }|xs |xs |}t        dt        ||            }||kD  rt        d|dd|dd      ||k(  r|}|||fS )N   zQmin_clusters must be smaller than (or equal to) max_clusters (here: min_clusters=gz and max_clusters=z).)maxmin
ValueError)r   r!   r"   r#   r$   s        r   set_num_clusterszBaseClustering.set_num_clusters6   s     $8|8q1c.,?@#E|E~1c.,?@,&''3A&66HVWHXXZ\ 
 <''L\<77r    
embeddingssegmentationsmin_active_ratioreturnc                 x   |j                   j                  \  }}}t        j                  |j                   dd      dk(  }t        j                  |j                   |z  d      }|||z  k\  }t        j                  t        j
                  |      d       }	t        j                  ||	z        \  }
}||
|f   |
|fS )a   Filter embeddings before clustering

        Embeddings that are removed:
        * NaN embeddings
        * embeddings speaking less than `min_active_ratio` times the chunk duration

        Parameters
        ----------
        embeddings : (num_chunks, num_speakers, dimension) array
            Sequence of embeddings.
        segmentations : (num_chunks, num_frames, num_speakers) array
            Binary segmentations.
        min_active_ratio : float, optional
            Minimum active ratio for a speaker to be considered active
            during clustering.

        Returns
        -------
        filtered_embeddings : (num_embeddings, dimension) array
        chunk_idx : (num_embeddings, ) array
        speaker_idx : (num_embeddings, ) array
           Taxiskeepdimsr&   r3   )datashapenpsumanyisnanwhere)r   r,   r-   r.   _
num_framessingle_active_masknum_clean_framesactivevalid	chunk_idxspeaker_idxs               r   filter_embeddingsz BaseClustering.filter_embeddingsM   s    : )--33:q !ff]%7%7a$OSTT 66-"4"47I"IPQR "%5
%BB ,155 "$&5.!9	;)[019kIIr    soft_clustersc                 J   t        j                  |t        j                  |            }|j                  \  }}}dt        j                  ||ft         j
                        z  }t        |      D ]0  \  }}t        |d      \  }}	t        ||	      D ]  \  }
}||||
f<    2 |S )N)nandtypeT)maximize)	r8   
nan_to_numnanminr7   onesint8	enumerater   zip)r   rF   
num_chunksnum_speakersr"   hard_clustersccostspeakersclusterssks               r   constrained_argmaxz!BaseClustering.constrained_argmax   s    m=9QR1>1D1D.
L, RWWj,%?rwwOO /GAt!6td!KHhHh/1&'ad# 0 0
 r    train_chunk_idxtrain_speaker_idxtrain_clustersconstrainedc           
         t        j                  |      dz   }|j                  \  }}}	|||f   }
t        j                  t	        |      D cg c]  }t        j
                  |
||k(     d      ! c}      }t        t        t        |d      || j                        d||      }d|z
  }|r| j                  |      }nt        j                  |d      }|||fS c c}w )	a  Assign embeddings to the closest centroid

        Cluster centroids are computed as the average of the train embeddings
        previously assigned to them.

        Parameters
        ----------
        embeddings : (num_chunks, num_speakers, dimension)-shaped array
            Complete set of embeddings.
        train_chunk_idx : (num_embeddings,)-shaped array
        train_speaker_idx : (num_embeddings,)-shaped array
            Indices of subset of embeddings used for "training".
        train_clusters : (num_embedding,)-shaped array
            Clusters of the above subset
        constrained : bool, optional
            Use constrained_argmax, instead of (default) argmax.

        Returns
        -------
        soft_clusters : (num_chunks, num_speakers, num_clusters)-shaped array
        hard_clusters : (num_chunks, num_speakers)-shaped array
        centroids : (num_clusters, dimension)-shaped array
            Clusters centroids
        r&   r   r5   c s d -> (c s) dr   (c s) k -> c s krV   rZ   r1   )r8   r(   r7   vstackrangemeanr   r   r   r\   argmax)r   r,   r]   r^   r_   r`   r"   rS   rT   	dimensiontrain_embeddingsr[   	centroidse2k_distancerF   rU   s                   r   assign_embeddingsz BaseClustering.assign_embeddings   s    F vvn-1.8.>.>+
L)%o7H&HIII |,,A (1)<=AF,
	 !*&89{{
 	
 L(  33MBMIIm!<M mY66;s   $Cc                    | j                  ||      \  }}}	|j                  \  }
}| j                  |
|||      \  }}}|dk  rl|j                  \  }}}t        j                  ||ft        j
                        }t        j                  ||df      }t        j                  |dd      }|||fS | j                  ||||	      }| j                  |||	|| j                  
      \  }}}|||fS )a  Apply clustering

        Parameters
        ----------
        embeddings : (num_chunks, num_speakers, dimension) array
            Sequence of embeddings.
        segmentations : (num_chunks, num_frames, num_speakers) array
            Binary segmentations.
        num_clusters : int, optional
            Number of clusters, when known. Default behavior is to use
            internal threshold hyper-parameter to decide on the number
            of clusters.
        min_clusters : int, optional
            Minimum number of clusters. Has no effect when `num_clusters` is provided.
        max_clusters : int, optional
            Maximum number of clusters. Has no effect when `num_clusters` is provided.

        Returns
        -------
        hard_clusters : (num_chunks, num_speakers) array
            Hard cluster assignment (hard_clusters[c, s] = k means that sth speaker
            of cth chunk is assigned to kth cluster)
        soft_clusters : (num_chunks, num_speakers, num_clusters) array
            Soft cluster assignment (the higher soft_clusters[c, s, k], the most likely
            the sth speaker of cth chunk belongs to kth cluster)
        centroids : (num_clusters, dimension) array
            Centroid vectors of each cluster
        r-   )r"   r#   r$   r1   rJ   r&   r   Tr2   )r#   r$   r"   )r`   )rE   r7   r+   r8   zerosrP   rO   rh   clusterrn   r   )r   r,   r-   r"   r#   r$   kwargsrk   r]   r^   r!   r=   rS   rT   rU   rF   rl   r_   s                     r   __call__zBaseClustering.__call__   s5   L @D?U?U' @V @
</+<
 -22373H3H%%%	 4I 4
0lL !*4*:*:'JaHHj,%?rwwOMGGZq$ABM 0q4HI -::%%%	 & 
 372H2H33 3I 3
/}i mY66r    cosineFNNN)Ng?)FNNNN)__name__
__module____qualname__strboolr   intr+   r8   ndarrayr   floattuplerE   r\   rn   rt   __classcell__r   s   @r   r   r   ,   s    ',== !%= $(#'#'88 Dj8 Dj	8
 Dj84 6:"%	0JJJ0J ,d20J  	0J
 
rzz2::rzz1	20Jd

 rzz * "F7JJF7 F7 ::	F7
 

F7 F7V 6:#'#'#'K7JJK7 ,d2K7 Dj	K7
 DjK7 DjK7 
K7r    r   c            
            e Zd ZU dZdZeed<   	 	 ddedef fdZ	 	 	 dde	j                  d	edz  d
edz  dedz  fdZ xZS )AgglomerativeClusteringa  Agglomerative clustering

    Parameters
    ----------
    metric : {"cosine", "euclidean", ...}, optional
        Distance metric to use. Defaults to "cosine".

    Hyper-parameters
    ----------------
    method : {"average", "centroid", "complete", "median", "single", "ward"}
        Linkage method.
    threshold : float in range [0.0, 2.0]
        Clustering threshold.
    min_cluster_size : int in range [1, 20]
        Minimum cluster size
    Fexpects_num_clustersr   r   c                     t         |   ||       t        dd      | _        t	        g d      | _        t        dd      | _        y )Nr   r   g        g       @)averagecentroidcompletemediansinglewardweightedr&      )r   r   r   	thresholdr   methodr   min_cluster_sizer   s      r   r   z AgglomerativeClustering.__init__8  sL    
 	#9 	 	

 !c*!W

 !(2r    Nr,   r#   r$   r"   c           
         |j                   \  }}t        | j                  t        dt	        d|z                    }|dk(  r%t        j                  dt
        j                        S | j                  dk(  rl| j                  dv r^t        j                  dd      5  |t
        j                  j                  |d	d
      z  }ddd       t        || j                  d      }n"t        || j                  | j                        }t        || j                  d      dz
  }	t        j                   |	d
      \  }
}|
||k\     }t#        |      }||k  r|}n||kD  r|}|J||k7  rDt        j$                  |      }t        j&                  |dz
        |dddf<   |dz
  }d}t        j(                  t        j*                  |dddf   | j                  z
              D ]u  }||df   }||k  rt        ||d      dz
  }	t        j                   |	d
      \  }
}|
||k\     }t#        |      }t+        ||z
        t+        ||z
        k  r|}|}||k(  su n ||k7  rPt        ||d      dz
  }	t        j                   |	d
      \  }
}|
||k\     }t#        |      }t-        d| d| d       |dk(  rd|	dd |	S |
||k     }t#        |      dk(  r|	S t        j.                  |D cg c]  }t        j0                  ||	|k(     d      ! c}      }t        j.                  |D cg c]  }t        j0                  ||	|k(     d      ! c}      }t3        ||| j                        }t5        t        j6                  |d            D ]  \  }}||   |	|	||   k(  <    t        j                   |	d
      \  }}	|	S # 1 sw Y   xY wc c}w c c}w )a@  

        Parameters
        ----------
        embeddings : (num_embeddings, dimension) array
            Embeddings
        min_clusters : int
            Minimum number of clusters
        max_clusters : int
            Maximum number of clusters
        num_clusters : int, optional
            Actual number of clusters. Default behavior is to estimate it based
            on values provided for `min_clusters`,  `max_clusters`, and `threshold`.

        Returns
        -------
        clusters : (num_embeddings, ) array
            0-indexed cluster indices.
        r&   g?)r&   rJ   rv   )r   r   r   ignoredivideinvalidTr2   N	euclideanr   r   distance	criterion)return_countsr1      zFound only z& clusters. Using a smaller value than z# for `min_cluster_size` might help.r   r5   rc   return_inverse)r7   r)   r   r(   roundr8   rq   uint8r   r   errstatelinalgnormr   r   r   uniquelencopyarangeargsortabsprintrf   rh   r   rQ   argmin)r   r,   r#   r$   r"   r!   r=   r   
dendrogramrY   cluster_uniquecluster_countslarge_clustersnum_large_clusters_dendrogrambest_iterationbest_num_large_clusters	iterationnew_cluster_sizesmall_clusterslarge_klarge_centroidssmall_ksmall_centroidscentroids_cdists                            r   rr   zAgglomerativeClustering.clusterJ  s   6 ',, !!3q%n0D*E#F

 Q88D11 ;;("t{{6T'THh?biinnZb4nPP
 @%,4;;{&J &-4;;t{{&J
 J*MPQQ *,*
& (:J(JK 0 ,'L  ,.'L #(:l(J''*-K "		.1*< =K1+a/N&'#
  ZZz!Q$/?$../P(QR	 $/y!|#< #&66 $KjQTUU138SW1X.!/BR0R!S%(%8" )L89C+l:=  &/N.@+ &5/ S4 ',6[.JORSS  248SW1X.!/BR0R!S%(%8"!"4!55[\l[m  nQ  R "HQKO'9I(IJ~!#O ))  .-G 
8w#67a@-
 ))  .-G 
8w#67a@-
  U )"))O!*L MGW<J7<SHX!889 !N ii>8Y @?vs   &N1$N>$O1N;ru   rw   ry   rz   r{   __doc__r   r}   __annotations__r|   r   r8   r   r~   rr   r   r   s   @r   r   r   $  s    " "'$& ',// !%/* $(#'#'VJJV DjV Dj	V
 DjVr    r   c            
            e Zd ZU dZdZeed<   	 ddef fdZ	 	 	 dde	j                  dedz  d	edz  d
edz  fdZ xZS )KMeansClusteringzKMeans clustering

    Parameters
    ----------
    metric : {"cosine", "euclidean"}, optional
        Distance metric to use. Defaults to "cosine".

    Hyper-parameters
    ----------------
    None
    Tr   r   c                 L    |dvrt        d| d      t        | 	  |       y )N)rv   r   zUnsupported metric: z". Must be 'cosine' or 'euclidean'.rc   )r*   r   r   )r   r   r   s     r   r   zKMeansClustering.__init__  s:     00&vh.PQ  	'r    Nr,   r#   r$   r"   c                    |t        d      |j                  \  }}||k  r%t        j                  |t        j                        S | j
                  dk(  rEt        j                  dd      5  |t        j                  j                  |dd	      z  }ddd       t        |d
dd      j                  |      S # 1 sw Y   'xY w)aY  Perform KMeans clustering

        Parameters
        ----------
        embeddings : (num_embeddings, dimension) array
            Embeddings
        num_clusters : int, optional
            Expected number of clusters.

        Returns
        -------
        clusters : (num_embeddings, ) array
            0-indexed cluster indices.
        Nz `num_clusters` must be provided.rJ   rv   r   r   r   Tr2   r   *   F
n_clustersn_initrandom_statecopy_x)r*   r7   r8   r   int32r   r   r   r   r   fit_predict)r   r,   r#   r$   r"   r!   r=   s          r   rr   zKMeansClustering.cluster  s    , ?@@&,,L(99^288<< ;;("Hh?biinnZb4nPP
 @ #ABu

+j
!	"	 @?s   -&B99C)rv   rw   r   r   s   @r   r   r     sm    
 "&$% 	(	( $(#'#'&"JJ&" Dj&" Dj	&"
 Dj&"r    r   c                        e Zd ZU dZeed<   	 	 ddededef fdZ	 	 	 	 dde	j                  d	edz  d
edz  dedz  dedz  de	j                  fdZ xZS )VBxClusteringFr   pldar   r   c                     t         |   ||       || _        t        dd      | _        t        dd      | _        t        dd      | _        y )Nr   g      ?g?g{Gz?g      .@)r   r   r   r   r   FaFb)r   r   r   r   r   s       r   r   zVBxClustering.__init__+  sP     	#9 	 	

 	 c*$$$%r    Nr,   r-   r"   r#   r$   r/   c           
         | j                   }| j                  ||      \  }}	}	|j                  d   dk  rl|j                  \  }
}}	t        j                  |
|ft        j
                        }t        j                  |
|df      }t        j                  |dd      }|||fS |t        j                  j                  |dd      z  }t        |dd	
      }t        || j                  d      dz
  }t        j                  |d      \  }	}| j                  |      }t        ||| j                  j                   | j"                  | j$                  d      \  }}|j                  \  }
}}|d d |dkD  f   }|j&                  |j)                  d|      z  |j+                  dd      j&                  z  }|j                  \  }}	||k  r|}n||kD  r|}|rl||k7  rgd}t-        |ddd      j/                  |      }t        j0                  t3        |      D cg c]  }t        j                  |||k(     d      ! c}      }t5        t7        t5        |d      || j8                        d|
|      }d|z
  }|rF|j;                         dz
  }|||j<                  j+                  d      dk(  <   | j?                  |      }nt        j@                  |d      }|j)                  |
|      }|||fS c c}w )Nrp   r   r1   rJ   r&   Tr2   r   r   r   r   r   r   r   )r   r   maxItersgHz>r   )r4   Fr   r   r   r5   rb   rc   rd   re         ?)!r   rE   r7   r8   rq   rP   rO   rh   r   r   r   r   r   r   r   r	   phir   r   Treshaper9   r   r   rf   rg   r   r   r   r)   r6   r\   ri   )r   r,   r-   r"   r#   r$   rs   r   rk   r=   rS   rT   rU   rF   rl   train_embeddings_normedr   ahc_clustersfeaqsprj   Wauto_num_clusterskmeans_clustersr[   rm   consts                               r   rt   zVBxClustering.__call__<  s    "&!<!<!%!7!7m "8 "
!Q !!!$q(*4*:*:'JaHHj,%?rwwOMGGZq$ABM 0q4HI -:: #3RYY^^1t 6D 6
 #
 #J{

  
DNNjQTUU))LF< ii()IIMMwwww
2 /9.>.>+
L)adlOCC*222yAAAEE!VZED[D]D]]	  )1|+'L-'LL,== &+"$'5k12  		 #<00 GG,_-ABK0I !*&89{{
 	
 L( "!%%'",E<AM-,,003q89 33M IIm!<M%--j,GmY66=s   $K&)rv   Trx   )ry   rz   r{   r   r}   r   r   r|   r   r8   r   r   r~   rt   r   r   s   @r   r   r   &  s    !&$& '+	&& & !%	&( 6:#'#'#'a7JJa7 ,d2a7 Dj	a7
 Dja7 Dja7 
a7r    r   c                       e Zd ZU dZdZeed<   	 	 	 	 ddej                  dz  de	dz  de
dz  dedz  d	ej                  f
d
Zy)OracleClusteringzOracle clusteringTr   Nr,   r-   fileframesr/   c           
      b   |j                   j                  \  }}}|j                  }	t        ||	|      }
|
|d<   |
j                   j                  \  }}}|j                   dddt	        ||      f   }|
j                   dddt	        ||      f   }
dt        j                  ||ft
        j                        z  }t        j                  |||f      }t        t        ||
            D ]O  \  }\  }}t        |t
        j                     |      \  }^}}t        |      D ]  \  }}|	||||f<   d||||f<    Q |||dfS | j                  ||      \  }}}|||f   }t        j                  t        |      D cg c]  }t        j                   |||k(     d	      ! c}      }|||fS c c}w )
a  Apply oracle clustering

        Parameters
        ----------
        embeddings : (num_chunks, num_speakers, dimension) array, optional
            Sequence of embeddings. When provided, compute speaker centroids
            based on these embeddings.
        segmentations : (num_chunks, num_frames, num_speakers) array
            Binary segmentations.
        file : AudioFile
        frames : SlidingWindow

        Returns
        -------
        hard_clusters : (num_chunks, num_speakers) array
            Hard cluster assignment (hard_clusters[c, s] = k means that sth speaker
            of cth chunk is assigned to kth cluster)
        soft_clusters : (num_chunks, num_speakers, num_clusters) array
            Soft cluster assignment (the higher soft_clusters[c, s, k], the most likely
            the sth speaker of cth chunk belongs to kth cluster)
        centroids : (num_clusters, dimension), optional
            Clusters centroids if `embeddings` is provided, None otherwise.
        )r   oracle_segmentationsNrI   rJ   r   rp   r   r5   )r6   r7   sliding_windowr   r)   r8   rO   rP   rq   rQ   rR   r   newaxisrE   rf   rg   rh   )r   r,   r-   r   r   rs   rS   r>   rT   windowr   r=   oracle_num_framesr"   rU   rF   rV   segmentationoraclepermutationjirk   r]   r^   r_   r[   rl   s                               r   rt   zOracleClustering.__call__  s   @ 0=/A/A/G/G,
J--24O (<#$-A-F-F-L-L*l%**1.RJ@Q0R.R+RS3883Z!2333 
 RWWj,%?rwwOO*lL!IJ)234*
%A%f $-VBJJ-?#N A a!+.19&'ad#),aAg&	 /	*
  -55 ""' # 
		
 '8I'IJII |,,A (1)<=AF,
	 mY66s   <$F,rx   )ry   rz   r{   r   r   r}   r   r8   r   r   r   r
   rt    r    r   r   r     su    !%$% )-59!%'+O7JJ%O7 ,d2O7 $	O7
 $O7 
O7r    r   c                       e Zd ZeZeZeZeZy)
ClusteringN)ry   rz   r{   r   r   r   r   r   r    r   r   r     s    5'!M'r    r   ))r   enumr   numpyr8   einopsr   pyannote.audio.core.ior   pyannote.audio.core.pldar   pyannote.audio.pipelines.utilsr    pyannote.audio.utils.permutationr   pyannote.audio.utils.vbxr	   pyannote.corer
   r   pyannote.pipeliner   pyannote.pipeline.parameterr   r   r   scipy.cluster.hierarchyr   r   scipy.optimizer   scipy.spatial.distancer   sklearn.clusterr   r   r   r   r   r   r   r   r    r   <module>r     s   0     , ) > 6 0 = & E E 5 0 ( "u7X u7p|n |~@"~ @"Fw7N w7tT7~ T7n( (r    