docs: def from_dict(cls, d, alternative_paths={}, datasets=None,
                    pwd=None, ignore_keys=['attrs', 'plotter', 'ds'],
                    only=None, chname={}, **kwargs):
          """
          Create a list from the dictionary returned by :meth:`array_info`
  
          This classmethod creates an :class:`~psyplot.data.ArrayList` instance
          from a dictionary containing filename, dimension infos and array names
  
          Parameters
          ----------
          d: dict
              The dictionary holding the data
          alternative_paths: dict or list or str
              A mapping from original filenames as used in `d` to filenames that
              shall be used instead. If `alternative_paths` is not None,
              datasets must be None. Paths must be accessible from the current
              working directory.
              If `alternative_paths` is a list (or any other iterable) is
              provided, the file names will be replaced as they appear in `d`
              (note that this is very unsafe if `d` is not and OrderedDict)
          datasets: dict or list or None
              A mapping from original filenames in `d` to the instances of
              :class:`xarray.Dataset` to use. If it is an iterable, the same
              holds as for the `alternative_paths` parameter
          pwd: str
              Path to the working directory from where the data can be imported.
              If None, use the current working directory.
          ignore_keys: list of str
              Keys specified in this list are ignored and not seen as array
              information (note that ``attrs`` are used anyway)
          only: string, list or callable
              Can be one of the following three things:
  
              - a string that represents a pattern to match the array names
                that shall be included
              - a list of array names to include
              - a callable with two arguments, a string and a dict such as
  
                .. code-block:: python
  
                    def filter_func(arr_name: str, info: dict): -> bool
                        '''
                        Filter the array names
  
                        This function should return True if the array shall be
                        included, else False
  
                        Parameters
                        ----------
                        arr_name: str
                            The array name (i.e. the ``arr_name`` attribute)
                        info: dict
                            The dictionary with the array informations. Common
                            keys are ``'name'`` that points to the variable name
                            and ``'dims'`` that points to the dimensions and
                            ``'fname'`` that points to the file name
                        '''
                        return True or False
  
                The function should return ``True`` if the array shall be
                included, else ``False``. This function will also be given to
                subsequents instances of :class:`InteractiveList` objects that
                are contained in the returned value
          chname: dict
              A mapping from variable names in the project to variable names
              that should be used instead
  
          Other Parameters
          ----------------
          ``**kwargs``
              Any other parameter from the `psyplot.data.open_dataset` function
          %(open_dataset.parameters)s
  
          Returns
          -------
          psyplot.data.ArrayList
              The list with the interactive objects
  
          See Also
          --------
          from_dataset, array_info"""
          pwd = pwd or getcwd()
          if only is None:
              def only_filter(arr_name, info):
                  return True
          elif callable(only):
              only_filter = only
          elif isstring(only):
              def only_filter(arr_name, info):
                  return patt.search(arr_name) is not None
              patt = re.compile(only)
              only = None
          else:
              def only_filter(arr_name, info):
                  return arr_name in save_only
              save_only = only
              only = None
  
          def get_fname_use(fname):
              squeeze = isstring(fname)
              fname = safe_list(fname)
              ret = tuple(f if utils.is_remote_url(f) or osp.isabs(f) else
                          osp.join(pwd, f)
                          for f in fname)
              return ret[0] if squeeze else ret
  
          def get_name(name):
              if not isstring(name):
                  return list(map(get_name, name))
              else:
                  return chname.get(name, name)
  
          if not isinstance(alternative_paths, dict):
              it = iter(alternative_paths)
              alternative_paths = defaultdict(partial(next, it, None))
          # first open all datasets if not already done
          if datasets is None:
              replace_concat_dim = 'concat_dim' not in kwargs
  
              names_and_stores = cls._get_dsnames(d, concat_dim=True)
              datasets = {}
              for fname, (store_mod, store_cls), concat_dim in names_and_stores:
                  fname_use = fname
                  got = True
                  if replace_concat_dim and concat_dim is not None:
                      kwargs['concat_dim'] = concat_dim
                  elif replace_concat_dim and concat_dim is None:
                      kwargs.pop('concat_dim', None)
                  try:
                      fname_use = alternative_paths[fname]
                  except KeyError:
                      got = False
                  if not got or not fname_use:
                      if fname is not None:
                          fname_use = get_fname_use(fname)
                  if fname_use is not None:
                      datasets[fname] = _open_ds_from_store(
                          fname_use, store_mod, store_cls, **kwargs)
              if alternative_paths is not None:
                  for fname in set(alternative_paths).difference(datasets):
                      datasets[fname] = _open_ds_from_store(fname, **kwargs)
          elif not isinstance(datasets, dict):
              it_datasets = iter(datasets)
              datasets = defaultdict(partial(next, it_datasets, None))
          arrays = [0] * len(d)
          i = 0
          for arr_name, info in six.iteritems(d):
              if arr_name in ignore_keys or not only_filter(arr_name, info):
                  arrays.pop(i)
                  continue
              if not {'fname', 'ds', 'arr'}.intersection(info):
                  # the described object is an InteractiveList
                  arr = InteractiveList.from_dict(
                      info, alternative_paths=alternative_paths,
                      datasets=datasets, chname=chname)
                  if not arr:
                      warn("Skipping empty list %s!" % arr_name)
                      arrays.pop(i)
                      continue
              else:
                  if 'arr' in info:
                      arr = info.pop('arr')
                  elif 'ds' in info:
                      arr = cls.from_dataset(
                          info['ds'], dims=info['dims'],
                          name=get_name(info['name']))[0]
                  else:
                      fname = info['fname']
                      if fname is None:
                          warn("Could not open array %s because no filename was "
                               "specified!" % arr_name)
                          arrays.pop(i)
                          continue
                      try:  # in case, datasets is a defaultdict
                          datasets[fname]
                      except KeyError:
                          pass
                      if fname not in datasets:
                          warn("Could not open array %s because %s was not in "
                               "the list of datasets!" % (arr_name, fname))
                          arrays.pop(i)
                          continue
                      arr = cls.from_dataset(
                          datasets[fname], dims=info['dims'],
                          name=get_name(info['name']))[0]
                  for key, val in six.iteritems(info.get('attrs', {})):
                      arr.attrs.setdefault(key, val)
              arr.psy.arr_name = arr_name
              arrays[i] = arr
              i += 1
          return cls(arrays, attrs=d.get('attrs', {}))