
    Wi8                        d dl Zd dlZd dlmZmZ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 d dlmZ 	 	 	 	 	 	 	 	 	 	 	 	 dded	ee   dz  d
edz  dedeeef   dedededej6                  dee	gej8                  f   dz  dee	ge	f   dz  dedej:                  fdZ	 ddej6                  de	dee	gej8                  f   dee	ge	f   dededeee      fdZy)    N)CallableListUnion)
csr_matrix)	hierarchycosine_similarity)select_topic_representation)validate_distance_matrixorientationtopicstop_n_topics
use_ctfidfcustom_labelstitlewidthheighthierarchical_topicslinkage_functiondistance_functioncolor_thresholdreturnc                 
  ! d |
d }
| j                         }|j                  |j                  dk7  ddf   }|t        |      }nL|'t	        |j                  j                         d|       }n#t	        |j                  j                               }t	        t        | j                         j                                     }t        j                  |D cg c]  }|j                  |       c}      }t        | j                  | j                  |      d   |   !|	Bt        |      t        |j                  j                               k(  rt        | |	!|
||      }nd}!fd}t!        j"                  !|||
||      }|d	k(  rd
nd}t%        |t&              r|j(                  |   d   D cg c]#  }t'        |      dgg| j*                  |   |   z   % }}|D cg c]'  }dj-                  |dd D cg c]  }|d   	 c}      ) }}}|D cg c]  }t        |      dk  r|n|dd dz    }}n| j.                  H|rF|j(                  |   d   D cg c]*  }| j.                  |t1        |         | j2                  z      , }}n|j(                  |   d   D cg c]9  }t'        |t1        |               dgg| j5                  |t1        |               ; }}|D cg c]'  }dj-                  |dd D cg c]  }|d   	 c}      ) }}}|D cg c]  }t        |      dk  r|n|dd dz    }}|j7                  dd| dddt9        dd      dt9        ddd             |d	k(  r|j7                  d d!t        |      z  z   |t9        d"|#      $       t;        |d%   D cg c]  }|d&   j;                         d'z    c}      }t=        |d%   D cg c]  }|d&   j=                         d'z
   c}      }|j7                  t9        ||g(      )       n.|j7                  d d!t        |      z  z   |t9        d"|#      *       |	d+D ]  }|d	k(  rd,nd&}|j>                  D cg c]  }|d-   s	||   |   dkD  s|d,   |    }}|j>                  D cg c]  }|d-   s	||   |   dkD  s|d&   |    }}|j>                  D cg c]  }|d-   s	||   |   dkD  s|d-   |    } }|jA                  tC        jD                  ||d.| d-d/d01              |S c c}w c c}w c c}w c c}}w c c}w c c}w c c}w c c}w c c}}w c c}w c c}w c c}w c c}w c c}w c c}w )2ap  Visualize a hierarchical structure of the topics.

    A ward linkage function is used to perform the
    hierarchical clustering based on the cosine distance
    matrix between topic embeddings (either c-TF-IDF or the embeddings from the embedding model).

    Arguments:
        topic_model: A fitted BERTopic instance.
        orientation: The orientation of the figure.
                     Either 'left' or 'bottom'
        topics: A selection of topics to visualize
        top_n_topics: Only select the top n most frequent topics
        use_ctfidf: Whether to calculate distances between topics based on c-TF-IDF embeddings. If False, the embeddings
                    from the embedding model are used.
        custom_labels: If bool, whether to use custom topic labels that were defined using
                       `topic_model.set_topic_labels`.
                       If `str`, it uses labels from other aspects, e.g., "Aspect1".
                       NOTE: Custom labels are only generated for the original
                       un-merged topics.
        title: Title of the plot.
        width: The width of the figure. Only works if orientation is set to 'left'
        height: The height of the figure. Only works if orientation is set to 'bottom'
        hierarchical_topics: A dataframe that contains a hierarchy of topics
                             represented by their parents and their children.
                             NOTE: The hierarchical topic names are only visualized
                             if both `topics` and `top_n_topics` are not set.
        linkage_function: The linkage function to use. Default is:
                          `lambda x: sch.linkage(x, 'ward', optimal_ordering=True)`
                          NOTE: Make sure to use the same `linkage_function` as used
                          in `topic_model.hierarchical_topics`.
        distance_function: The distance function to use on the c-TF-IDF matrix. Default is:
                           `lambda x: 1 - cosine_similarity(x)`.
                            You can pass any function that returns either a square matrix of
                            shape (n_samples, n_samples) with zeros on the diagonal and
                            non-negative values or condensed distance matrix of shape
                            (n_samples * (n_samples - 1) / 2,) containing the upper
                            triangular of the distance matrix.
                           NOTE: Make sure to use the same `distance_function` as used
                           in `topic_model.hierarchical_topics`.
        color_threshold: Value at which the separation of clusters will be made which
                         will result in different colors for different clusters.
                         A higher value will typically lead in less colored clusters.

    Returns:
        fig: A plotly figure

    Examples:
    To visualize the hierarchical structure of
    topics simply run:

    ```python
    topic_model.visualize_hierarchy()
    ```

    If you also want the labels visualized of hierarchical topics,
    run the following:

    ```python
    # Extract hierarchical topics and their representations
    hierarchical_topics = topic_model.hierarchical_topics(docs)

    # Visualize these representations
    topic_model.visualize_hierarchy(hierarchical_topics=hierarchical_topics)
    ```

    If you want to save the resulting figure:

    ```python
    fig = topic_model.visualize_hierarchy()
    fig.write_html("path/to/file.html")
    ```
    <iframe src="../../getting_started/visualization/hierarchy.html"
    style="width:1000px; height: 680px; border: 0px;""></iframe>
    Nc                     dt        |       z
  S )N   r   xs    h/home/sietch6/trending-topics-pipeline/venv/lib/python3.12/site-packages/bertopic/plotting/_hierarchy.py<lambda>z%visualize_hierarchy.<locals>.<lambda>j   s    a*;A*>&>     c                 2    t        j                  | dd      S )NwardT)optimal_ordering)schlinkager   s    r   r   z%visualize_hierarchy.<locals>.<lambda>m   s    S[[FT%R r    r   )topic_modelr   
embeddingsr   r   r   r   c                 B    t         |       j                  d         S )Nr   )r   shape)r   r   r(   s    r   r   z%visualize_hierarchy.<locals>.<lambda>   s#    &>?PQR?SU_UeUefgUh&i r    )r   distfun
linkagefun	hovertextr   leftyaxisxaxisticktext_         z...z#ECEFF1plotly_whiteg      ?centertop   Black)sizecolor)textr   xanchoryanchorfontwhite   Rockwell)bgcolor	font_sizefont_family)plot_bgcolortemplater   
hoverlabel      array)tickmoder1   )r   r   r/   datay   )range)r/   )r   r   r0   )r      r   r=   blackmarkersF)r   rO   marker_colorr-   	hoverinfomode
showlegend)#get_topic_freqlocTopiclistsortedto_list
get_topicskeysnprL   indexr
   	c_tf_idf_topic_embeddings_len_get_annotationsffcreate_dendrogram
isinstancestrlayouttopic_aspects_joincustom_labels_int	_outliers	get_topicupdate_layoutdictmaxminrN   	add_tracegoScatter)"r'   r   r   r   r   r   r   r   r   r   r   r   r   freq_df
all_topicstopicindicesannotationsdistance_function_vizfigaxisr   
new_labelslabelslabeltracey_maxy_minrb   rN   xsysr-   r(   s"              `                     @r   visualize_hierarchyr      s   r  >R ((*Gkk'--2-q01Gf		!--/>?--/0 [335::<=>JhhVDE
((/DEG -[-B-BKDaDacmnopqJ
 &3v;#gmm>S>S>U:V+V&# 3!/-#'
  j


%#'C "V+7D-%UXU_U_`dUefpUq
PQc!fd^{99-HKK

 
 R\\vchhfRajAUaAB\
\T^_5s5zBeE#2J4FF_
_		#	#	/MX[XbXbcgXhisXt
STK&&vc!f~8M8M'MN

 

 \_[e[efj[klv[w
VWc&Q.!4(Q;+@+@A+PQ

 
 R\\vchhfRajAUaAB\
\T^_5s5zBeE#2J4FF_
_ gb0
 2:N   f"s6{*+*= 	 	
 s6{CeU3Z^^%)CDs6{CeU3Z^^%)CDE5> :; 	c&k)**= 	 	
 & 	E%/3SD/2xxdtDLTRVZX]M^abMb$s)E"dBd/2xxdtDLTRVZX]M^abMb$s)E"dBd9<nd6lW[\`WabgWhklWlfe,nInMM

!('$"$
	" JQ EH
  B\_

  B\_2 DC edns   T4(T$#T.:T)	T.T4/T9!>T>&U=U		UU,UU+
U6U
U
U"'U"3
U"
U'U'$
U')T.Ur(   c                 2   |j                   |j                  dk7  ddf   } ||      }t        ||j                  d         } ||      }	t	        j
                  |	|d      }
t        j                  dt        |
d         dz  dz   d      }t        t        |
d   |            }t               }|j                         D ]  \  }}|g||<    t        t        |j                  |j                              }g }t        |
d	         D ]  \  }}||d      }||d
      }t        |      dk(  rt        |t               r@|d    ddj#                  t%        t        | j&                  |   |d             dd       z   }n| j(                  "|r | j(                  |d   | j*                  z      }ndj#                  | j-                  |d         D cg c]  \  }}|	 c}}dd       }n[|j                         D ]H  \  }}t/        |      t/        |      k(  s|j                   |j                  |k(  df   j0                  d   }J t        |      dk(  rt        |t               r@|d    ddj#                  t%        t        | j&                  |   |d             dd       z   }n| j(                  "|r | j(                  |d   | j*                  z      }ndj#                  | j-                  |d         D cg c]  \  }}|	 c}}dd       }n[|j                         D ]H  \  }}t/        |      t/        |      k(  s|j                   |j                  |k(  df   j0                  d   }J |j3                  ddg       |d   |d
   z   d
z  }||z   ||<    |S c c}}w c c}}w )a  Get annotations by replicating linkage function calculation in scipy.

    Arguments:
        topic_model: A fitted BERTopic instance.
        hierarchical_topics: A dataframe that contains a hierarchy of topics
                             represented by their parents and their children.
                             NOTE: The hierarchical topic names are only visualized
                             if both `topics` and `top_n_topics` are not set.
        embeddings: The c-TF-IDF matrix on which to model the hierarchy
        linkage_function: The linkage function to use. Default is:
                          `lambda x: sch.linkage(x, 'ward', optimal_ordering=True)`
                          NOTE: Make sure to use the same `linkage_function` as used
                          in `topic_model.hierarchical_topics`.
        distance_function: The distance function to use on the c-TF-IDF matrix. Default is:
                           `lambda x: 1 - cosine_similarity(x)`.
                            You can pass any function that returns either a square matrix of
                            shape (n_samples, n_samples) with zeros on the diagonal and
                            non-negative values or condensed distance matrix of shape
                            (n_samples * (n_samples - 1) / 2,) containing the upper
                            triangular of the distance matrix.
                           NOTE: Make sure to use the same `distance_function` as used
                           in `topic_model.hierarchical_topics`.
        orientation: The orientation of the figure.
                     Either 'left' or 'bottom'
        custom_labels: Whether to use custom topic labels that were defined using
                       `topic_model.set_topic_labels`.
                       NOTE: Custom labels are only generated for the original
                       un-merged topics.

    Returns:
        text_annotations: Annotations to be used within Plotly's `ff.create_dendogram`
    TopNr   T)r   no_plotrP   leaves
   icoord   r   r2   rR   Parent_Name )rZ   r   r   r*   r$   
dendrogramra   arangere   rs   zipitems	Parent_IDTopics	enumerateri   rj   rm   nextrl   rn   rp   rq   setvaluesappend)r'   r   r(   r   r   r   r   dfXZPx_ticksx_topic
topic_valskeyvalparent_topictext_annotationsrb   r   	fst_topic
scnd_topicfst_namewordr2   value	scnd_namer7   s                               r   rf   rf      s   R 
	 	 !4!@!@E!I1!L	MB 	*%A J$4$4Q$78A 	Aqk4@A ii3q{+b014b9G3q{G,-GJMMO  S%
3  BLL"))45L !!H+. #4uuQx(	a)
y>Q--'l^1-k88G	RSUVWXZYZ[1  ++7M&55il[EZEZ6Z[889N9NyYZ|9\$]gdAT$]^`_`$ab*002 T
Uu:Y/!vvbllc&9=&HIPPQRSHT z?a--)!}oQ/#((k88G
STVWXY[Z[\3 	 ++7M'66z!}{G\G\7\]	HH+:O:OPZ[\P]:^%_wtQd%_`bab%cd	*002 U
Uu:Z0 "r||s':M'I J Q QRS TIU 	2r9 =>(U1X%*&3
6G#4J 3 %^ &`s   	N*N)r.   NNTFz<b>Hierarchical Clustering</b>i  iX  NNNr   )F) numpyra   pandaspdtypingr   r   r   scipy.sparser   scipy.clusterr   r$   sklearn.metrics.pairwiser	   bertopic._utilsr
   plotly.graph_objectsgraph_objectsrw   plotly.figure_factoryfigure_factoryrg   r   rj   ro   bool	DataFramendarrayFigurer   rf    r    r   <module>r      s     ( ( # * 6 7 ! " 4
 ##&+1(,BFCGSS IS *	S
 S s#S S S S S 
|RZZ784?S  j 89D@S S YYSz  dd d 
|RZZ78	d
  j 89d d d 
$s)_dr    