code: def create_trend_clustering_graph(top_n):
      if (
          "Trend Clustering" not in gd["reports"].values
      ):  # no clustering data
          return None
      header = gd["reports"][5]
      scatter_series_pos = gd[
          (gd["x_tre"] != -1)
          & (gd["x_tre"].notna())
          & (gd["change"] > 0)
      ]
      scatter_series_neg = gd[
          (gd["x_tre"] != -1)
          & (gd["x_tre"].notna())
          & (gd["change"] < 0)
      ]
      hot_phrases = scatter_series_pos["trends"].values
      cold_phrases = scatter_series_neg["trends"].values
      hot_change = scatter_series_pos["change"].values
      cold_change = scatter_series_neg["change"].values
      hot_x_t = scatter_series_pos["x_tre"].values
      cold_x_t = scatter_series_neg["x_tre"].values
      hot_y_t = scatter_series_pos["y_tre"].values
      cold_y_t = scatter_series_neg["y_tre"].values
      phrases_h, changes_h, x_h, y_h, hover_data_h = [], [], [], [], []
      phrases_c, changes_c, x_c, y_c, hover_data_c = [], [], [], [], []
      opacity_h, opacity_c = [], []
      hot, cold = 0, 0  # counters for each list
      opacity_norm = 1
      if len(hot_change) > 0 and len(cold_change) > 0:
          highest_change = max(hot_change[0], abs(cold_change[0]))
          opacity_norm = (
              1 / (highest_change) if highest_change != 0 else 0.05
          )
  
      for i in range(len(hot_phrases)):
          if hot == top_n:
              break
          phrase = hot_phrases[i]
          change = float(hot_change[i])
          if phrase in white_list:
              phrases_h.append(phrase)
              changes_h.append(change)
              x_h.append(hot_x_t[i])
              y_h.append(hot_y_t[i])
              hover_data_h.append(phrase)
              opacity = opacity_norm * abs(change)
              opacity_h.append(opacity if opacity > 0.05 else 0.05)
              hot += 1
  
      for j in range(len(cold_phrases)):
          if cold == top_n:
              break
          phrase = cold_phrases[j]
          change = float(cold_change[j])
          if phrase in white_list:
              phrases_c.append(phrase)
              changes_c.append(change)
              x_c.append(cold_x_t[j])
              y_c.append(cold_y_t[j])
              hover_data_c.append(phrase)
              opacity = opacity_norm * abs(change)
              opacity_c.append(opacity if opacity > 0.05 else 0.05)
              cold += 1
  
      opacities = []
      colors = []
      # hot:
      for i in range(len(x_h)):
          opacities.append(opacity_h[i])
          colors.append("#4c823d")
      # cold:
      for i in range(len(x_c)):
          opacities.append(opacity_c[i])
          colors.append("#d6400a")
  
      source = ColumnDataSource(
          data=dict(
              x=x_h + x_c,
              y=y_h + y_c,
              topic=hover_data_h + hover_data_c,
              opacities=opacities,
              colors=colors,
          )
      )
      p = figure(
          title=header,
          plot_width=600,
          plot_height=400,
          tooltips="@topic",
      )
      p.circle(
          x="x",
          y="y",
          size=13,
          color="colors",
          alpha="opacities",
          source=source,
      )
      return p
  
imports: import csv
  import logging
  import time
  from os import path
  from os.path import isfile
  import pandas
  from bokeh.io import curdoc
  from bokeh.layouts import column, layout, WidgetBox
  from bokeh.models import ColumnDataSource, Div, Row, ranges, LabelSet, CDSView, IndexFilter
  from bokeh.models.widgets import DataTable, TableColumn, RadioGroup, Dropdown, Tabs, Panel, TextInput, Button, Slider
  from bokeh.plotting import figure
  from trend_analysis import analyze
  from nlp_architect import LIBRARY_OUT
label_desc: Use image node_id 19 for calling a global function with example usage: create_trend_clustering_graph(top_n) and returns: p, None