def calc_euler(evecs): """ Calculate the Euler angles that rotate from the canonical coordinate frame to a coordinate frame defined by a set of eigenvectors. Parameters ---------- evecs : 3-by-3 array """ rot0 = np.eye(4) # What is the rotation from the first eigenvector to eye(3)? rot0[:3, :3] = vec2vec_rotmat(evecs[0], np.eye(3)[0]) # Decompose (we only need the angles) scale, shear, angles0, translate, perspective = decompose_matrix(rot0) # Convert angles to Euler matrix: em = euler_matrix(*angles0) # Now, we need another rotation to bring the second eigenvector to the right # direction ang1 = np.arccos( np.dot(evecs[1], em[1, :3]) / (np.linalg.norm(evecs[1]) * np.linalg.norm(em[1, :3]))) rar = np.eye(4) # The rar is a matrix that rotates for a given angle around a given # vector: rar[:3, :3] = rodrigues_axis_rotation(evecs[0], np.rad2deg(ang1)) # We combine these two rotations and decompose the combined matrix to give # us three Euler angles, which will be our parameters scale, shear, angles, translate, perspective = decompose_matrix(em @ rar) return angles
def decompose_matrix44(mat, size=12): """ Given a 4x4 homogeneous matrix return the parameter vector Parameters ----------- mat : array Homogeneous 4x4 transformation matrix size : int Size of output vector. 6 for rigid, 7 for similarity and 12 for affine. Default is 12. Returns ------- t : ndarray One dimensional ndarray of 6, 7 or 12 affine parameters. """ scale, shear, angles, translate, _ = decompose_matrix(mat) t = np.zeros(12) t[:3] = translate t[3: 6] = np.rad2deg(angles) if size == 6: return t[:6] if size == 7: t[6] = np.mean(scale) return t[:7] if size == 12: t[6: 9] = scale t[9: 12] = shear return t raise ValueError('Size can be 6, 7 or 12')
def decompose_matrix44(mat, size=12): """ Given a 4x4 homogeneous matrix return the parameter vector Parameters ----------- mat : array Homogeneous 4x4 transformation matrix size : int Size of output vector. 6 for rigid, 7 for similarity and 12 for affine. Default is 12. Returns ------- t : ndarray One dimensional ndarray of 6, 7 or 12 affine parameters. """ scale, shear, angles, translate, _ = decompose_matrix(mat) t = np.zeros(12) t[:3] = translate t[3:6] = np.rad2deg(angles) if size == 6: return t[:6] if size == 7: t[6] = np.mean(scale) return t[:7] if size == 12: t[6:9] = scale t[9:12] = shear return t raise ValueError('Size can be 6, 7 or 12')
def itk_affine_to_rigid(transform_file, cwd): """uses c3d_affine_tool and FSL's aff2rigid to convert an itk linear transform from affine to rigid""" rigid_mat_file = cwd + "/6DOFrigid.mat" translation_mat_file = cwd + '/translation.mat' inverse_mat_file = cwd + '/6DOFinverse.mat' raw_transform = sitk.ReadTransform(transform_file) aff_transform = sitk.AffineTransform(3) aff_transform.SetFixedParameters(raw_transform.GetFixedParameters()) aff_transform.SetParameters(raw_transform.GetParameters()) full_matrix = np.eye(4) full_matrix[:3, :3] = np.array(aff_transform.GetMatrix()).reshape( (3, 3), order="C") _, _, angles, _, _ = geom.decompose_matrix(full_matrix) rot_mat = geom.euler_matrix(angles[0], angles[1], angles[2]) rigid = sitk.Euler3DTransform() rigid.SetCenter(aff_transform.GetCenter()) rigid.SetTranslation(aff_transform.GetTranslation()) # Write a translation-only transform sitk.WriteTransform(rigid, translation_mat_file) # Write the full rigid (translation + rotation) transform rigid.SetMatrix(tuple(rot_mat[:3, :3].flatten(order="C"))) sitk.WriteTransform(rigid, rigid_mat_file) # Write the inverse rigid transform sitk.WriteTransform(rigid.GetInverse(), inverse_mat_file) if False in (op.exists(rigid_mat_file), op.exists(translation_mat_file), op.exists(inverse_mat_file)): raise Exception("unable to create rigid AC-PC transform") return rigid_mat_file, inverse_mat_file, translation_mat_file
def load_dwi_files_blinds(folder_name): from dipy.core.gradients import gradient_table from dipy.core.geometry import compose_matrix, decompose_matrix for file in os.listdir(folder_name): if file.endswith(".bvec"): bvec_file = os.path.join(folder_name, file) if file.endswith("labels.nii"): labels_file_name = os.path.join(folder_name, file) if file.endswith("WM.nii"): wm_file_name = os.path.join(folder_name, file) bval_file = bvec_file[:-4:]+'bval' nii_file = bvec_file[:-4:]+'nii' hardi_img = nib.load(nii_file) data = hardi_img.get_fdata() affine = hardi_img.affine scale, shear, ang, trans, pre = decompose_matrix(affine) shear = np.zeros(np.shape(shear)) affine = compose_matrix(scale, shear, ang, trans, pre) gtab = gradient_table(bval_file, bvec_file) #voxel_size = nib.affines.voxel_sizes(affine) #data, affine1 = reslice(data, affine, voxel_size, (3., 3., 3.)) labels_img = nib.load(labels_file_name) labels = labels_img.get_fdata() #labels,affine1=reslice(labels,affine,voxel_size,(3., 3., 3.)) wm_img = nib.load(wm_file_name) white_matter = wm_img.get_fdata() #white_matter,affine1=reslice(white_matter,affine,voxel_size,(3., 3., 3.)) return gtab,data,affine,labels,white_matter,nii_file,bvec_file
def _run_interface(self, runtime): collected_motion = [] output_fname = os.path.join(runtime.cwd, "motion_params.csv") output_spm_fname = os.path.join(runtime.cwd, "spm_movpar.txt") for motion_file in self.inputs.transform_files: if os.path.exists("output.txt"): os.remove("output.txt") # Convert to homogenous matrix os.system("ConvertTransformFile 3 %s output.txt --RAS --hm" % (motion_file)) affine = np.loadtxt("output.txt") scale, shear, angles, translate, persp = decompose_matrix(affine) collected_motion.append( np.concatenate([scale, shear, np.array(angles), translate])) final_motion = np.row_stack(collected_motion) cols = [ "scaleX", "scaleY", "scaleZ", "shearXY", "shearXZ", "shearYZ", "rotateX", "rotateY", "rotateZ", "shiftX", "shiftY", "shiftZ" ] motion_df = pd.DataFrame(data=final_motion, columns=cols) motion_df.to_csv(output_fname, index=False) self._results['motion_file'] = output_fname spmcols = motion_df[[ 'shiftX', 'shiftY', 'shiftZ', 'rotateX', 'rotateY', 'rotateZ' ]] self._results['spm_motion_file'] = output_spm_fname np.savetxt(output_spm_fname, spmcols.values) return runtime
def test_compose_decompose_matrix(): for translate in permutations(40 * np.random.rand(3), 3): for angles in permutations(np.deg2rad(90 * np.random.rand(3)), 3): for shears in permutations(3 * np.random.rand(3), 3): for scale in permutations(3 * np.random.rand(3), 3): mat = compose_matrix(translate=translate, angles=angles, shear=shears, scale=scale) sc, sh, ang, trans, _ = decompose_matrix(mat) assert_array_almost_equal(translate, trans) assert_array_almost_equal(angles, ang) assert_array_almost_equal(shears, sh) assert_array_almost_equal(scale, sc)