code: def _get_scatter_plot_elements(
      sp: Plot,
      source_pd: pd.DataFrame,
      x_col: str,
      y_col: str,
      label_cols: List[str],
      colors: Optional[Dict[str, ColorMapper]] = None,
      size: int = 4,
      hover_cols: Optional[Set[str]] = None,
  ) -> Union[
      Tuple[
          Plot,
          Dict[str, List[LegendItem]],
          Legend,
          ColorBar,
          Dict[str, ColorMapper],
          List[Renderer],
      ],
      Tuple[Plot, None, None, None, None, None],
  ]:
      if not source_pd.shape[0]:
          print("WARN: No data to plot.")
          return sp, None, None, None, None, None
  
      possible_tooltips = [
          (x_col, f"@{x_col}"),
          (y_col, f"@{y_col}"),
      ] + [
          (c, f"@{c}")
          for c in source_pd.columns
          if c not in [x_col, y_col]
      ]
  
      if hover_cols is not None:
          possible_tooltips = [
              x for x in possible_tooltips if x[0] in hover_cols
          ]
      sp.tools.append(HoverTool(tooltips=possible_tooltips))
  
      cds = ColumnDataSource(source_pd)
  
      if not label_cols:
          sp.circle(x_col, y_col, source=cds, size=size)
          return sp, None, None, None, None, None
      continuous_cols = [
          col
          for col in label_cols
          if (
              str(source_pd.dtypes[col]).startswith("float")
              or str(source_pd.dtypes[col]).startswith("int")
          )
      ]
      factor_cols = [
          col for col in label_cols if col not in continuous_cols
      ]
  
      #  Assign color mappers to columns
      if colors is None:
          colors = {}
      color_mappers: Dict[str, ColorMapper] = {}
  
      for col in continuous_cols:
          low = np.nanmin(source_pd[col])
          if np.isnan(low):
              low = 0
              high = 0
          else:
              high = np.nanmax(source_pd[col])
          color_mappers[col] = (
              colors[col]
              if col in colors
              else LinearColorMapper(
                  palette="Magma256", low=low, high=high
              )
          )
  
      for col in factor_cols:
          if col in colors:
              color_mappers[col] = colors[col]
          else:
              factors = list(set(source_pd[col]))
              color_mappers[col] = _get_categorical_palette(factors)
  
      # Create initial glyphs
      initial_col = label_cols[0]
      initial_mapper = color_mappers[initial_col]
      legend_items: Dict[str, List[LegendItem]] = {}
  
      if not factor_cols:
          all_renderers = [
              sp.circle(
                  x_col,
                  y_col,
                  color=transform(initial_col, initial_mapper),
                  source=cds,
                  size=size,
              )
          ]
  
      else:
          all_renderers = []
          legend_items_by_key_by_factor = {
              col: collections.defaultdict(list) for col in factor_cols
          }
          for key in source_pd.groupby(factor_cols).groups.keys():
              key = key if len(factor_cols) > 1 else [key]
              cds_view = CDSView(
                  filter=IntersectionFilter(
                      operands=[
                          GroupFilter(
                              column_name=factor_cols[i], group=key[i]
                          )
                          for i in range(0, len(factor_cols))
                      ]
                  )
              )
              renderer = sp.circle(
                  x_col,
                  y_col,
                  color=transform(initial_col, initial_mapper),
                  source=cds,
                  view=cds_view,
                  size=size,
              )
              all_renderers.append(renderer)
              for i in range(0, len(factor_cols)):
                  legend_items_by_key_by_factor[factor_cols[i]][
                      key[i]
                  ].append(renderer)
  
          legend_items = {
              factor: [
                  LegendItem(label=key, renderers=renderers)
                  for key, renderers in key_renderers.items()
              ]
              for factor, key_renderers in legend_items_by_key_by_factor.items()
          }
  
      # Add legend / color bar
      legend = (
          Legend(
              visible=False, click_policy="hide", orientation="vertical"
          )
          if initial_col not in factor_cols
          else Legend(
              items=legend_items[initial_col],
              click_policy="hide",
              orientation="vertical",
          )
      )
      color_bar = ColorBar(color_mapper=color_mappers[initial_col])
      if initial_col not in continuous_cols:
          color_bar.visible = False
      sp.add_layout(legend, "left")
      sp.add_layout(color_bar, "left")
  
      return (
          sp,
          legend_items,
          legend,
          color_bar,
          color_mappers,
          all_renderers,
      )
  
imports: import math
  import collections
  import numpy
  import pandas
  import bokeh
  import bokeh.io
  import bokeh.models
  import warnings
  from bokeh.models import HoverTool, ColorBar, LogTicker, LogColorMapper, LinearColorMapper, CategoricalColorMapper, ColumnDataSource, BasicTicker, Plot, CDSView, GroupFilter, IntersectionFilter, Legend, LegendItem, Renderer, CustomJS, Select, Column, Span, DataRange1d, Slope, Label, ColorMapper, GridPlot
  import bokeh.plotting
  import bokeh.palettes
  from bokeh.plotting import figure
  from bokeh.transform import transform
  from bokeh.layouts import gridplot
  from hail.expr import aggregators
  from hail.expr.expressions import Expression, NumericExpression, StringExpression, LocusExpression, Int32Expression, Int64Expression, Float32Expression, Float64Expression, expr_numeric, expr_float64, expr_any, expr_locus, expr_str, raise_unless_row_indexed
  from hail.expr.functions import _error_from_cdf_python
  from hail.typecheck import typecheck, oneof, nullable, sized_tupleof, numeric, sequenceof, dictof
  from hail import Table, MatrixTable
  from hail.utils.struct import Struct
  from hail.utils.java import warning
  from typing import List, Tuple, Dict, Union, Callable, Optional, Sequence, Any, Set
  import hail
label_desc: Use image node_id 14 for calling a global function with example usage: _get_scatter_plot_elements(sp, source_pd, x_col, y_col, label_cols, colors, size, hover_cols) and returns: sp,  legend_items,  legend,  color_bar,  color_mappers,  all_renderers, sp,  None,  None,  None,  None,  None, sp,  None,  None,  None,  None,  None