@cached<EOL><INDENT>def properties(self):<DEDENT>
<EOL>invert = (np.linalg.det(self.r) < <NUM_LIT:0>)<EOL>factor = {True: -<NUM_LIT:1>, False: <NUM_LIT:1>}[invert]<EOL>cos_angle = <NUM_LIT:0.5>*(factor*np.trace(self.r) - <NUM_LIT:1>)<EOL>if cos_angle > <NUM_LIT:1>: cos_angle = <NUM_LIT:1.0><EOL>if cos_angle < -<NUM_LIT:1>: cos_angle = -<NUM_LIT:1.0><EOL>axis = <NUM_LIT:0.5>*factor*np.array([-self.r[<NUM_LIT:1>, <NUM_LIT:2>] + self.r[<NUM_LIT:2>, <NUM_LIT:1>], self.r[<NUM_LIT:0>, <NUM_LIT:2>] - self.r[<NUM_LIT:2>, <NUM_LIT:0>], -self.r[<NUM_LIT:0>, <NUM_LIT:1>] + self.r[<NUM_LIT:1>, <NUM_LIT:0>]])<EOL>sin_angle = np.linalg.norm(axis)<EOL>if (sin_angle == <NUM_LIT:0.0>) and (cos_angle > <NUM_LIT:0>):<EOL><INDENT>axis[<NUM_LIT:2>] = <NUM_LIT:1.0><EOL><DEDENT>elif abs(sin_angle) < (<NUM_LIT:1>-cos_angle):<EOL><INDENT>for index in range(<NUM_LIT:3>):<EOL><INDENT>axis[index] = {True: -<NUM_LIT:1>, False: <NUM_LIT:1>}[axis[index] < <NUM_LIT:0>] * np.sqrt(abs((factor*self.r[index, index] - cos_angle) / (<NUM_LIT:1> - cos_angle)))<EOL><DEDENT><DEDENT>else:<EOL><INDENT>axis = axis / sin_angle<EOL><DEDENT>angle = np.arctan2(sin_angle, cos_angle)<EOL>return angle, axis, invert<EOL>
Rotation properties: angle, axis, invert