code: def inv_ornt_aff(ornt, shape):
      """Affine transform reversing transforms implied in `ornt`
  
      Imagine you have an array ``arr`` of shape `shape`, and you apply the
      transforms implied by `ornt` (more below), to get ``tarr``.
      ``tarr`` may have a different shape ``shape_prime``.  This routine
      returns the affine that will take a array coordinate for ``tarr``
      and give you the corresponding array coordinate in ``arr``.
  
      Parameters
      ----------
      ornt : (p, 2) ndarray
         orientation transform. ``ornt[P, 1]` is flip of axis N of the array
         implied by `shape`, where 1 means no flip and -1 means flip.  For
         example, if ``P==0`` and ``ornt[0, 1] == -1``, and there's an array
         ``arr`` of shape `shape`, the flip would correspond to the effect of
         ``np.flipud(arr)``.  ``ornt[:,0]`` gives us the (reverse of the)
         transpose that has been done to ``arr``.  If there are any NaNs in
         `ornt`, we raise an ``OrientationError`` (see notes)
      shape : length p sequence
         shape of array you may transform with `ornt`
  
      Returns
      -------
      transform_affine : (p + 1, p + 1) ndarray
         An array ``arr`` (shape `shape`) might be transformed according to
         `ornt`, resulting in a transformed array ``tarr``.  `transformed_affine`
         is the transform that takes you from array coordinates in ``tarr`` to
         array coordinates in ``arr``.
  
      Notes
      -----
      If a row in `ornt` contains NaN, this means that the input row does not
      influence the output space, and is thus effectively dropped from the output
      space.  In that case one ``tarr`` coordinate maps to many ``arr``
      coordinates, we can't invert the transform, and we raise an error
      """
      ornt = np.asarray(ornt)
      if np.any(np.isnan(ornt)):
          raise OrientationError(
              "We cannot invert orientation transform"
          )
      p = ornt.shape[0]
      shape = np.array(shape)[:p]
      # ornt implies a flip, followed by a transpose.   We need the affine
      # that inverts these.  Thus we need the affine that first undoes the
      # effect of the transpose, then undoes the effects of the flip.
      # ornt indicates the transpose that has occurred to get the current
      # ordering, relative to canonical, so we just use that.
      # undo_reorder is a row permutatation matrix
      axis_transpose = [int(v) for v in ornt[:, 0]]
      undo_reorder = np.eye(p + 1)[axis_transpose + [p], :]
      undo_flip = np.diag(list(ornt[:, 1]) + [1.0])
      center_trans = -(shape - 1) / 2.0
      undo_flip[:p, p] = (ornt[:, 1] * center_trans) - center_trans
      return np.dot(undo_flip, undo_reorder)
  
file_path: nibabel/nibabel/orientations.py
imports: import numpy
  import numpy.linalg
  from .deprecated import deprecate_with_version
label_desc: Use image node_id 4 for calling a global function with example usage: inv_ornt_aff(ornt, shape) and returns: np