class_docstr: 4x4 Transform matrix that can always be represented as a combination of 3 matrices: scale * rotate * translate
  This transform has no shear; angles are always preserved.
class_docstr_tok: ["4x4","Transform","matrix","that","can","always","be","represented","as","a","combination","of","3","matrices",":","scale","*","rotate","*","translate","This","transform","has","no","shear",";","angles","are","always","preserved","."]
docstr: Set this transform based on the elements of *m*
  The input matrix must be affine AND have no shear,
  otherwise the conversion will most likely fail.
docstr_tok: ["Set","this","transform","based","on","the","elements","of","*","m","*","The","input","matrix","must","be","affine","AND","have","no","shear",",","otherwise","the","conversion","will","most","likely","fail","."]
code: def setFromMatrix(self, m):
      """
      Set this transform based on the elements of *m*
      The input matrix must be affine AND have no shear,
      otherwise the conversion will most likely fail.
      """
      import numpy.linalg
  
      for i in range(4):
          self.setRow(i, m.row(i))
      m = self.matrix().reshape(4, 4)
      ## translation is 4th column
      self._state["pos"] = m[:3, 3]
  
      ## scale is vector-length of first three columns
      scale = (m[:3, :3] ** 2).sum(axis=0) ** 0.5
      ## see whether there is an inversion
      z = np.cross(m[0, :3], m[1, :3])
      if np.dot(z, m[2, :3]) < 0:
          scale[1] *= -1  ## doesn't really matter which axis we invert
      self._state["scale"] = scale
  
      ## rotation axis is the eigenvector with eigenvalue=1
      r = m[:3, :3] / scale[np.newaxis, :]
      try:
          evals, evecs = numpy.linalg.eig(r)
      except:
          print("Rotation matrix: %s" % str(r))
          print("Scale: %s" % str(scale))
          print("Original matrix: %s" % str(m))
          raise
      eigIndex = np.argwhere(np.abs(evals - 1) < 1e-6)
      if len(eigIndex) < 1:
          print("eigenvalues: %s" % str(evals))
          print("eigenvectors: %s" % str(evecs))
          print("index: %s, %s" % (str(eigIndex), str(evals - 1)))
          raise Exception("Could not determine rotation axis.")
      axis = evecs[:, eigIndex[0, 0]].real
      axis /= ((axis**2).sum()) ** 0.5
      self._state["axis"] = axis
  
      ## trace(r) == 2 cos(angle) + 1, so:
      cos = (r.trace() - 1) * 0.5  ## this only gets us abs(angle)
  
      ## The off-diagonal values can be used to correct the angle ambiguity,
      ## but we need to figure out which element to use:
      axisInd = np.argmax(np.abs(axis))
      rInd, sign = [((1, 2), -1), ((0, 2), 1), ((0, 1), -1)][axisInd]
  
      ## Then we have r-r.T = sin(angle) * 2 * sign * axis[axisInd];
      ## solve for sin(angle)
      sin = (r - r.T)[rInd] / (2.0 * sign * axis[axisInd])
  
      ## finally, we get the complete angle from arctan(sin/cos)
      self._state["angle"] = degrees(atan2(sin, cos))
      if self._state["angle"] == 0:
          self._state["axis"] = (0, 0, 1)
  
imports: from math import atan2, degrees
  import numpy
  from .Qt import QtGui
  from .Transform3D import Transform3D
  from .Vector import Vector
  from .None import SRTTransform
label_desc: Use image node_id 12 for calling the SRTTransform3D obj's underlying member method code with example usage: obj.setFromMatrix(m) without return types