class_docstr: Class that manages communication between a
  :class:`fiftyone.core.session.Session` and one or more
  :class:`fiftyone.core.plots.base.ResponsivePlot` instances.
  
  Each plot can be linked to either the view, samples, frames, or labels of a
  session:
  
  -   **View links:** When a plot has ``link_type == "view"``, then, when the
      session's view changes, the plot is updated based on the content of the
      view
  
  -   **Sample links:** When points are selected in a plot with
      ``link_type == "samples"``, a view containing the corresponding samples
      is loaded in the App. Conversely, when the session's view changes, the
      corresponding points are selected in the plot
  
  -   **Frame links:** When points are selected in a plot with
      ``link_type == "frames"``, a view containing the corresponding frames
      is loaded in the App. Conversely, when the session's view changes, the
      corresponding points are selected in the plot
  
  -   **Label links:** When points are selected in a plot with
      ``link_type == "labels"``, a view containing the corresponding labels
      is loaded in the App. Conversely, when the session's view changes, the
      points in the plot corresponding to all labels in the view are selected
      in the plot
  
  Args:
      session: a :class:`fiftyone.core.session.Session`
class_docstr_tok: ["Class","that","manages","communication","between","a",":","class",":","`","fiftyone.core.session.Session","`","and","one","or","more",":","class",":","`","fiftyone.core.plots.base.ResponsivePlot","`","instances",".","Each","plot","can","be","linked","to","either","the","view",",","samples",",","frames",",","or","labels","of","a","session",":","-","*","*","View","links",":","*","*","When","a","plot","has","``","link_type","==","``","view","''","``",",","then",",","when","the","session","'s","view","changes",",","the","plot","is","updated","based","on","the","content","of","the","view","-","*","*","Sample","links",":","*","*","When","points","are","selected","in","a","plot","with","``","link_type","==","``","samples","''","``",",","a","view","containing","the","corresponding","samples","is","loaded","in","the","App",".","Conversely",",","when","the","session","'s","view","changes",",","the","corresponding","points","are","selected","in","the","plot","-","*","*","Frame","links",":","*","*","When","points","are","selected","in","a","plot","with","``","link_type","==","``","frames","''","``",",","a","view","containing","the","corresponding","frames","is","loaded","in","the","App",".","Conversely",",","when","the","session","'s","view","changes",",","the","corresponding","points","are","selected","in","the","plot","-","*","*","Label","links",":","*","*","When","points","are","selected","in","a","plot","with","``","link_type","==","``","labels","''","``",",","a","view","containing","the","corresponding","labels","is","loaded","in","the","App",".","Conversely",",","when","the","session","'s","view","changes",",","the","points","in","the","plot","corresponding","to","all","labels","in","the","view","are","selected","in","the","plot","Args",":","session",":","a",":","class",":","`","fiftyone.core.session.Session","`"]
code: def _on_plot_selection(self, name, ids):
      plot = self._plots[name]
  
      if not plot.is_connected:
          return
  
      if not self._ready_for_update(name):
          return
  
      if plot.init_view is not None:
          plot_view = plot.init_view.view()
      else:
          plot_view = self._session.dataset.view()
  
      sample_ids = None
      frame_ids = None
      labels = None
  
      if ids is None:
          # Plot is in default state
          pass
      elif plot.link_type == "samples":
          # Update `plot_view` to only contain the right content
          if isinstance(
              plot_view,
              (fop.PatchesView, fov.FramesView, foc.ClipsView),
          ):
              # Create a view that only contains the selected samples
              plot_view = plot_view.select_by("sample_id", ids)
          else:
              # Create a view that only contains the selected samples
              plot_view = plot_view.select(ids)
  
          # This plot is linked to samples, so we already know exactly which
          # IDs to use
          sample_ids = ids
  
          # If the session has plots linked to frames, retrieve the current
          # frame IDs
          if self.has_frame_links:
              if isinstance(plot_view, fov.FramesView):
                  frame_ids = plot_view.values("id")
              elif plot_view._contains_videos():
                  frame_ids = plot_view.values("frames.id", unwind=True)
  
          # If the session has plots linked to labels, retrieve the current
          # label IDs
          if self.has_label_links:
              labels = plot_view._get_selected_labels()
      elif plot.link_type == "frames":
          # Update `plot_view` to only contain the right content
          if isinstance(plot_view, fov.FramesView):
              # Create a view that only contains the selected frames
              plot_view = plot_view.select(ids)
          elif plot.selection_mode == "select":
              # Create a view that only contains the selected frames
              plot_view = plot_view.select_frames(ids)
          elif plot.selection_mode == "match":
              # Create a view that only contains unfiltered samples with at
              # least one selected frame
              _ids = [ObjectId(_id) for _id in ids]
              plot_view = plot_view.match(
                  F("frames._id").contains(_ids)
              )
          elif plot.selection_mode == "frames":
              # We shouldn't actually get here, since `plot_view` should have
              # been a `FramesView`
              _ids = [ObjectId(_id) for _id in ids]
              plot_view = plot_view.match(
                  F("frames._id").contains(_ids)
              )
          else:
              raise ValueError(
                  "Unsupported `selection_mode=%s`"
                  % plot.selection_mode
              )
  
          # If the session has plots linked to samples, retrieve the current
          # sample IDs
          if self.has_sample_links:
              if isinstance(plot_view, fov.FramesView):
                  sample_ids = plot_view.values("sample_id")
              else:
                  sample_ids = plot_view.values("id")
  
          # This plot is linked to frames, so we already know exactly which
          # IDs to use
          frame_ids = ids
  
          # If the session has plots linked to labels, retrieve the current
          # label IDs
          if self.has_label_links:
              labels = plot_view._get_selected_labels()
      elif plot.link_type == "labels":
          # Update `plot_view` to only contain the right content
          if plot.selection_mode == "select":
              # Create a view that only contains the selected labels
              plot_view = plot_view.select_labels(
                  ids=ids, fields=plot.label_fields
              )
          elif plot.selection_mode == "match":
              # Create a view that only contains unfiltered samples with at
              # least one selected label
              plot_view = plot_view.match_labels(
                  ids=ids, fields=plot.label_fields
              )
          elif plot.selection_mode == "patches":
              if isinstance(plot_view, fop.PatchesView):
                  # Create a view that only contains the selected labels
                  plot_view = plot_view.select(ids)
              else:
                  # We shouldn't actually get here, since `plot_view` should
                  # have been a `PatchesView`...
                  plot_view = plot_view.match_labels(
                      ids=ids, fields=plot.label_fields
                  )
          else:
              raise ValueError(
                  "Unsupported `selection_mode=%s`"
                  % plot.selection_mode
              )
  
          field = plot.label_fields
          if field is not None and not etau.is_str(field):
              field = None  # multiple fields; unclear which one to use
  
          # If the session has plots linked to samples, retrieve the current
          # sample IDs
          if self.has_sample_links:
              if isinstance(plot_view, fov.FramesView):
                  sample_ids = plot_view.values("sample_id")
              else:
                  sample_ids = plot_view.values("id")
  
          # If the session has plots linked to frames, retrieve the current
          # frame IDs
          if self.has_frame_links:
              if isinstance(plot_view, fov.FramesView):
                  frame_ids = plot_view.values("id")
              elif plot_view._contains_videos():
                  frame_ids = plot_view.values("frames.id", unwind=True)
  
          # This plot is linked to labels, so we already know exactly which
          # IDs to use
          labels = [{"field": field, "label_id": _id} for _id in ids]
      else:
          raise ValueError(
              "Plot '%s' has unsupported link type '%s'"
              % (name, plot.link_type)
          )
  
      self._current_sample_ids = sample_ids
      self._current_frame_ids = frame_ids
      self._current_labels = labels
      self._update_session(plot_view)
      self._update_plots_from_session(exclude=[name])
  
imports: import datetime
  import itertools
  import logging
  from bson import ObjectId
  import eta.core.utils
  import fiftyone.core.clips
  from fiftyone.core.expressions import ViewField
  import fiftyone.core.patches
  import fiftyone.core.video
  from .base import ResponsivePlot, ViewPlot, InteractivePlot
label_desc: Use image node_id 34 for calling the PlotManager obj's underlying member method code with example usage: obj._on_plot_selection(name, ids) without return types