class_docstr: Class for affine transformation from domain to a range
  
  This class has an affine attribute, which is a matrix representing
  the affine transformation in homogeneous coordinates.  This matrix
  is used to evaluate the function, rather than having an explicit
  function (as is the case for a CoordinateMap).
  
  Examples
  --------
  >>> inp_cs = CoordinateSystem('ijk')
  >>> out_cs = CoordinateSystem('xyz')
  >>> cm = AffineTransform(inp_cs, out_cs, np.diag([1, 2, 3, 1]))
  >>> cm
  AffineTransform(
     function_domain=CoordinateSystem(coord_names=('i', 'j', 'k'), name='', coord_dtype=float64),
     function_range=CoordinateSystem(coord_names=('x', 'y', 'z'), name='', coord_dtype=float64),
     affine=array([[ 1.,  0.,  0.,  0.],
                   [ 0.,  2.,  0.,  0.],
                   [ 0.,  0.,  3.,  0.],
                   [ 0.,  0.,  0.,  1.]])
  )
  
  >>> cm.affine
  array([[ 1.,  0.,  0.,  0.],
         [ 0.,  2.,  0.,  0.],
         [ 0.,  0.,  3.,  0.],
         [ 0.,  0.,  0.,  1.]])
  >>> cm([1,1,1])
  array([ 1.,  2.,  3.])
  >>> icm = cm.inverse()
  >>> icm([1,2,3])
  array([ 1.,  1.,  1.])
class_docstr_tok: ["Class","for","affine","transformation","from","domain","to","a","range","This","class","has","an","affine","attribute",",","which","is","a","matrix","representing","the","affine","transformation","in","homogeneous","coordinates",".","This","matrix","is","used","to","evaluate","the","function",",","rather","than","having","an","explicit","function","(","as","is","the","case","for","a","CoordinateMap",")",".","Examples","--","--","--","--",">",">",">","inp_cs","=","CoordinateSystem","(","'ijk","'",")",">",">",">","out_cs","=","CoordinateSystem","(","'xyz","'",")",">",">",">","cm","=","AffineTransform","(","inp_cs",",","out_cs",",","np.diag","(","[","1",",","2",",","3",",","1","]",")",")",">",">",">","cm","AffineTransform","(","function_domain=CoordinateSystem","(","coord_names=","(","'","i","'",",","'","j","'",",","'","k","'",")",",","name=","''",",","coord_dtype=float64",")",",","function_range=CoordinateSystem","(","coord_names=","(","'","x","'",",","'","y","'",",","'","z","'",")",",","name=","''",",","coord_dtype=float64",")",",","affine=array","(","[","[","1.",",","0.",",","0.",",","0",".","]",",","[","0.",",","2.",",","0.",",","0",".","]",",","[","0.",",","0.",",","3.",",","0",".","]",",","[","0.",",","0.",",","0.",",","1",".","]","]",")",")",">",">",">","cm.affine","array","(","[","[","1.",",","0.",",","0.",",","0",".","]",",","[","0.",",","2.",",","0.",",","0",".","]",",","[","0.",",","0.",",","3.",",","0",".","]",",","[","0.",",","0.",",","0.",",","1",".","]","]",")",">",">",">","cm","(","[","1,1,1","]",")","array","(","[","1.",",","2.",",","3",".","]",")",">",">",">","icm","=","cm.inverse","(",")",">",">",">","icm","(","[","1,2,3","]",")","array","(","[","1.",",","1.",",","1",".","]",")"]
docstr: Return coordinate map with inverse affine transform or None
  
  Parameters
  ----------
  preserve_dtype : bool
      If False, return affine mapping from inverting the ``affine``.  The
      domain / range dtypes for the inverse may then change as a function
      of the dtype of the inverted ``affine``.  If True, try to invert our
      ``affine``, and see if it can be cast to the needed data type, which
      is ``self.function_domain.coord_dtype``.  We need this dtype in
      order for the inverse to preserve the coordinate system dtypes.
  
  Returns
  -------
  aff_cm_inv : ``AffineTransform`` instance or None
      ``AffineTransform`` mapping from the *range* of input `self` to the
      *domain* of input `self` - the inverse of `self`.  If
      ``self.affine`` was not invertible return None.  If `preserve_dtype`
      is True, and the inverse of ``self.affine`` cannot be cast to
      ``self.function_domain.coord_dtype``, then return None.  Otherwise
      return ``AffineTransform`` inverse mapping.  If `preserve_dtype` is
      False, the domain / range dtypes of the return inverse may well be
      different from those of the input `self`.
  
  Examples
  --------
  >>> input_cs = CoordinateSystem('ijk', coord_dtype=np.int_)
  >>> output_cs = CoordinateSystem('xyz', coord_dtype=np.int_)
  >>> affine = np.array([[1,0,0,1],
  ...                    [0,1,0,1],
  ...                    [0,0,1,1],
  ...                    [0,0,0,1]])
  >>> affine_transform = AffineTransform(input_cs, output_cs, affine)
  >>> affine_transform([2,3,4]) #doctest: +FIX
  array([3, 4, 5])
  
  The inverse transform, by default, generates a floating point inverse
  matrix and therefore floating point output:
  
  >>> affine_transform_inv = affine_transform.inverse()
  >>> affine_transform_inv([2, 6, 12])
  array([  1.,   5.,  11.])
  
  You can force it to preserve the coordinate system dtype with the
  `preserve_dtype` flag:
  
  >>> at_inv_preserved = affine_transform.inverse(preserve_dtype=True)
  >>> at_inv_preserved([2, 6, 12]) #doctest: +FIX
  array([  1,   5,  11])
  
  If you `preserve_dtype`, and there is no inverse affine preserving the
  dtype, the inverse is None:
  
  >>> affine2 = affine.copy()
  >>> affine2[0, 0] = 2 # now inverse can't be integer
  >>> aff_t = AffineTransform(input_cs, output_cs, affine2)
  >>> aff_t.inverse(preserve_dtype=True) is None
  True
docstr_tok: ["Return","coordinate","map","with","inverse","affine","transform","or","None","Parameters","--","--","--","--","--","preserve_dtype",":","bool","If","False",",","return","affine","mapping","from","inverting","the","``","affine","``",".","The","domain","\/","range","dtypes","for","the","inverse","may","then","change","as","a","function","of","the","dtype","of","the","inverted","``","affine","``",".","If","True",",","try","to","invert","our","``","affine","``",",","and","see","if","it","can","be","cast","to","the","needed","data","type",",","which","is","``","self.function_domain.coord_dtype","``",".","We","need","this","dtype","in","order","for","the","inverse","to","preserve","the","coordinate","system","dtypes",".","Returns","--","--","--","-","aff_cm_inv",":","``","AffineTransform","``","instance","or","None","``","AffineTransform","``","mapping","from","the","*","range","*","of","input","`","self","`","to","the","*","domain","*","of","input","`","self","`","-","the","inverse","of","`","self","`",".","If","``","self.affine","``","was","not","invertible","return","None",".","If","`","preserve_dtype","`","is","True",",","and","the","inverse","of","``","self.affine","``","can","not","be","cast","to","``","self.function_domain.coord_dtype","``",",","then","return","None",".","Otherwise","return","``","AffineTransform","``","inverse","mapping",".","If","`","preserve_dtype","`","is","False",",","the","domain","\/","range","dtypes","of","the","return","inverse","may","well","be","different","from","those","of","the","input","`","self","`",".","Examples","--","--","--","--",">",">",">","input_cs","=","CoordinateSystem","(","'ijk","'",",","coord_dtype=np.int_",")",">",">",">","output_cs","=","CoordinateSystem","(","'xyz","'",",","coord_dtype=np.int_",")",">",">",">","affine","=","np.array","(","[","[","1,0,0,1","]",",","...","[","0,1,0,1","]",",","...","[","0,0,1,1","]",",","...","[","0,0,0,1","]","]",")",">",">",">","affine_transform","=","AffineTransform","(","input_cs",",","output_cs",",","affine",")",">",">",">","affine_transform","(","[","2,3,4","]",")","#","doctest",":","+FIX","array","(","[","3",",","4",",","5","]",")","The","inverse","transform",",","by","default",",","generates","a","floating","point","inverse","matrix","and","therefore","floating","point","output",":",">",">",">","affine_transform_inv","=","affine_transform.inverse","(",")",">",">",">","affine_transform_inv","(","[","2",",","6",",","12","]",")","array","(","[","1.",",","5.",",","11",".","]",")","You","can","force","it","to","preserve","the","coordinate","system","dtype","with","the","`","preserve_dtype","`","flag",":",">",">",">","at_inv_preserved","=","affine_transform.inverse","(","preserve_dtype=True",")",">",">",">","at_inv_preserved","(","[","2",",","6",",","12","]",")","#","doctest",":","+FIX","array","(","[","1",",","5",",","11","]",")","If","you","`","preserve_dtype","`",",","and","there","is","no","inverse","affine","preserving","the","dtype",",","the","inverse","is","None",":",">",">",">","affine2","=","affine.copy","(",")",">",">",">","affine2","[","0",",","0","]","=","2","#","now","inverse","ca","n't","be","integer",">",">",">","aff_t","=","AffineTransform","(","input_cs",",","output_cs",",","affine2",")",">",">",">","aff_t.inverse","(","preserve_dtype=True",")","is","None","True"]
code: def inverse(self, preserve_dtype=False):
      """Return coordinate map with inverse affine transform or None
  
      Parameters
      ----------
      preserve_dtype : bool
          If False, return affine mapping from inverting the ``affine``.  The
          domain / range dtypes for the inverse may then change as a function
          of the dtype of the inverted ``affine``.  If True, try to invert our
          ``affine``, and see if it can be cast to the needed data type, which
          is ``self.function_domain.coord_dtype``.  We need this dtype in
          order for the inverse to preserve the coordinate system dtypes.
  
      Returns
      -------
      aff_cm_inv : ``AffineTransform`` instance or None
          ``AffineTransform`` mapping from the *range* of input `self` to the
          *domain* of input `self` - the inverse of `self`.  If
          ``self.affine`` was not invertible return None.  If `preserve_dtype`
          is True, and the inverse of ``self.affine`` cannot be cast to
          ``self.function_domain.coord_dtype``, then return None.  Otherwise
          return ``AffineTransform`` inverse mapping.  If `preserve_dtype` is
          False, the domain / range dtypes of the return inverse may well be
          different from those of the input `self`.
  
      Examples
      --------
      >>> input_cs = CoordinateSystem('ijk', coord_dtype=np.int_)
      >>> output_cs = CoordinateSystem('xyz', coord_dtype=np.int_)
      >>> affine = np.array([[1,0,0,1],
      ...                    [0,1,0,1],
      ...                    [0,0,1,1],
      ...                    [0,0,0,1]])
      >>> affine_transform = AffineTransform(input_cs, output_cs, affine)
      >>> affine_transform([2,3,4]) #doctest: +FIX
      array([3, 4, 5])
  
      The inverse transform, by default, generates a floating point inverse
      matrix and therefore floating point output:
  
      >>> affine_transform_inv = affine_transform.inverse()
      >>> affine_transform_inv([2, 6, 12])
      array([  1.,   5.,  11.])
  
      You can force it to preserve the coordinate system dtype with the
      `preserve_dtype` flag:
  
      >>> at_inv_preserved = affine_transform.inverse(preserve_dtype=True)
      >>> at_inv_preserved([2, 6, 12]) #doctest: +FIX
      array([  1,   5,  11])
  
      If you `preserve_dtype`, and there is no inverse affine preserving the
      dtype, the inverse is None:
  
      >>> affine2 = affine.copy()
      >>> affine2[0, 0] = 2 # now inverse can't be integer
      >>> aff_t = AffineTransform(input_cs, output_cs, affine2)
      >>> aff_t.inverse(preserve_dtype=True) is None
      True
      """
      aff_dt = self.function_range.coord_dtype
      try:
          m_inv = npl.inv(self.affine)
      except npl.LinAlgError:
          return None
      except TypeError:
          # Try using sympy for the inverse.  This might be needed for sympy
          # symbols in the affine, or Float128, or complex numbers.
          from sympy import Matrix, matrix2numpy
  
          sym_inv = Matrix(self.affine).inv()
          m_inv = matrix2numpy(sym_inv).astype(aff_dt)
      else:  # linalg inverse succeeded
          # Do we need a specific dtype?  Can we cast to this dtype?
          if preserve_dtype and aff_dt != np.object_:
              m_inv_orig = m_inv
              m_inv = m_inv.astype(aff_dt)
              if not np.allclose(m_inv_orig, m_inv):
                  return None
      return AffineTransform(
          self.function_range, self.function_domain, m_inv
      )
  
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 2 for calling the AffineTransform obj's underlying member method code with example usage: obj.inverse(preserve_dtype) and returns: AffineTransform, None, None