code: def _plot_scatter(
      points,
      labels=None,
      sizes=None,
      classes=None,
      categorical=False,
      marker_size=None,
      cmap=None,
      ax=None,
      ax_equal=False,
      figsize=None,
      **kwargs,
  ):
      if labels is not None and classes is not None:
          values_map = {c: i for i, c in enumerate(classes)}
          values = np.array([values_map.get(l, -1) for l in labels])
      else:
          values = labels
  
      scatter_3d = points.shape[1] == 3
  
      if ax is None:
          projection = "3d" if scatter_3d else None
          fig = plt.figure()
          ax = fig.add_subplot(111, projection=projection)
      else:
          fig = ax.figure
  
      if cmap is None:
          cmap = (
              "Spectral"
              if categorical
              else _DEFAULT_CONTINUOUS_COLORSCALE
          )
  
      cmap = plt.get_cmap(cmap)
  
      if categorical:
          boundaries = np.arange(0, len(classes) + 1)
          norm = mpl.colors.BoundaryNorm(boundaries, cmap.N)
      else:
          norm = None
  
      if marker_size is None:
          # Choose a reasonable marker size based on number of points
          marker_size = 2.0 * (10 ** (4 - np.log10(points.shape[0])))
          marker_size = max(1, min(marker_size, 50))
  
      if sizes is None:
          if values is not None:
              sizes = np.full(values.shape, marker_size)
          else:
              sizes = marker_size
      else:
          # Scale sizes so that 0.5 * max(sizes) corresponds to `marker_size`
          min_marker_size = min(0.1, marker_size)
          sizeref = 0.5 * max(sizes) / marker_size
          sizes = np.maximum(sizes / sizeref, min_marker_size)
  
      args = [points[:, 0], points[:, 1]]
      if scatter_3d:
          args.append(points[:, 2])
  
      collection = ax.scatter(
          *args,
          c=values,
          s=sizes,
          cmap=cmap,
          norm=norm,
          **kwargs,
      )
  
      if values is not None:
          divider = make_axes_locatable(ax)
          cax = divider.append_axes(
              "right", size="5%", pad=0.1, axes_class=mpl.axes.Axes
          )
  
          if categorical:
              ticks = 0.5 + np.arange(0, len(classes))
              cbar = mpl.colorbar.ColorbarBase(
                  cax,
                  cmap=cmap,
                  norm=norm,
                  spacing="proportional",
                  boundaries=boundaries,
                  ticks=ticks,
              )
              cbar.set_ticklabels(classes)
          else:
              mappable = mpl.cm.ScalarMappable(cmap=cmap, norm=norm)
              mappable.set_array(values)
              fig.colorbar(mappable, cax=cax)
  
      if figsize is not None:
          fig.set_size_inches(*figsize)
  
      if ax_equal:
          collection.axes.axis("equal")
  
      return collection
  
imports: import itertools
  import logging
  import numpy
  import matplotlib
  from matplotlib.widgets import Button, LassoSelector
  from matplotlib.path import Path
  import matplotlib.pyplot
  from mpl_toolkits.axes_grid1 import make_axes_locatable
  from mpl_toolkits.axes_grid1.inset_locator import InsetPosition
  from mpl_toolkits.mplot3d import Axes3D
  import sklearn.metrics.pairwise
  import sklearn.metrics
  import eta.core.utils
  import fiftyone.core.context
  import fiftyone.core.utils
  from .base import InteractivePlot
  from .utils import best_fit_line, load_button_icon, parse_lines_inputs, parse_locations, parse_scatter_inputs
label_desc: Use image node_id 10 for calling a global function with example usage: _plot_scatter(points, labels, sizes, classes, categorical, marker_size, cmap, ax, ax_equal, figsize) and returns: collection