code: def io_axis_indices(coordmap, axis_id, fix0=True):
      """Return input and output axis index for id `axis_id` in `coordmap`
  
      Parameters
      ----------
      cm : class:`AffineTransform`
          Affine coordinate map instance
      axis_id : int or str
          If int, gives index of *input* axis.  Can be negative, so that -2 refers
          to the second from last input axis. If str, gives name of input *or*
          output axis.   If `axis_id` is a str, it must be unambiguous - if the
          named axis exists in both input and output, and they do not correspond,
          raises a AxisError.  See Raises section for checks
      fix0: bool, optional
          Whether to fix potential 0 column / row in affine
  
      Returns
      -------
      in_index : None or int
          index of input axis that corresponds to `axis_id`
      out_index : None or int
          index of output axis that corresponds to `axis_id`
  
      Raises
      ------
      AxisError: if `axis_id` is a str and does not match any input or output
          coordinate names.
      AxisError: if the named `axis_id` exists in both input and output, and they
          do not correspond.
  
      Examples
      --------
      >>> aff = [[0, 1, 0, 10], [1, 0, 0, 11], [0, 0, 1, 12], [0, 0, 0, 1]]
      >>> cmap = AffineTransform('ijk', 'xyz', aff)
      >>> io_axis_indices(cmap, 0)
      (0, 1)
      >>> io_axis_indices(cmap, 1)
      (1, 0)
      >>> io_axis_indices(cmap, -1)
      (2, 2)
      >>> io_axis_indices(cmap, 'j')
      (1, 0)
      >>> io_axis_indices(cmap, 'y')
      (0, 1)
      """
      in_dims = list(coordmap.function_domain.coord_names)
      out_dims = list(coordmap.function_range.coord_names)
      in_dim, out_dim, is_str = None, None, False
      if isinstance(axis_id, int):  # Integer axis, always input axis
          # Integers are always input indices
          in_dim = axis_id if axis_id >= 0 else len(in_dims) + axis_id
      else:  # Let's hope they are strings
          if axis_id in in_dims:
              in_dim = in_dims.index(axis_id)
          elif axis_id in out_dims:
              out_dim = out_dims.index(axis_id)
          else:
              raise AxisError(
                  f"No input or output dimension with name ({axis_id})"
              )
          is_str = True
      if out_dim is None:
          out_dim = axmap(coordmap, "in2out", fix0=fix0)[in_dim]
          if (
              is_str
              and axis_id in out_dims
              and out_dim != out_dims.index(axis_id)
          ):
              raise AxisError(
                  "Input and output axes with the same name but "
                  "the axes do not appear to correspond"
              )
      elif in_dim is None:
          in_dim = axmap(coordmap, "out2in", fix0=fix0)[out_dim]
      return in_dim, out_dim
  
imports: import warnings
  import numpy
  import numpy.linalg
  from nibabel import io_orientation
  from nibabel.affines import from_matvec, to_matvec
  from .coordinate_system import CoordinateSystem, is_coordsys, safe_dtype
  from .coordinate_system import product
label_desc: Use image node_id 20 for calling a global function with example usage: io_axis_indices(coordmap, axis_id, fix0) and returns: in_dim,  out_dim