<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 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