class_docstr: This is a high-level widget for exploring relationships in tabular data.
      
  Given a multi-column record array, the widget displays a scatter plot of a
  specific subset of the data. Includes controls for selecting the columns to
  plot, filtering data, and determining symbol color and shape.
  
  The widget consists of four components:
  
  1) A list of column names from which the user may select 1 or 2 columns
     to plot. If one column is selected, the data for that column will be
     plotted in a histogram-like manner by using :func:`pseudoScatter()
     <pyqtgraph.pseudoScatter>`. If two columns are selected, then the
     scatter plot will be generated with x determined by the first column
     that was selected and y by the second.
  2) A DataFilter that allows the user to select a subset of the data by 
     specifying multiple selection criteria.
  3) A ColorMap that allows the user to determine how points are colored by
     specifying multiple criteria.
  4) A PlotWidget for displaying the data.
code: def updatePlot(self):
      self.plot.clear()
      if self.data is None or len(self.data) == 0:
          return
  
      if self.filtered is None:
          mask = self.filter.generateMask(self.data)
          self.filtered = self.data[mask]
          self.filteredIndices = self.indices[mask]
      data = self.filtered
      if len(data) == 0:
          return
  
      colors = np.array(
          [fn.mkBrush(*x) for x in self.colorMap.map(data)]
      )
  
      style = self.style.copy()
  
      ## Look up selected columns and units
      sel = list(
          [str(item.text()) for item in self.fieldList.selectedItems()]
      )
      units = list(
          [
              item.opts.get("units", "")
              for item in self.fieldList.selectedItems()
          ]
      )
      if len(sel) == 0:
          self.plot.setTitle("")
          return
  
      if len(sel) == 1:
          self.plot.setLabels(
              left=("N", ""), bottom=(sel[0], units[0]), title=""
          )
          if len(data) == 0:
              return
          # x = data[sel[0]]
          # y = None
          xy = [data[sel[0]], None]
      elif len(sel) == 2:
          self.plot.setLabels(
              left=(sel[1], units[1]), bottom=(sel[0], units[0])
          )
          if len(data) == 0:
              return
  
          xy = [data[sel[0]], data[sel[1]]]
          # xydata = []
          # for ax in [0,1]:
          # d = data[sel[ax]]
          ### scatter catecorical values just a bit so they show up better in the scatter plot.
          ##if sel[ax] in ['MorphologyBSMean', 'MorphologyTDMean', 'FIType']:
          ##d += np.random.normal(size=len(cells), scale=0.1)
  
          # xydata.append(d)
          # x,y = xydata
  
      ## convert enum-type fields to float, set axis labels
      enum = [False, False]
      for i in [0, 1]:
          axis = self.plot.getAxis(["bottom", "left"][i])
          if xy[i] is not None and (
              self.fields[sel[i]].get("mode", None) == "enum"
              or xy[i].dtype.kind in ("S", "O")
          ):
              vals = self.fields[sel[i]].get("values", list(set(xy[i])))
              xy[i] = np.array(
                  [
                      vals.index(x) if x in vals else len(vals)
                      for x in xy[i]
                  ],
                  dtype=float,
              )
              axis.setTicks([list(enumerate(vals))])
              enum[i] = True
          else:
              axis.setTicks(None)  # reset to automatic ticking
  
      ## mask out any nan values
      mask = np.ones(len(xy[0]), dtype=bool)
      if xy[0].dtype.kind == "f":
          mask &= np.isfinite(xy[0])
      if xy[1] is not None and xy[1].dtype.kind == "f":
          mask &= np.isfinite(xy[1])
  
      xy[0] = xy[0][mask]
      style["symbolBrush"] = colors[mask]
      data = data[mask]
      indices = self.filteredIndices[mask]
  
      ## Scatter y-values for a histogram-like appearance
      if xy[1] is None:
          ## column scatter plot
          xy[1] = fn.pseudoScatter(xy[0])
      else:
          ## beeswarm plots
          xy[1] = xy[1][mask]
          for ax in [0, 1]:
              if not enum[ax]:
                  continue
              imax = int(xy[ax].max()) if len(xy[ax]) > 0 else 0
              for i in range(imax + 1):
                  keymask = xy[ax] == i
                  scatter = fn.pseudoScatter(
                      xy[1 - ax][keymask], bidir=True
                  )
                  if len(scatter) == 0:
                      continue
                  smax = np.abs(scatter).max()
                  if smax != 0:
                      scatter *= 0.2 / smax
                  xy[ax][keymask] += scatter
  
      if self.scatterPlot is not None:
          try:
              self.scatterPlot.sigPointsClicked.disconnect(
                  self.plotClicked
              )
          except:
              pass
  
      self._visibleXY = xy
      self._visibleData = data
      self._visibleIndices = indices
      self._indexMap = None
      self.scatterPlot = self.plot.plot(
          xy[0], xy[1], data=data, **style
      )
      self.scatterPlot.sigPointsClicked.connect(self.plotClicked)
      self.scatterPlot.sigPointsHovered.connect(self.plotHovered)
      self.updateSelected()
  
imports: from collections import OrderedDict
  import numpy
  from ..None import functions
  from ..None import getConfigOption
  from ..None import parametertree
  from ..graphicsItems.TextItem import TextItem
  from ..Qt import QtCore, QtWidgets
  from .ColorMapWidget import ColorMapParameter
  from .DataFilterWidget import DataFilterParameter
  from .PlotWidget import PlotWidget
label_desc: Use image node_id 9 for calling the ScatterPlotWidget obj's underlying member method code with example usage: obj.updatePlot() without return types