docs: def _add_data(self, plotter_cls, filename_or_obj, fmt={}, make_plot=True,
                    draw=False, mf_mode=False, ax=None, engine=None, delete=True,
                    share=False, clear=False, enable_post=None,
                    concat_dim=_concat_dim_default, load=False,
                    *args, **kwargs):
          """
          Extract data from a dataset and visualize it with the given plotter
  
          Parameters
          ----------
          plotter_cls: type
              The subclass of :class:`psyplot.plotter.Plotter` to use for
              visualization
          filename_or_obj: filename, :class:`xarray.Dataset` or data store
              The object (or file name) to open. If not a dataset, the
              :func:`psyplot.data.open_dataset` will be used to open a dataset
          fmt: dict
              Formatoptions that shall be when initializing the plot (you can
              however also specify them as extra keyword arguments)
          make_plot: bool
              If True, the data is plotted at the end. Otherwise you have to
              call the :meth:`psyplot.plotter.Plotter.initialize_plot` method or
              the :meth:`psyplot.plotter.Plotter.reinit` method by yourself
          %(InteractiveBase.start_update.parameters.draw)s
          mf_mode: bool
              If True, the :func:`psyplot.open_mfdataset` method is used.
              Otherwise we use the :func:`psyplot.open_dataset` method which can
              open only one single dataset
          ax: None, tuple (x, y[, z]) or (list of) matplotlib.axes.Axes
              Specifies the subplots on which to plot the new data objects.
  
              - If None, a new figure will be created for each created plotter
              - If tuple (x, y[, z]), `x` specifies the number of rows, `y` the
                number of columns and the optional third parameter `z` the
                maximal number of subplots per figure.
              - If :class:`matplotlib.axes.Axes` (or list of those, e.g. created
                by the :func:`matplotlib.pyplot.subplots` function), the data
                will be plotted on these subplots
          %(open_dataset.parameters.engine)s
          %(multiple_subplots.parameters.delete)s
          share: bool, fmt key or list of fmt keys
              Determines whether the first created plotter shares it's
              formatoptions with the others. If True, all formatoptions are
              shared. Strings or list of strings specify the keys to share.
          clear: bool
              If True, axes are cleared before making the plot. This is only
              necessary if the `ax` keyword consists of subplots with projection
              that differs from the one that is needed
          enable_post: bool
              If True, the :attr:`~psyplot.plotter.Plotter.post` formatoption is
              enabled and post processing scripts are allowed. If ``None``, this
              parameter is set to True if there is a value given for the `post`
              formatoption in `fmt` or `kwargs`
          %(xarray.open_mfdataset.parameters.concat_dim)s
              This parameter only does have an effect if `mf_mode` is True.
          load: bool
              If True, load the complete dataset into memory before plotting.
              This might be useful if the data of other variables in the dataset
              has to be accessed multiple times, e.g. for unstructured grids.
          %(ArrayList.from_dataset.parameters.no_base)s
  
          Other Parameters
          ----------------
          %(ArrayList.from_dataset.other_parameters.no_args_kwargs)s
          ``**kwargs``
              Any other dimension or formatoption that shall be passed to `dims`
              or `fmt` respectively.
  
          Returns
          -------
          Project
              The subproject that contains the new (visualized) data array"""
          if not isinstance(filename_or_obj, xarray.Dataset):
              if mf_mode:
                  filename_or_obj = open_mfdataset(filename_or_obj,
                                                   engine=engine,
                                                   concat_dim=concat_dim)
              else:
                  filename_or_obj = open_dataset(filename_or_obj,
                                                 engine=engine)
          if load:
              old = filename_or_obj
              filename_or_obj = filename_or_obj.load()
              old.close()
  
          fmt = dict(fmt)
          possible_fmts = list(plotter_cls._get_formatoptions())
          additional_fmt, kwargs = utils.sort_kwargs(
              kwargs, possible_fmts)
          fmt.update(additional_fmt)
          if enable_post is None:
              enable_post = bool(fmt.get('post'))
          # create the subproject
          sub_project = self.from_dataset(filename_or_obj, **kwargs)
          sub_project.main = self
          sub_project.no_auto_update = not (
              not sub_project.no_auto_update or not self.no_auto_update)
          # create the subplots
          proj = plotter_cls._get_sample_projection()
          if isinstance(ax, tuple):
              axes = iter(multiple_subplots(
                  *ax, n=len(sub_project), subplot_kw={'projection': proj}))
          elif ax is None or isinstance(ax, (mpl.axes.SubplotBase,
                                             mpl.axes.Axes)):
              axes = repeat(ax)
          else:
              axes = iter(ax)
          clear = clear or (isinstance(ax, tuple) and proj is not None)
          for arr in sub_project:
              plotter_cls(arr, make_plot=(not bool(share) and make_plot),
                          draw=False, ax=next(axes), clear=clear,
                          project=self, enable_post=enable_post, **fmt)
          if share:
              if share is True:
                  share = possible_fmts
              elif isinstance(share, six.string_types):
                  share = [share]
              else:
                  share = list(share)
              sub_project[0].psy.plotter.share(
                  [arr.psy.plotter for arr in sub_project[1:]], keys=share,
                  draw=False)
              if make_plot:
                  for arr in sub_project:
                      arr.psy.plotter.reinit(draw=False, clear=clear)
          if draw is None:
              draw = rcParams['auto_draw']
          if draw:
              sub_project.draw()
              if rcParams['auto_show']:
                  self.show()
          self.extend(sub_project, new_name=True)
          if self is gcp(True):
              scp(sub_project)
          return sub_project