docs: def setup_coords(arr_names=None, sort=[], dims={}, **kwargs):
      """
      Sets up the arr_names dictionary for the plot
  
      Parameters
      ----------
      arr_names: string, list of strings or dictionary
          Set the unique array names of the resulting arrays and (optionally)
          dimensions.
  
          - if string: same as list of strings (see below). Strings may
            include {0} which will be replaced by a counter.
          - list of strings: those will be used for the array names. The final
            number of dictionaries in the return depend in this case on the
            `dims` and ``**furtherdims``
          - dictionary:
            Then nothing happens and an :class:`OrderedDict` version of
            `arr_names` is returned.
      sort: list of strings
          This parameter defines how the dictionaries are ordered. It has no
          effect if `arr_names` is a dictionary (use a
          :class:`~collections.OrderedDict` for that). It can be a list of
          dimension strings matching to the dimensions in `dims` for the
          variable.
      dims: dict
          Keys must be variable names of dimensions (e.g. time, level, lat or
          lon) or 'name' for the variable name you want to choose.
          Values must be values of that dimension or iterables of the values
          (e.g. lists). Note that strings will be put into a list.
          For example dims = {'name': 't2m', 'time': 0} will result in one plot
          for the first time step, whereas dims = {'name': 't2m', 'time': [0, 1]}
          will result in two plots, one for the first (time == 0) and one for the
          second (time == 1) time step.
      ``**kwargs``
          The same as `dims` (those will update what is specified in `dims`)
  
      Returns
      -------
      ~collections.OrderedDict
          A mapping from the keys in `arr_names` and to dictionaries. Each
          dictionary corresponds defines the coordinates of one data array to
          load"""
      try:
          return OrderedDict(arr_names)
      except (ValueError, TypeError):
          # ValueError for cyordereddict, TypeError for collections.OrderedDict
          pass
      if arr_names is None:
          arr_names = repeat('arr{0}')
      elif isstring(arr_names):
          arr_names = repeat(arr_names)
      dims = OrderedDict(dims)
      for key, val in six.iteritems(kwargs):
          dims.setdefault(key, val)
      sorted_dims = OrderedDict()
      if sort:
          for key in sort:
              sorted_dims[key] = dims.pop(key)
          for key, val in six.iteritems(dims):
              sorted_dims[key] = val
      else:
          # make sure, it is first sorted for the variable names
          if 'name' in dims:
              sorted_dims['name'] = None
          for key, val in sorted(dims.items()):
              sorted_dims[key] = val
          for key, val in six.iteritems(kwargs):
              sorted_dims.setdefault(key, val)
      for key, val in six.iteritems(sorted_dims):
          sorted_dims[key] = iter(safe_list(val))
      return OrderedDict([
          (arr_name.format(i), dict(zip(sorted_dims.keys(), dim_tuple)))
          for i, (arr_name, dim_tuple) in enumerate(zip(
              arr_names, product(
                  *map(list, sorted_dims.values()))))])