docs: def load_project(cls, fname, auto_update=None, make_plot=True,
                       draw=False, alternative_axes=None, main=False,
                       encoding=None, enable_post=False, new_fig=True,
                       clear=None, **kwargs):
          """
          Load a project from a file or dict
  
          This classmethod allows to load a project that has been stored using
          the :meth:`save_project` method and reads all the data and creates the
          figures.
  
          Since the data is stored in external files when saving a project,
          make sure that the data is accessible under the relative paths
          as stored in the file `fname` or from the current working directory
          if `fname` is a dictionary. Alternatively use the `alternative_paths`
          parameter or the `pwd` parameter
  
          Parameters
          ----------
          fname: str or dict
              The string might be the path to a file created with the
              :meth:`save_project` method, or it might be a dictionary from this
              method
          %(InteractiveBase.parameters.auto_update)s
          %(Project._add_data.parameters.make_plot)s
          %(InteractiveBase.start_update.parameters.draw)s
          alternative_axes: dict, None or list
              alternative axes instances to use
  
              - If it is None, the axes and figures from the saving point will be
                reproduced.
              - a dictionary should map from array names in the created
                project to matplotlib axes instances
              - a list should contain axes instances that will be used for
                iteration
          main: bool, optional
              If True, a new main project is created and returned.
              Otherwise (by default default) the data is added to the current
              main project.
          encoding: str
              The encoding to use for loading the project. If None, it is
              automatically determined by pickle. Note: Set this to ``'latin1'``
              if using a project created with python2 on python3.
          enable_post: bool
              If True, the :attr:`~psyplot.plotter.Plotter.post` formatoption is
              enabled and post processing scripts are allowed. Do only set this
              parameter to ``True`` if you know you can trust the information in
              `fname`
          new_fig: bool
              If True (default) and `alternative_axes` is None, new figures are
              created if the figure already exists
          %(Project._add_data.parameters.clear)s
          pwd: str or None, optional
              Path to the working directory from where the data can be imported.
              If None and `fname` is the path to a file, `pwd` is set to the
              directory of this file. Otherwise the current working directory is
              used.
          %(ArrayList.from_dict.parameters.no_d|pwd)s
  
          Other Parameters
          ----------------
          %(ArrayList.from_dict.parameters)s
  
          Returns
          -------
          Project
              The project in state of the saving point"""
          from pkg_resources import iter_entry_points
  
          def get_ax_base(name, alternatives):
              ax_base = next(iter(obj(arr_name=name).axes), None)
              if ax_base is None:
                  ax_base = next(iter(obj(arr_name=alternatives).axes), None)
              if ax_base is not None:
                  alternatives.difference_update(obj(ax=ax_base).arr_names)
              return ax_base
  
          pwd = kwargs.pop('pwd', None)
          if isinstance(fname, six.string_types):
              with open(fname, 'rb') as f:
                  pickle_kws = {} if not encoding else {'encoding': encoding}
                  d = pickle.load(f, **pickle_kws)
              pwd = pwd or os.path.dirname(fname)
          else:
              d = dict(fname)
              pwd = pwd or getcwd()
          # check for patches of plugins
          for ep in iter_entry_points('psyplot', name='patches'):
              patches = ep.load()
              for arr_d in d.get('arrays').values():
                  plotter_cls = arr_d.get('plotter', {}).get('cls')
                  if plotter_cls is not None and plotter_cls in patches:
                      # apply the patch
                      patches[plotter_cls](arr_d['plotter'],
                                           d.get('versions', {}))
          fig_map = {}
          if alternative_axes is None:
              for fig_dict in six.itervalues(d.get('figs', {})):
                  orig_num = fig_dict.get('num') or 1
                  fig_map[orig_num] = _ProjectLoader.load_figure(
                      fig_dict, new_fig=new_fig).number
          elif not isinstance(alternative_axes, dict):
              alternative_axes = cycle(iter(alternative_axes))
          obj = cls.from_dict(d['arrays'], pwd=pwd, **kwargs)
          if main:
              # we create a new project with the project factory to make sure
              # that everything is handled correctly
              obj = project(None, obj)
          axes = {}
          arr_names = obj.arr_names
          sharex = defaultdict(set)
          sharey = defaultdict(set)
          for arr, (arr_name, arr_dict) in zip(
                  obj, filter(lambda t: t[0] in arr_names,
                              six.iteritems(d['arrays']))):
              if not arr_dict.get('plotter'):
                  continue
              plot_dict = arr_dict['plotter']
              plotter_cls = getattr(
                  import_module(plot_dict['cls'][0]), plot_dict['cls'][1])
              ax = None
              if alternative_axes is not None:
                  if isinstance(alternative_axes, dict):
                      ax = alternative_axes.get(arr.arr_name)
                  else:
                      ax = next(alternative_axes, None)
              if ax is None and 'ax' in plot_dict:
                  already_opened = plot_dict['ax'].get(
                      'shared', set()).intersection(axes)
                  if already_opened:
                      ax = axes[next(iter(already_opened))]
                  else:
                      plot_dict['ax'].pop('shared', None)
                      plot_dict['ax']['fig'] = fig_map[
                          plot_dict['ax'].get('fig') or 1]
                      if plot_dict['ax'].get('sharex'):
                          sharex[plot_dict['ax'].pop('sharex')].add(
                              arr.psy.arr_name)
                      if plot_dict['ax'].get('sharey'):
                          sharey[plot_dict['ax'].pop('sharey')].add(
                              arr.psy.arr_name)
                      axes[arr.psy.arr_name] = ax = _ProjectLoader.load_axes(
                          plot_dict['ax'])
              plotter_cls(
                  arr, make_plot=False, draw=False, clear=False,
                  ax=ax, project=obj.main, enable_post=enable_post,
                  **plot_dict['fmt'])
          # handle shared x and y-axes
          for key, names in sharex.items():
              ax_base = get_ax_base(key, names)
              if ax_base is not None:
                  ax_base.get_shared_x_axes().join(
                      ax_base, *obj(arr_name=names).axes)
                  for ax in obj(arr_name=names).axes:
                      ax._sharex = ax_base
          for key, names in sharey.items():
              ax_base = get_ax_base(key, names)
              if ax_base is not None:
                  ax_base.get_shared_y_axes().join(
                      ax_base, *obj(arr_name=names).axes)
                  for ax in obj(arr_name=names).axes:
                      ax._sharey = ax_base
          for arr in obj.with_plotter:
              shared = d['arrays'][arr.psy.arr_name]['plotter'].get('shared', {})
              for key, arr_names in six.iteritems(shared):
                  arr.psy.plotter.share(obj(arr_name=arr_names).plotters,
                                        keys=[key])
          if make_plot:
              for plotter in obj.plotters:
                  plotter.reinit(
                      draw=False,
                      clear=clear or (
                          clear is None and
                          plotter_cls._get_sample_projection() is not None))
              if draw is None:
                  draw = rcParams['auto_draw']
              if draw:
                  obj.draw()
                  if rcParams['auto_show']:
                      obj.show()
          if auto_update is None:
              auto_update = rcParams['lists.auto_update']
          if not main:
              obj._main = gcp(True)
              obj.main.extend(obj, new_name=True)
          obj.no_auto_update = not auto_update
          scp(obj)
          return obj