code: def _collect_scatter_plot_data(
      x: Tuple[str, NumericExpression],
      y: Tuple[str, NumericExpression],
      fields: Optional[Dict[str, Expression]] = None,
      n_divisions: Optional[int] = None,
      missing_label: str = "NA",
  ) -> pd.DataFrame:
      expressions = dict()
      if fields is not None:
          expressions.update(
              {
                  k: hail.or_else(v, missing_label)
                  if isinstance(v, StringExpression)
                  else v
                  for k, v in fields.items()
              }
          )
  
      if n_divisions is None:
          collect_expr = hail.struct(
              **dict((k, v) for k, v in (x, y)), **expressions
          )
          plot_data = [
              point
              for point in collect_expr.collect()
              if point[x[0]] is not None and point[y[0]] is not None
          ]
          source_pd = pd.DataFrame(plot_data)
      else:
          # FIXME: remove the type conversion logic if/when downsample supports continuous values for labels
          # Save all numeric types to cast in DataFrame
          numeric_expr = {
              k: "int32"
              for k, v in expressions.items()
              if isinstance(v, Int32Expression)
          }
          numeric_expr.update(
              {
                  k: "int64"
                  for k, v in expressions.items()
                  if isinstance(v, Int64Expression)
              }
          )
          numeric_expr.update(
              {
                  k: "float32"
                  for k, v in expressions.items()
                  if isinstance(v, Float32Expression)
              }
          )
          numeric_expr.update(
              {
                  k: "float64"
                  for k, v in expressions.items()
                  if isinstance(v, Float64Expression)
              }
          )
  
          # Cast non-string types to string
          expressions = {
              k: hail.str(v)
              if not isinstance(v, StringExpression)
              else v
              for k, v in expressions.items()
          }
  
          agg_f = x[1]._aggregation_method()
          res = agg_f(
              hail.agg.downsample(
                  x[1],
                  y[1],
                  label=list(expressions.values())
                  if expressions
                  else None,
                  n_divisions=n_divisions,
              )
          )
          source_pd = pd.DataFrame(
              [
                  dict(
                      **{x[0]: point[0], y[0]: point[1]},
                      **(
                          dict(zip(expressions, point[2]))
                          if point[2] is not None
                          else {}
                      ),
                  )
                  for point in res
              ]
          )
          source_pd = source_pd.astype(numeric_expr, copy=False)
  
      return source_pd
  
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 12 for calling a global function with example usage: _collect_scatter_plot_data(x, y, fields, n_divisions, missing_label) and returns: source_pd