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: Initialize AffineTransform
  
  Parameters
  ----------
  function_domain : :class:`CoordinateSystem`
     input coordinates
  function_range : :class:`CoordinateSystem`
     output coordinates
  affine : array-like
     affine homogeneous coordinate matrix
  
  Notes
  -----
  The dtype of the resulting matrix is determined by finding a
  safe typecast for the function_domain, function_range and affine.
docstr_tok: ["Initialize","AffineTransform","Parameters","--","--","--","--","--","function_domain",":",":","class",":","`","CoordinateSystem","`","input","coordinates","function_range",":",":","class",":","`","CoordinateSystem","`","output","coordinates","affine",":","array-like","affine","homogeneous","coordinate","matrix","Notes","--","--","-","The","dtype","of","the","resulting","matrix","is","determined","by","finding","a","safe","typecast","for","the","function_domain",",","function_range","and","affine","."]
code: def __init__(self, function_domain, function_range, affine):
      """Initialize AffineTransform
  
      Parameters
      ----------
      function_domain : :class:`CoordinateSystem`
         input coordinates
      function_range : :class:`CoordinateSystem`
         output coordinates
      affine : array-like
         affine homogeneous coordinate matrix
  
      Notes
      -----
      The dtype of the resulting matrix is determined by finding a
      safe typecast for the function_domain, function_range and affine.
      """
      if not is_coordsys(function_domain):
          function_domain = CoordinateSystem(function_domain)
      if not is_coordsys(function_range):
          function_range = CoordinateSystem(function_range)
      affine = np.asarray(affine)
      dtype = safe_dtype(
          affine.dtype,
          function_domain.coord_dtype,
          function_range.coord_dtype,
      )
      inaxes = function_domain.coord_names
      outaxes = function_range.coord_names
      self.function_domain = CoordinateSystem(
          inaxes, function_domain.name, dtype
      )
  
      self.function_range = CoordinateSystem(
          outaxes, function_range.name, dtype
      )
      self.ndims = (self.function_domain.ndim, self.function_range.ndim)
      affine = np.asarray(affine, dtype=dtype)
      if affine.shape != (self.ndims[1] + 1, self.ndims[0] + 1):
          raise ValueError(
              "coordinate lengths do not match " "affine matrix shape"
          )
      # Test that it is actually an affine mapping in homogeneous
      # form
      bottom_row = np.array([0] * self.ndims[0] + [1])
      if not np.all(affine[-1] == bottom_row):
          raise ValueError(
              "the homogeneous transform should have bottom="
              + f"row {repr(bottom_row)}"
          )
      self.affine = affine
  
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 1 to create a new AffineTransform object  with example: obj = AffineTransform(function_domain, function_range, affine)