def euler2mat(z=0, y=0, x=0): """Return matrix for intrinsic rotations around z, y, x Parameters ---------- z : float y : float x : float Returns ------- M the intrinsic rotation matrix Example ------- >>> zrot = 1.3 # radians >>> yrot = -0.1 >>> xrot = 0.2 >>> M = euler2mat(zrot, yrot, xrot) >>> M1 = euler2mat(z=1.3) >>> M2 = euler2mat(y=-0.1) >>> M3 = euler2mat(x=0.2) >>> composed_M = dot(M3, dot(M2, M1)) >>> allclose(M, composed_M) True """ return np.dot(ea.euler2mat(z=z), np.dot(ea.euler2mat(y=y), ea.euler2mat(x=x)))
def test_affines_save(image_orientation): """Check implementation of exporting affines to formats.""" # Generate test transform img = loadimg(SOMEONES_ANATOMY) imgaff = img.affine if image_orientation == 'LAS': newaff = imgaff.copy() newaff[0, 0] *= -1.0 newaff[0, 3] = imgaff.dot(np.hstack( (np.array(img.shape[:3]) - 1, 1.0)))[0] img = Nifti1Image(np.flip(img.get_fdata(), 0), newaff, img.header) elif image_orientation == 'LPS': newaff = imgaff.copy() newaff[0, 0] *= -1.0 newaff[1, 1] *= -1.0 newaff[:2, 3] = imgaff.dot(np.hstack( (np.array(img.shape[:3]) - 1, 1.0)))[:2] img = Nifti1Image(np.flip(np.flip(img.get_fdata(), 0), 1), newaff, img.header) elif image_orientation == 'oblique': A = shape_zoom_affine(img.shape, img.header.get_zooms(), x_flip=False) R = from_matvec(euler2mat(x=0.09, y=0.001, z=0.001)) newaff = R.dot(A) img = Nifti1Image(img.get_fdata(), newaff, img.header) img.header.set_qform(newaff, 1) img.header.set_sform(newaff, 1) T = from_matvec(euler2mat(x=0.9, y=0.001, z=0.001), [4.0, 2.0, -1.0]) xfm = nbl.Affine(T) xfm.reference = img itk = nbl.load(os.path.join(data_path, 'affine-%s-itk.tfm' % image_orientation), fmt='itk') fsl = np.loadtxt( os.path.join(data_path, 'affine-%s.fsl' % image_orientation)) afni = np.loadtxt( os.path.join(data_path, 'affine-%s.afni' % image_orientation)) with InTemporaryDirectory(): xfm.to_filename('M.tfm', fmt='itk') xfm.to_filename('M.fsl', fmt='fsl') xfm.to_filename('M.afni', fmt='afni') nb_itk = nbl.load('M.tfm', fmt='itk') nb_fsl = np.loadtxt('M.fsl') nb_afni = np.loadtxt('M.afni') assert_equal(itk, nb_itk) assert_almost_equal(fsl, nb_fsl) assert_almost_equal(afni, nb_afni) # Create version not aligned to canonical
def twist_around_axis(thread, angle1, angle2, axis): xyz = thread.getXYZ() cons = thread.getConstraints() mat1 = euler2mat(*cons[3:6]) mat2 = euler2mat(*cons[9:12]) tmat1 = euler2mat(*angle_axis2euler(angle1, axis)) tmat2 = euler2mat(*angle_axis2euler(angle2, axis)) newmat1 = dot(tmat1, mat1) newmat2 = dot(tmat2, mat2) neweul1 = mat2euler(newmat1) neweul2 = mat2euler(newmat2) cons[3:6] = neweul1 cons[9:12] = neweul2 thread.setConstraints(cons)
def twist_around_axis(thread,angle1,angle2,axis): xyz = thread.getXYZ() cons = thread.getConstraints() mat1 = euler2mat(*cons[3:6]) mat2 = euler2mat(*cons[9:12]) tmat1 = euler2mat(*angle_axis2euler(angle1,axis)) tmat2 = euler2mat(*angle_axis2euler(angle2,axis)) newmat1 = dot(tmat1,mat1) newmat2 = dot(tmat2,mat2) neweul1 = mat2euler(newmat1) neweul2 = mat2euler(newmat2) cons[3:6] = neweul1 cons[9:12] = neweul2 thread.setConstraints(cons)
def test_against_spm_resample(): # Test resampling against images resampled with SPM12 # anatomical.nii has a diagonal -2, 2 2 affine; # functional.nii has a diagonal -4, 4 4 affine; # These are a bit boring, so first add some rotations and translations to # the anatomical image affine, and then resample to the first volume in the # functional, and compare to the same thing in SPM. # See ``make_moved_anat.py`` script in this directory for input to SPM. anat = nib.load(pjoin(DATA_DIR, 'anatomical.nii')) func = nib.load(pjoin(DATA_DIR, 'functional.nii')) some_rotations = euler2mat(0.1, 0.2, 0.3) extra_affine = from_matvec(some_rotations, [3, 4, 5]) moved_anat = nib.Nifti1Image(anat.get_data().astype(float), extra_affine.dot(anat.affine), anat.header) one_func = nib.Nifti1Image(func.dataobj[..., 0], func.affine, func.header) moved2func = resample_from_to(moved_anat, one_func, order=1, cval=np.nan) spm_moved = nib.load(pjoin(DATA_DIR, 'resampled_anat_moved.nii')) assert_spm_resampling_close(moved_anat, moved2func, spm_moved) # Next we resample the rotated anatomical image to output space, and compare # to the same operation done with SPM (our own version of 'reorient.m' by # John Ashburner). moved2output = resample_to_output(moved_anat, 4, order=1, cval=np.nan) spm2output = nib.load(pjoin(DATA_DIR, 'reoriented_anat_moved.nii')) assert_spm_resampling_close(moved_anat, moved2output, spm2output);
def test_against_spm_resample(): # Test resampling against images resampled with SPM12 # anatomical.nii has a diagonal -2, 2 2 affine; # functional.nii has a diagonal -4, 4 4 affine; # These are a bit boring, so first add some rotations and translations to # the anatomical image affine, and then resample to the first volume in the # functional, and compare to the same thing in SPM. # See ``make_moved_anat.py`` script in this directory for input to SPM. anat = nib.load(pjoin(DATA_DIR, 'anatomical.nii')) func = nib.load(pjoin(DATA_DIR, 'functional.nii')) some_rotations = euler2mat(0.1, 0.2, 0.3) extra_affine = from_matvec(some_rotations, [3, 4, 5]) moved_anat = nib.Nifti1Image(anat.get_fdata(), extra_affine.dot(anat.affine), anat.header) one_func = nib.Nifti1Image(func.dataobj[..., 0], func.affine, func.header) moved2func = resample_from_to(moved_anat, one_func, order=1, cval=np.nan) spm_moved = nib.load(pjoin(DATA_DIR, 'resampled_anat_moved.nii')) assert_spm_resampling_close(moved_anat, moved2func, spm_moved) # Next we resample the rotated anatomical image to output space, and compare # to the same operation done with SPM (our own version of 'reorient.m' by # John Ashburner). moved2output = resample_to_output(moved_anat, 4, order=1, cval=np.nan) spm2output = nib.load(pjoin(DATA_DIR, 'reoriented_anat_moved.nii')) assert_spm_resampling_close(moved_anat, moved2output, spm2output);
def rotate_hessian_3d(dxx, dxy, dxz, dyy, dyz, dzz, z, y=0.0, x=0.0): """Rotate a 3d hessian or band pass hessian. Hp = R' * H * R """ R = euler2mat(z) H = np.zeros([3, 3, dxx.size], dtype=dxx.dtype) H[0, 0, :] = dxx.ravel() H[0, 1, :] = dxy.ravel() H[0, 2, :] = dxz.ravel() H[1, 1, :] = dyy.ravel() H[1, 2, :] = dyz.ravel() H[2, 2, :] = dzz.ravel() H[1, 0, :] = H[0, 1, :] H[2, 0, :] = H[0, 2, :] H[2, 1, :] = H[1, 2, :] # Hp = np.zeros(H.shape, dtype=H.dtype) # for n in range(H.shape[2]): # Hp[:,:,n] = R.transpose() @ H[:,:,n] @ R Hp = np.dot(np.dot(R.transpose(), H).transpose(2, 0, 1), R).transpose(1, 2, 0) dxxp = Hp[0, 0, :].reshape(dxx.shape) dxyp = Hp[0, 1, :].reshape(dxy.shape) dxzp = Hp[0, 2, :].reshape(dxz.shape) dyyp = Hp[1, 1, :].reshape(dyy.shape) dyzp = Hp[1, 2, :].reshape(dyz.shape) dzzp = Hp[2, 2, :].reshape(dzz.shape) return dxxp, dxyp, dxzp, dyyp, dyzp, dzzp
def test_LinearList_common(tmpdir, data_path, sw, image_orientation, get_testdata): tmpdir.chdir() angles = np.random.uniform(low=-3.14, high=3.14, size=(5, 3)) translation = np.random.uniform(low=-5., high=5., size=(5, 3)) mats = [from_matvec(euler2mat(*a), t) for a, t in zip(angles, translation)] ext = '' if sw == 'afni': factory = afni.AFNILinearTransformArray elif sw == 'fsl': factory = fsl.FSLLinearTransformArray elif sw == 'itk': ext = '.tfm' factory = itk.ITKLinearTransformArray tflist1 = factory(mats) fname = 'affine-%s.%s%s' % (image_orientation, sw, ext) with pytest.raises(FileNotFoundError): factory.from_filename(fname) tmpdir.join('singlemat.%s' % ext).write('') with pytest.raises(TransformFileError): factory.from_filename('singlemat.%s' % ext) tflist1.to_filename(fname) tflist2 = factory.from_filename(fname) assert tflist1['nxforms'] == tflist2['nxforms'] assert all([np.allclose(x1['parameters'], x2['parameters']) for x1, x2 in zip(tflist1.xforms, tflist2.xforms)])
def test_ITKLinearTransform(tmpdir, data_path): tmpdir.chdir() matlabfile = data_path / 'ds-005_sub-01_from-T1_to-OASIS_affine.mat' mat = loadmat(str(matlabfile)) with open(str(matlabfile), 'rb') as f: itkxfm = itk.ITKLinearTransform.from_fileobj(f) assert np.allclose(itkxfm['parameters'][:3, :3].flatten(), mat['AffineTransform_float_3_3'][:-3].flatten()) assert np.allclose(itkxfm['offset'], mat['fixed'].reshape((3, ))) itkxfm = itk.ITKLinearTransform.from_filename(matlabfile) assert np.allclose(itkxfm['parameters'][:3, :3].flatten(), mat['AffineTransform_float_3_3'][:-3].flatten()) assert np.allclose(itkxfm['offset'], mat['fixed'].reshape((3, ))) # Test to_filename(textfiles) itkxfm.to_filename('textfile.tfm') with open('textfile.tfm', 'r') as f: itkxfm2 = itk.ITKLinearTransform.from_fileobj(f) assert np.allclose(itkxfm['parameters'], itkxfm2['parameters']) # Test to_filename(matlab) itkxfm.to_filename('copy.mat') with open('copy.mat', 'rb') as f: itkxfm3 = itk.ITKLinearTransform.from_fileobj(f) assert np.all(itkxfm['parameters'] == itkxfm3['parameters']) rasmat = from_matvec(euler2mat(x=0.9, y=0.001, z=0.001), [4.0, 2.0, -1.0]) itkxfm = itk.ITKLinearTransform.from_ras(rasmat) assert np.allclose(itkxfm['parameters'], ITK_MAT * rasmat) assert np.allclose(itkxfm.to_ras(), rasmat)
def par2referenceFSL (par_file, session, par_cycle): rigids_euler = np.array(pd.read_csv(par_file, header=None, delimiter='\s+')) number_of_cycles = rigids_euler.shape[0] rigids = np.empty((number_of_cycles, 4, 4)) for i in range(number_of_cycles): mat = euler2mat( -rigids_euler[i,0], # gieren / yaw / z -rigids_euler[i,1], # rollen / roll / y rigids_euler[i,2]) # nicken / pitch / x vec = rigids_euler[i,3:] rigids[i] = from_matvec( matrix=mat, vector=np.array((-vec[1], vec[0], -vec[2]))) reference_maps = ReferenceMaps(session.name) reference_maps.temporal_resolution = session.temporal_resolution reference_maps.slice_timing = session.slice_timing reference_maps.set_acquisition_maps(Affines(rigids)) reference_maps.shape = (session.numob, session.shape[session.ep]) # The realignment parameters (Euler angles and transformations) # saved by McFLIRT are given with respect to the centre of mass of # the reference scan cycle (Why do you have to make *everything* so # complicated, FSL?!). We need to apply a translation from the # centre of mass of the reference cycle to the coordinate system of # the session. n,x,y,z = session.data.shape indices = ((slice(0,x), slice(0,y), slice(0,z))) lattice = session.reference.apply_to_indices(indices) lattice = np.moveaxis(lattice, -1 ,0) com = (session.raw[par_cycle] * lattice).sum(axis=(1,2,3)) / session.raw[par_cycle].sum() translation_from_com = Affine(from_matvec(np.eye(3), -com)) reference_maps.reset_reference_space(x=translation_from_com) return reference_maps
def twist_ctrl(thread, angle1, angle2): xyz = thread.getXYZ() axis1 = xyz[:, 1] - xyz[:, 0] axis2 = xyz[:, -1] - xyz[:, -2] cons = thread.getConstraints() mat1 = euler2mat(*cons[3:6]) mat2 = euler2mat(*cons[9:12]) tmat1 = euler2mat(*angle_axis2euler(angle1, axis1)) tmat2 = euler2mat(*angle_axis2euler(angle2, axis2)) newmat1 = dot(tmat1, mat1) newmat2 = dot(tmat2, mat2) neweul1 = mat2euler(newmat1) neweul2 = mat2euler(newmat2) #print "orig",cons[blah] cons[3:6] = neweul1 cons[9:12] = neweul2 thread.setConstraints(cons)
def twist_ctrl(thread,angle1,angle2): xyz = thread.getXYZ() axis1 = xyz[:,1] - xyz[:,0] axis2 = xyz[:,-1] - xyz[:,-2] cons = thread.getConstraints() mat1 = euler2mat(*cons[3:6]) mat2 = euler2mat(*cons[9:12]) tmat1 = euler2mat(*angle_axis2euler(angle1,axis1)) tmat2 = euler2mat(*angle_axis2euler(angle2,axis2)) newmat1 = dot(tmat1,mat1) newmat2 = dot(tmat2,mat2) neweul1 = mat2euler(newmat1) neweul2 = mat2euler(newmat2) #print "orig",cons[blah] cons[3:6] = neweul1 cons[9:12] = neweul2 thread.setConstraints(cons)
def transformEuler(eul1,rot_type,rot): mat1 = euler2mat(*eul1) if rot_type == "angle_axis": ang1,ax1 = rot tmat1 = angle_axis2mat(ax1,ang1) elif rot_type == "mat": tmat1 = rot elif rot_type == "euler": eul1 = rot tmat1 = euler2mat(*eul1) elif rot_type == "towards": targ_vec1,ang1 = rot cur_vec1 = euler2mat(*eul1)[:,0] ax_rot1 = cross(cur_vec1,targ_vec1) tmat1 = angle_axis2mat(ang1,ax_rot1) else: raise Exception("rotation type %s not understood"%rot_type) mat1new = dot(tmat1,mat1) return mat2euler(mat1new)
def test_aff2euler(): xr = 0.1 yr = -1.3 zr = 3.1 scales = (2.1, 3.2, 4.4) R = np.dot(euler.euler2mat(xr, yr, zr), np.diag(scales)) aff = np.eye(4) aff[:3, :3] = R aff[:3, 3] = [11, 12, 13] npt.assert_almost_equal(reg.aff2euler(aff), (xr, yr, zr))
def test_aff2euler(): xr = 0.1 yr = -1.3 zr = 3.1 scales = (2.1, 3.2, 4.4) R = euler.euler2mat(xr, yr, zr).dot(np.diag(scales)) aff = np.eye(4) aff[:3, :3] = R aff[:3, 3] = [11, 12, 13] npt.assert_almost_equal(reg.aff2euler(aff), (xr, yr, zr))
def test_obliquity(): """Check the calculation of inclination of an affine axes.""" from math import pi aligned = np.diag([2.0, 2.0, 2.3, 1.0]) aligned[:-1, -1] = [-10, -10, -7] R = from_matvec(euler2mat(x=0.09, y=0.001, z=0.001), [0.0, 0.0, 0.0]) oblique = R.dot(aligned) np.testing.assert_almost_equal(obliquity(aligned), [0.0, 0.0, 0.0]) np.testing.assert_almost_equal(obliquity(oblique) * 180 / pi, [0.0810285, 5.1569949, 5.1569376])
def transformEuler(eul1, rot_type, rot): mat1 = euler2mat(*eul1) if rot_type == "angle_axis": ang1, ax1 = rot tmat1 = angle_axis2mat(ax1, ang1) elif rot_type == "mat": tmat1 = rot elif rot_type == "euler": eul1 = rot tmat1 = euler2mat(*eul1) elif rot_type == "towards": targ_vec1, ang1 = rot cur_vec1 = euler2mat(*eul1)[:, 0] ax_rot1 = cross(cur_vec1, targ_vec1) tmat1 = angle_axis2mat(ang1, ax_rot1) else: raise Exception("rotation type %s not understood" % rot_type) mat1new = dot(tmat1, mat1) return mat2euler(mat1new)
def rotate_gradient_2d(gx, gy, z=0.0): """Rotate a 2d gradient or band pass gradient. gp = R * g """ R = euler2mat(z=z)[:2, :2] g = np.zeros([2, gx.size], dtype=gx.dtype) g[0, :] = gx.ravel() g[1, :] = gy.ravel() gp = R @ g gxp = gp[0].reshape(gx.shape) gyp = gp[1].reshape(gy.shape) return gxp, gyp
def _transform_inplace(self, tx1=0, ty1=0, tz1=0, tx2=0, ty2=0, tz2=0, rx1=0, ry1=0, rz1=0, rx2=0, ry2=0, rz2=0): name1 = os.path.basename(self.object1.folder) name2 = os.path.basename(self.object2.folder) rx1, ry1, rz1, rx2, ry2, rz2 = np.deg2rad( [rx1, ry1, rz1, rx2, ry2, rz2]) t1 = np.eye(4) t2 = np.eye(4) t1[:3, 3] = tx1, ty1, tz1 t1[:3, :3] = eulerangles.euler2mat(rz1, ry1, rx1) t2[:3, 3] = tx2, ty2, tz2 t2[:3, :3] = eulerangles.euler2mat(rz2, ry2, rx2) json_dict = dict(json_template) json_dict['levels'][0]['nodes'][0]['modelId'] = name1 json_dict['levels'][0]['nodes'][1]['modelId'] = name2 json_dict['levels'][0]['nodes'][0]['transform'] = list(t1.flatten('F')) json_dict['levels'][0]['nodes'][1]['transform'] = list(t2.flatten('F')) path = os.path.join(self.folder, 'house.json') with open(path, 'w') as f: json.dump(json_dict, f) return path
def rotate_gradient_3d(gx, gy, gz, z=0.0, y=0.0, x=0.0): """Rotate a 3d gradient or band pass gradient. gp = R * g """ R = euler2mat(z=z, y=y, x=x) g = np.zeros([3, gx.size], dtype=gx.dtype) g[0, :] = gx.ravel() g[1, :] = gy.ravel() g[2, :] = gz.ravel() gp = R @ g gxp = gp[0].reshape(gx.shape) gyp = gp[1].reshape(gy.shape) gzp = gp[2].reshape(gz.shape) return gxp, gyp, gzp
def test_get_direction_and_spacings(): xrot = 0.5 yrot = 0.75 zrot = 1.0 direction_gt = eulerangles.euler2mat(zrot, yrot, xrot) spacings_gt = np.array([1.1, 1.2, 1.3]) scaling_gt = np.diag(spacings_gt) translation_gt = np.array([1, 2, 3]) affine = np.eye(4) affine[:3, :3] = direction_gt.dot(scaling_gt) affine[:3, 3] = translation_gt direction, spacings = imwarp.get_direction_and_spacings(affine, 3) assert_array_almost_equal(direction, direction_gt) assert_array_almost_equal(spacings, spacings_gt)
def test_get_direction_and_spacings(): xrot = 0.5 yrot = 0.75 zrot = 1.0 direction_gt = eulerangles.euler2mat(zrot, yrot, xrot) spacings_gt = np.array([1.1, 1.2, 1.3]) scaling_gt = np.diag(spacings_gt) translation_gt = np.array([1,2,3]) affine = np.eye(4) affine[:3, :3] = direction_gt.dot(scaling_gt) affine[:3, 3] = translation_gt direction, spacings = imwarp.get_direction_and_spacings(affine, 3) assert_array_almost_equal(direction, direction_gt) assert_array_almost_equal(spacings, spacings_gt)
def test_apply_linear_transform(tmpdir, get_testdata, image_orientation, sw_tool): """Check implementation of exporting affines to formats.""" tmpdir.chdir() img = get_testdata[image_orientation] # Generate test transform T = from_matvec(euler2mat(x=0.9, y=0.001, z=0.001), [4.0, 2.0, -1.0]) xfm = nitl.Affine(T) xfm.reference = img ext = "" if sw_tool == "itk": ext = ".tfm" elif sw_tool == "fs": ext = ".lta" img.to_filename("img.nii.gz") xfm_fname = "M.%s%s" % (sw_tool, ext) xfm.to_filename(xfm_fname, fmt=sw_tool) cmd = APPLY_LINEAR_CMD[sw_tool]( transform=os.path.abspath(xfm_fname), reference=os.path.abspath("img.nii.gz"), moving=os.path.abspath("img.nii.gz"), ) # skip test if command is not available on host exe = cmd.split(" ", 1)[0] if not shutil.which(exe): pytest.skip("Command {} not found on host".format(exe)) exit_code = check_call([cmd], shell=True) assert exit_code == 0 sw_moved = nb.load("resampled.nii.gz") nt_moved = xfm.apply(img, order=0) diff = sw_moved.get_fdata() - nt_moved.get_fdata() # A certain tolerance is necessary because of resampling at borders assert (np.abs(diff) > 1e-3).sum() / diff.size < TESTS_BORDER_TOLERANCE nt_moved = xfm.apply("img.nii.gz", order=0) diff = sw_moved.get_fdata() - nt_moved.get_fdata() # A certain tolerance is necessary because of resampling at borders assert (np.abs(diff) > 1e-3).sum() / diff.size < TESTS_BORDER_TOLERANCE
def test_Linear_common(tmpdir, data_path, sw, image_orientation, get_testdata): tmpdir.chdir() moving = get_testdata[image_orientation] reference = get_testdata[image_orientation] ext = '' if sw == 'afni': factory = afni.AFNILinearTransform elif sw == 'fsl': factory = fsl.FSLLinearTransform elif sw == 'itk': reference = None moving = None ext = '.tfm' factory = itk.ITKLinearTransform elif sw == 'fs': ext = '.lta' factory = fs.LinearTransformArray with pytest.raises(TransformFileError): factory.from_string('') fname = 'affine-%s.%s%s' % (image_orientation, sw, ext) # Test the transform loaders are implemented xfm = factory.from_filename(data_path / fname) with open(str(data_path / fname)) as f: text = f.read() f.seek(0) xfm = factory.from_fileobj(f) # Test to_string assert text == xfm.to_string() xfm.to_filename(fname) assert filecmp.cmp(fname, str((data_path / fname).resolve())) # Test from_ras RAS = from_matvec(euler2mat(x=0.9, y=0.001, z=0.001), [4.0, 2.0, -1.0]) xfm = factory.from_ras(RAS, reference=reference, moving=moving) assert np.allclose(xfm.to_ras(reference=reference, moving=moving), RAS)
def par2referenceSPM(par_file, session): rigids_euler = np.array(pd.read_csv(par_file, header=None, delimiter='\s+')) number_of_cycles = rigids_euler.shape[0] rigids = np.empty((number_of_cycles, 4, 4)) for i in range(number_of_cycles): mat = euler2mat( -rigids_euler[i, 3], # gieren / yaw / z -rigids_euler[i, 4], # rollen / roll / y -rigids_euler[i, 5]) # nicken / pitch / x vec = rigids_euler[i, :3] rigids[i] = from_matvec(matrix=mat, vector=np.array((-vec[1], -vec[0], -vec[2]))) reference_maps = ReferenceMaps(session.name) reference_maps.temporal_resolution = session.temporal_resolution reference_maps.slice_timing = session.slice_timing reference_maps.set_acquisition_maps(Affines(rigids)) reference_maps.shape = (session.numob, session.shape[session.ep]) return reference_maps
def test_linear_save(tmpdir, data_path, get_testdata, image_orientation, sw_tool): """Check implementation of exporting affines to formats.""" tmpdir.chdir() img = get_testdata[image_orientation] # Generate test transform T = from_matvec(euler2mat(x=0.9, y=0.001, z=0.001), [4.0, 2.0, -1.0]) xfm = ntl.Affine(T) xfm.reference = img ext = '' if sw_tool == 'itk': ext = '.tfm' elif sw_tool == 'fs': ext = '.lta' xfm_fname1 = 'M.%s%s' % (sw_tool, ext) xfm.to_filename(xfm_fname1, fmt=sw_tool) xfm_fname2 = str( data_path / 'affine-%s.%s%s') % (image_orientation, sw_tool, ext) assert_affines_by_filename(xfm_fname1, xfm_fname2)
def rotate_hessian_2d(dxx, dxy, dyy, z): """Rotate a 2d hessian or band pass hessian. Hp = R * H * R' """ R = euler2mat(z)[:2, :2] H = np.zeros([2, 2, dxx.size], dtype=dxx.dtype) H[0, 0, :] = dxx.ravel() H[0, 1, :] = dxy.ravel() H[1, 0, :] = H[0, 1, :] H[1, 1, :] = dyy.ravel() # Hp = np.zeros(H.shape, dtype=H.dtype) # for n in range(H.shape[2]): # Hp[:,:,n] = R @ H[:,:,n] @ R.transpose() Hp = np.dot(np.dot(R, H).transpose(2, 0, 1), R.transpose()).transpose(1, 2, 0) dxxp = Hp[0, 0, :].reshape(dxx.shape) dxyp = Hp[0, 1, :].reshape(dxy.shape) dyyp = Hp[1, 1, :].reshape(dyy.shape) return dxxp, dxyp, dyyp
def test_ITKLinearTransform(tmpdir, testdata_path): tmpdir.chdir() matlabfile = testdata_path / "ds-005_sub-01_from-T1_to-OASIS_affine.mat" mat = loadmat(str(matlabfile)) with open(str(matlabfile), "rb") as f: itkxfm = itk.ITKLinearTransform.from_fileobj(f) assert np.allclose( itkxfm["parameters"][:3, :3].flatten(), mat["AffineTransform_float_3_3"][:-3].flatten(), ) assert np.allclose(itkxfm["offset"], mat["fixed"].reshape((3, ))) itkxfm = itk.ITKLinearTransform.from_filename(matlabfile) assert np.allclose( itkxfm["parameters"][:3, :3].flatten(), mat["AffineTransform_float_3_3"][:-3].flatten(), ) assert np.allclose(itkxfm["offset"], mat["fixed"].reshape((3, ))) # Test to_filename(textfiles) itkxfm.to_filename("textfile.tfm") with open("textfile.tfm", "r") as f: itkxfm2 = itk.ITKLinearTransform.from_fileobj(f) assert np.allclose(itkxfm["parameters"], itkxfm2["parameters"]) # Test to_filename(matlab) itkxfm.to_filename("copy.mat") with open("copy.mat", "rb") as f: itkxfm3 = itk.ITKLinearTransform.from_fileobj(f) assert np.all(itkxfm["parameters"] == itkxfm3["parameters"]) rasmat = from_matvec(euler2mat(x=0.9, y=0.001, z=0.001), [4.0, 2.0, -1.0]) itkxfm = itk.ITKLinearTransform.from_ras(rasmat) assert np.allclose(itkxfm["parameters"], ITK_MAT * rasmat) assert np.allclose(itkxfm.to_ras(), rasmat)
""" Make anatomical image with altered affine * Add some rotations and translations to affine; * Save as ``.nii`` file so SPM can read it. See ``resample_using_spm.m`` for processing of this generated image by SPM. """ import numpy as np import nibabel as nib from nibabel.eulerangles import euler2mat from nibabel.affines import from_matvec img = nib.load('anatomical.nii') some_rotations = euler2mat(0.1, 0.2, 0.3) extra_affine = from_matvec(some_rotations, [3, 4, 5]) moved_anat = nib.Nifti1Image(img.dataobj, extra_affine.dot(img.affine), img.header) moved_anat.set_data_dtype(np.float32) nib.save(moved_anat, 'anat_moved.nii')
angle = 0.3 rot_box = rotate_box(orth_epi_box, angle, orth_epi_box[0]) epi_center = np.mean(rot_box, axis=0) anat_center = np.mean(anat_box, axis=0) # y axis on the plot is first axis of image sag_y, sag_x = sagittal.shape iso_center = (np.array([sag_x, sag_y]) - 1) / 2. sag_extents = [-iso_center[0], iso_center[0], -iso_center[1], iso_center[1]] # Back to image coordinates br_img = np.array([0, rot_box[0, 0], rot_box[0, 1]]) epi_trans = np.eye(4) epi_trans[:3, 3] = -br_img rot = np.eye(4) rot[:3, :3] = euler.euler2mat(0, 0, -angle) # downsample to make smaller output image downsamp = 1/3 epi_scale = np.diag([downsamp, downsamp, downsamp, 1]) # template voxels to epi box image voxels vox2epi_vox = epi_scale.dot(rot.dot(epi_trans)) # epi image voxels to mm epi_vox2mm = t2_img.affine.dot(npl.inv(vox2epi_vox)) # downsampled image shape epi_vox_shape = np.array([data.shape[0], epi_x_len, epi_y_len]) * downsamp # Make sure dimensions are odd by rounding up or down # This makes the voxel center an integer index, which is convenient epi_vox_shape = [np.floor(d) if np.floor(d) % 2 else np.ceil(d) for d in epi_vox_shape] # resample, preserving affine epi_cmap = nca.vox2mni(epi_vox2mm)
def test_resample_to_output(): # Test routine to sample iamges to output space # Image aligned to output axes - no-op data = np.arange(24).reshape((2, 3, 4)) img = Nifti1Image(data, np.eye(4)) # Check default resampling img2 = resample_to_output(img) assert_array_equal(img2.shape, (2, 3, 4)) assert_array_equal(img2.affine, np.eye(4)) assert_array_equal(img2.dataobj, data) # Check resampling with different voxel size specifications for vox_sizes in (None, 1, [1, 1, 1]): img2 = resample_to_output(img, vox_sizes) assert_array_equal(img2.shape, (2, 3, 4)) assert_array_equal(img2.affine, np.eye(4)) assert_array_equal(img2.dataobj, data) img2 = resample_to_output(img, vox_sizes) # Check 2D works img_2d = Nifti1Image(data[0], np.eye(4)) for vox_sizes in (None, 1, (1, 1), (1, 1, 1)): img3 = resample_to_output(img_2d, vox_sizes) assert_array_equal(img3.shape, (3, 4, 1)) assert_array_equal(img3.affine, np.eye(4)) assert_array_equal(img3.dataobj, data[0][..., None]) # Even 1D img_1d = Nifti1Image(data[0, 0], np.eye(4)) img3 = resample_to_output(img_1d) assert_array_equal(img3.shape, (4, 1, 1)) assert_array_equal(img3.affine, np.eye(4)) assert_array_equal(img3.dataobj, data[0, 0][..., None, None]) # But 4D does not img_4d = Nifti1Image(data.reshape(2, 3, 2, 2), np.eye(4)) assert_raises(ValueError, resample_to_output, img_4d) # Run vox2vox_out tests, checking output shape, coordinate transform for in_shape, in_aff, vox, out_shape, out_aff in get_outspace_params(): # Allow for expansion of image shape from < 3D in_n_dim = len(in_shape) if in_n_dim < 3: in_shape = in_shape + (1,) * (3 - in_n_dim) if not vox is None: vox = vox + (1,) * (3 - in_n_dim) assert len(out_shape) == in_n_dim out_shape = out_shape + (1,) * (3 - in_n_dim) img = Nifti1Image(np.ones(in_shape), in_aff) out_img = resample_to_output(img, vox) assert_all_in(in_shape, in_aff, out_img.shape, out_img.affine) assert_equal(out_img.shape, out_shape) assert_almost_equal(out_img.affine, out_aff) # Check data is as expected with some transforms # Flip first axis out_img = resample_to_output(Nifti1Image(data, np.diag([-1, 1, 1, 1]))) assert_array_equal(out_img.dataobj, np.flipud(data)) # Subsample voxels out_img = resample_to_output(Nifti1Image(data, np.diag([4, 5, 6, 1]))) exp_out = spnd.affine_transform(data, [1/4, 1/5, 1/6], output_shape = (5, 11, 19)) assert_array_equal(out_img.dataobj, exp_out) # Unsubsample with voxel sizes out_img = resample_to_output(Nifti1Image(data, np.diag([4, 5, 6, 1])), [4, 5, 6]) assert_array_equal(out_img.dataobj, data) # A rotation to test nearest, order, cval rot_3 = from_matvec(euler2mat(np.pi / 4), [0, 0, 0]) rot_3_img = Nifti1Image(data, rot_3) out_img = resample_to_output(rot_3_img) exp_shape = (4, 4, 4) assert_equal(out_img.shape, exp_shape) exp_aff = np.array([[1, 0, 0, -2 * np.cos(np.pi / 4)], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) assert_almost_equal(out_img.affine, exp_aff) rzs, trans = to_matvec(np.dot(npl.inv(rot_3), exp_aff)) exp_out = spnd.affine_transform(data, rzs, trans, exp_shape) assert_almost_equal(out_img.dataobj, exp_out) # Order assert_almost_equal( resample_to_output(rot_3_img, order=0).dataobj, spnd.affine_transform(data, rzs, trans, exp_shape, order=0)) # Cval assert_almost_equal( resample_to_output(rot_3_img, cval=99).dataobj, spnd.affine_transform(data, rzs, trans, exp_shape, cval=99)) # Mode assert_almost_equal( resample_to_output(rot_3_img, mode='nearest').dataobj, spnd.affine_transform(data, rzs, trans, exp_shape, mode='nearest')) # out_class img_ni1 = Nifti2Image(data, np.eye(4)) img_ni2 = Nifti2Image(data, np.eye(4)) # Default is Nifti1Image assert_equal( resample_to_output(img_ni2).__class__, Nifti1Image) # Can be overriden assert_equal( resample_to_output(img_ni1, out_class=Nifti2Image).__class__, Nifti2Image) # None specifies out_class from input assert_equal( resample_to_output(img_ni2, out_class=None).__class__, Nifti2Image)
def main(): """ Main function """ # List of classes classes = ['sky', 'building', 'ground', 'vegetation', 'clutter'] # Load the weights weights_file = "features.npz" # weights_file = "weights_shape_33.npz" weights = np.load(weights_file) weights = weights['weights0/w1'] # weights = weights.reshape(list(weights.shape[:-1]) + # [weights.shape[-1] // 3, 3]) # weights = np.concatenate([weights[:, 0, :, :, :, 0][..., None], # weights[:, 0, :, :, :, 2][..., None]], axis=-1) # print(weights.shape) # weights = weights.reshape(list(weights.shape[:-2]) + # [weights.shape[-2] * 2]) nclasses = weights.shape[-2] weights_tf = weight_variable_const("w", weights) # Sample a line along the unit circle nsamples = 36 x_angles = np.linspace(0, 2 * np.pi, nsamples) z_angles = np.linspace(0, 2 * np.pi, nsamples) # Create an image with line image = np.zeros([nsamples, 2, 2, 2], dtype=np.float32) # Save images img_fold = "Img_temp" if not os.path.exists(img_fold): os.mkdir(img_fold) # Save figures fig_fold = "Figures" if not os.path.exists(fig_fold): os.mkdir(fig_fold) # Draw a line for samp_x in range(nsamples): normal = np.dot(eulerangles.euler2mat(0, 0, x_angles[samp_x]), [0, 1, 0]) # Create the image for i in [-1, 1]: for j in [-1, 1]: for k in [-1, 1]: vox = np.array([i, j, k]) dist = np.dot(normal, vox) / linalg.norm(normal) val = max(0, 1 - abs(dist)) print(i, j, k, dist) if dist > 0: image[samp_x, 0 if i == -1 else 1, 0 if j == -1 else 1, 0 if k == -1 else 1] = max(val, min(1, dist)) else: image[samp_x, 0 if i == -1 else 1, 0 if j == -1 else 1, 0 if k == -1 else 1] = val # io.imsave("img-{}.png".format(samp_x), (255 * image[samp_x,0]).astype(np.uint8)) # io.imsave("img-1-{}.png".format(samp_x), (255 * image[samp_x,1]).astype(np.uint8)) # return # Apply the convolution probs_tf = tf.placeholder(dtype=tf.float32, shape=[None, 2, 2, 2, nclasses]) res_tf = conv3d(probs_tf, weights_tf) # Apply to many things for c in range(nclasses): if not os.path.exists('{}/{}'.format(fig_fold, classes[c])): os.mkdir('{}/{}'.format(fig_fold, classes[c])) print('{}/{}'.format(fig_fold, classes[c])) for d in range(nclasses): # Prepare the probabilites probs = np.zeros([nsamples, 2, 2, 2, nclasses], dtype=np.float32) if c == d: probs[:, :, :, :, c] = np.ones([nsamples, 2, 2, 2], dtype=np.float32) else: probs[:, :, :, :, c] = image probs[:, :, :, :, d] = 1 - image with tf.Session() as sess: sess.run(tf.global_variables_initializer()) res = sess.run([res_tf], feed_dict={probs_tf: probs}) res = res[0] res_x = np.abs(res[:, 0, 0, 0, :nclasses]) res_y = np.abs(res[:, 0, 0, 0, nclasses:2 * nclasses]) res_z = np.abs(res[:, 0, 0, 0, 2 * nclasses:]) res_vis = res_x + res_y + res_z plt.style.use("ggplot") # Save results plt.clf() res_vis = np.sum(res_vis, axis=1) fig = plt.figure(1) ax = plt.subplot(111, projection='polar') ax.plot(x_angles, res_vis) plt.tight_layout() plt.savefig('{}/{}/{}_to_{}.png'.format(fig_fold, classes[c], classes[c], classes[d]))
def applyRotEul(eul,ang,ax): return mat2euler(dot(angle_axis2mat(-ang,ax),euler2mat(*eul)))
def test_resample_to_output(): # Test routine to sample iamges to output space # Image aligned to output axes - no-op data = np.arange(24).reshape((2, 3, 4)) img = Nifti1Image(data, np.eye(4)) # Check default resampling img2 = resample_to_output(img) assert_array_equal(img2.shape, (2, 3, 4)) assert_array_equal(img2.affine, np.eye(4)) assert_array_equal(img2.dataobj, data) # Check resampling with different voxel size specifications for vox_sizes in (None, 1, [1, 1, 1]): img2 = resample_to_output(img, vox_sizes) assert_array_equal(img2.shape, (2, 3, 4)) assert_array_equal(img2.affine, np.eye(4)) assert_array_equal(img2.dataobj, data) img2 = resample_to_output(img, vox_sizes) # Check 2D works img_2d = Nifti1Image(data[0], np.eye(4)) for vox_sizes in (None, 1, (1, 1), (1, 1, 1)): img3 = resample_to_output(img_2d, vox_sizes) assert_array_equal(img3.shape, (3, 4, 1)) assert_array_equal(img3.affine, np.eye(4)) assert_array_equal(img3.dataobj, data[0][..., None]) # Even 1D img_1d = Nifti1Image(data[0, 0], np.eye(4)) img3 = resample_to_output(img_1d) assert_array_equal(img3.shape, (4, 1, 1)) assert_array_equal(img3.affine, np.eye(4)) assert_array_equal(img3.dataobj, data[0, 0][..., None, None]) # But 4D does not img_4d = Nifti1Image(data.reshape(2, 3, 2, 2), np.eye(4)) with pytest.raises(ValueError): resample_to_output(img_4d) # Run vox2vox_out tests, checking output shape, coordinate transform for in_shape, in_aff, vox, out_shape, out_aff in get_outspace_params(): # Allow for expansion of image shape from < 3D in_n_dim = len(in_shape) if in_n_dim < 3: in_shape = in_shape + (1,) * (3 - in_n_dim) if not vox is None: vox = vox + (1,) * (3 - in_n_dim) assert len(out_shape) == in_n_dim out_shape = out_shape + (1,) * (3 - in_n_dim) img = Nifti1Image(np.ones(in_shape), in_aff) out_img = resample_to_output(img, vox) assert_all_in(in_shape, in_aff, out_img.shape, out_img.affine) assert out_img.shape == out_shape assert_almost_equal(out_img.affine, out_aff) # Check data is as expected with some transforms # Flip first axis out_img = resample_to_output(Nifti1Image(data, np.diag([-1, 1, 1, 1]))) assert_array_equal(out_img.dataobj, np.flipud(data)) # Subsample voxels out_img = resample_to_output(Nifti1Image(data, np.diag([4, 5, 6, 1]))) exp_out = spnd.affine_transform(data, [1/4, 1/5, 1/6], output_shape = (5, 11, 19)) assert_array_equal(out_img.dataobj, exp_out) # Unsubsample with voxel sizes out_img = resample_to_output(Nifti1Image(data, np.diag([4, 5, 6, 1])), [4, 5, 6]) assert_array_equal(out_img.dataobj, data) # A rotation to test nearest, order, cval rot_3 = from_matvec(euler2mat(np.pi / 4), [0, 0, 0]) rot_3_img = Nifti1Image(data, rot_3) out_img = resample_to_output(rot_3_img) exp_shape = (4, 4, 4) assert out_img.shape == exp_shape exp_aff = np.array([[1, 0, 0, -2 * np.cos(np.pi / 4)], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) assert_almost_equal(out_img.affine, exp_aff) rzs, trans = to_matvec(np.dot(npl.inv(rot_3), exp_aff)) exp_out = spnd.affine_transform(data, rzs, trans, exp_shape) assert_almost_equal(out_img.dataobj, exp_out) # Order assert_almost_equal( resample_to_output(rot_3_img, order=0).dataobj, spnd.affine_transform(data, rzs, trans, exp_shape, order=0)) # Cval assert_almost_equal( resample_to_output(rot_3_img, cval=99).dataobj, spnd.affine_transform(data, rzs, trans, exp_shape, cval=99)) # Mode assert_almost_equal( resample_to_output(rot_3_img, mode='nearest').dataobj, spnd.affine_transform(data, rzs, trans, exp_shape, mode='nearest')) # out_class img_ni1 = Nifti2Image(data, np.eye(4)) img_ni2 = Nifti2Image(data, np.eye(4)) # Default is Nifti1Image assert resample_to_output(img_ni2).__class__ == Nifti1Image # Can be overriden assert resample_to_output(img_ni1, out_class=Nifti2Image).__class__ == Nifti2Image # None specifies out_class from input assert resample_to_output(img_ni2, out_class=None).__class__ == Nifti2Image
""" Make anatomical image with altered affine * Add some rotations and translations to affine; * Save as ``.nii`` file so SPM can read it. See ``resample_using_spm.m`` for processing of this generated image by SPM. """ import numpy as np import nibabel as nib from nibabel.eulerangles import euler2mat from nibabel.affines import from_matvec if __name__ == '__main__': img = nib.load('anatomical.nii') some_rotations = euler2mat(0.1, 0.2, 0.3) extra_affine = from_matvec(some_rotations, [3, 4, 5]) moved_anat = nib.Nifti1Image(img.dataobj, extra_affine.dot(img.affine), img.header) moved_anat.set_data_dtype(np.float32) nib.save(moved_anat, 'anat_moved.nii')
def applyRotEul(eul,ang,ax): "compose a rotation of ang around ax with rotation given by euler angles eul" return mat2euler(dot(angle_axis2mat(ang,ax),euler2mat(*eul)))
import numpy.linalg as npl from scipy.ndimage import affine_transform import nibabel as nib from nibabel.eulerangles import euler2mat img = nib.load('ds107_sub012_t1r2.nii') data = img.get_data() vol0 = data[..., 0] # The public volume x_rot, y_rot, z_rot = 0.1, 0.2, 0.3 Mx = euler2mat(x=x_rot) My = euler2mat(y=y_rot) Mz = euler2mat(z=z_rot) orig_to_new = Mz.dot(My).dot(Mx) new_to_orig = npl.inv(orig_to_new) rotated_vol0 = affine_transform(vol0, new_to_orig, order=1) new_img = nib.Nifti1Image(rotated_vol0, img.affine, img.header) nib.save(new_img, 'rotated_volume.nii') # The secret volume x_rot, y_rot, z_rot = 0.0, -0.1, 0.2 Mx = euler2mat(x=x_rot)
def applyRotEul(eul, ang, ax): return mat2euler(dot(angle_axis2mat(-ang, ax), euler2mat(*eul)))