def test_transform_origins_3d(): # Create arbitrary image-to-space transforms axis = np.array([.5, 2.0, 1.5]) t = 0.15 # translation factor for theta in [-1 * np.pi / 6.0, 0.0, np.pi / 5.0]: # rotation angle for s in [0.83, 1.3, 2.07]: # scale m_shapes = [(256, 256, 128), (255, 255, 127), (64, 127, 142)] for shape_moving in m_shapes: s_shapes = [(256, 256, 128), (255, 255, 127), (64, 127, 142)] for shape_static in s_shapes: moving = np.ndarray(shape=shape_moving) static = np.ndarray(shape=shape_static) trans = np.array([[1, 0, 0, -t * shape_static[0]], [0, 1, 0, -t * shape_static[1]], [0, 0, 1, -t * shape_static[2]], [0, 0, 0, 1]]) trans_inv = npl.inv(trans) rot = np.zeros(shape=(4, 4)) rot[:3, :3] = geometry.rodrigues_axis_rotation(axis, theta) rot[3, 3] = 1.0 scale = np.array([[1 * s, 0, 0, 0], [0, 1 * s, 0, 0], [0, 0, 1 * s, 0], [0, 0, 0, 1]]) static_grid2world = trans_inv.dot( scale.dot(rot.dot(trans))) moving_grid2world = npl.inv(static_grid2world) # Expected translation c_static = static_grid2world[:3, 3] c_moving = moving_grid2world[:3, 3] expected = np.eye(4) expected[:3, 3] = c_moving - c_static # Implementation under test actual = imaffine.transform_origins(static, static_grid2world, moving, moving_grid2world) assert_array_almost_equal(actual.affine, expected)
transform_origins) from dipy.align.transforms import (TranslationTransform3D, RigidTransform3D, AffineTransform3D) static = np.asarray(img_t2_mni.dataobj) static_affine = img_t2_mni.affine moving = mean_b0_masked_stanford moving_affine = hardi_img.affine """ We estimate an affine that maps the origin of the moving image to that of the static image. We can then use this later to account for the offsets of each image. """ affine_map = transform_origins(static, static_affine, moving, moving_affine) """ We specify the mismatch metric: """ nbins = 32 sampling_prop = None metric = MutualInformationMetric(nbins, sampling_prop) """ As well as the optimization strategy: """ level_iters = [10, 10, 5] sigmas = [3.0, 1.0, 0.0]
def wm_syn(t1w_brain, ap_path, working_dir, fa_path=None, template_fa_path=None): """ A function to perform SyN registration Parameters ---------- t1w_brain : str File path to the skull-stripped T1w brain Nifti1Image. ap_path : str File path to the AP moving image. working_dir : str Path to the working directory to perform SyN and save outputs. fa_path : str File path to the FA moving image. template_fa_path : str File path to the T1w-connformed template FA reference image. """ import uuid from time import strftime from dipy.align.imaffine import ( MutualInformationMetric, AffineRegistration, transform_origins, ) from dipy.align.transforms import ( TranslationTransform3D, RigidTransform3D, AffineTransform3D, ) from dipy.align.imwarp import SymmetricDiffeomorphicRegistration from dipy.align.metrics import CCMetric # from dipy.viz import regtools # from nilearn.image import resample_to_img ap_img = nib.load(ap_path) t1w_brain_img = nib.load(t1w_brain) static = np.asarray(t1w_brain_img.dataobj, dtype=np.float32) static_affine = t1w_brain_img.affine moving = np.asarray(ap_img.dataobj, dtype=np.float32) moving_affine = ap_img.affine affine_map = transform_origins(static, static_affine, moving, moving_affine) nbins = 32 sampling_prop = None metric = MutualInformationMetric(nbins, sampling_prop) level_iters = [10, 10, 5] sigmas = [3.0, 1.0, 0.0] factors = [4, 2, 1] affine_reg = AffineRegistration(metric=metric, level_iters=level_iters, sigmas=sigmas, factors=factors) transform = TranslationTransform3D() params0 = None translation = affine_reg.optimize(static, moving, transform, params0, static_affine, moving_affine) transform = RigidTransform3D() rigid_map = affine_reg.optimize( static, moving, transform, params0, static_affine, moving_affine, starting_affine=translation.affine, ) transform = AffineTransform3D() # We bump up the iterations to get a more exact fit: affine_reg.level_iters = [1000, 1000, 100] affine_opt = affine_reg.optimize( static, moving, transform, params0, static_affine, moving_affine, starting_affine=rigid_map.affine, ) # We now perform the non-rigid deformation using the Symmetric # Diffeomorphic Registration(SyN) Algorithm: metric = CCMetric(3) level_iters = [10, 10, 5] # Refine fit if template_fa_path is not None: from nilearn.image import resample_to_img fa_img = nib.load(fa_path) template_img = nib.load(template_fa_path) template_img_res = resample_to_img(template_img, t1w_brain_img) static = np.asarray(template_img_res.dataobj, dtype=np.float32) static_affine = template_img_res.affine moving = np.asarray(fa_img.dataobj, dtype=np.float32) moving_affine = fa_img.affine else: static = np.asarray(t1w_brain_img.dataobj, dtype=np.float32) static_affine = t1w_brain_img.affine moving = np.asarray(ap_img.dataobj, dtype=np.float32) moving_affine = ap_img.affine sdr = SymmetricDiffeomorphicRegistration(metric, level_iters) mapping = sdr.optimize(static, moving, static_affine, moving_affine, affine_opt.affine) warped_moving = mapping.transform(moving) # Save warped FA image run_uuid = f"{strftime('%Y%m%d_%H%M%S')}_{uuid.uuid4()}" warped_fa = f"{working_dir}/warped_fa_{run_uuid}.nii.gz" nib.save(nib.Nifti1Image(warped_moving, affine=static_affine), warped_fa) # # We show the registration result with: # regtools.overlay_slices(static, warped_moving, None, 0, # "Static", "Moving", # "%s%s%s%s" % (working_dir, # "/transformed_sagittal_", run_uuid, ".png")) # regtools.overlay_slices(static, warped_moving, None, # 1, "Static", "Moving", # "%s%s%s%s" % (working_dir, # "/transformed_coronal_", run_uuid, ".png")) # regtools.overlay_slices(static, warped_moving, # None, 2, "Static", "Moving", # "%s%s%s%s" % (working_dir, # "/transformed_axial_", run_uuid, ".png")) return mapping, affine_map, warped_fa
def wm_syn(template_path, fa_path, working_dir): """ A function to perform ANTS SyN registration Parameters ---------- template_path : str File path to the template reference image. fa_path : str File path to the FA moving image. working_dir : str Path to the working directory to perform SyN and save outputs. """ import uuid from time import strftime from dipy.align.imaffine import MutualInformationMetric, AffineRegistration, transform_origins from dipy.align.transforms import TranslationTransform3D, RigidTransform3D, AffineTransform3D from dipy.align.imwarp import SymmetricDiffeomorphicRegistration from dipy.align.metrics import CCMetric from dipy.viz import regtools fa_img = nib.load(fa_path) template_img = nib.load(template_path) static = np.asarray(template_img.dataobj) static_affine = template_img.affine moving = np.asarray(fa_img.dataobj).astype(np.float32) moving_affine = fa_img.affine affine_map = transform_origins(static, static_affine, moving, moving_affine) nbins = 32 sampling_prop = None metric = MutualInformationMetric(nbins, sampling_prop) level_iters = [10, 10, 5] sigmas = [3.0, 1.0, 0.0] factors = [4, 2, 1] affine_reg = AffineRegistration(metric=metric, level_iters=level_iters, sigmas=sigmas, factors=factors) transform = TranslationTransform3D() params0 = None translation = affine_reg.optimize(static, moving, transform, params0, static_affine, moving_affine) transform = RigidTransform3D() rigid_map = affine_reg.optimize(static, moving, transform, params0, static_affine, moving_affine, starting_affine=translation.affine) transform = AffineTransform3D() # We bump up the iterations to get a more exact fit: affine_reg.level_iters = [1000, 1000, 100] affine_opt = affine_reg.optimize(static, moving, transform, params0, static_affine, moving_affine, starting_affine=rigid_map.affine) # We now perform the non-rigid deformation using the Symmetric Diffeomorphic Registration(SyN) Algorithm: metric = CCMetric(3) level_iters = [10, 10, 5] sdr = SymmetricDiffeomorphicRegistration(metric, level_iters) mapping = sdr.optimize(static, moving, static_affine, moving_affine, affine_opt.affine) warped_moving = mapping.transform(moving) # Save warped FA image run_uuid = '%s_%s' % (strftime('%Y%m%d_%H%M%S'), uuid.uuid4()) warped_fa = '{}/warped_fa_{}.nii.gz'.format(working_dir, run_uuid) nib.save(nib.Nifti1Image(warped_moving, affine=static_affine), warped_fa) # We show the registration result with: regtools.overlay_slices( static, warped_moving, None, 0, "Static", "Moving", "%s%s%s%s" % (working_dir, "/transformed_sagittal_", run_uuid, ".png")) regtools.overlay_slices( static, warped_moving, None, 1, "Static", "Moving", "%s%s%s%s" % (working_dir, "/transformed_coronal_", run_uuid, ".png")) regtools.overlay_slices( static, warped_moving, None, 2, "Static", "Moving", "%s%s%s%s" % (working_dir, "/transformed_axial_", run_uuid, ".png")) return mapping, affine_map, warped_fa
def wm_syn(template_path, fa_path, working_dir): """A function to perform ANTS SyN registration using dipy functions Parameters ---------- template_path : str File path to the template reference FA image. fa_path : str File path to the FA moving image (image to be fitted to reference) working_dir : str Path to the working directory to perform SyN and save outputs. Returns ------- DiffeomorphicMap An object that can be used to register images back and forth between static (template) and moving (FA) domains AffineMap An object used to transform the moving (FA) image towards the static image (template) """ fa_img = nib.load(fa_path) template_img = nib.load(template_path) static = template_img.get_data() static_affine = template_img.affine moving = fa_img.get_data().astype(np.float32) moving_affine = fa_img.affine affine_map = transform_origins(static, static_affine, moving, moving_affine) nbins = 32 sampling_prop = None metric = MutualInformationMetric(nbins, sampling_prop) level_iters = [10, 10, 5] sigmas = [3.0, 1.0, 0.0] factors = [4, 2, 1] affine_reg = AffineRegistration(metric=metric, level_iters=level_iters, sigmas=sigmas, factors=factors) transform = TranslationTransform3D() params0 = None translation = affine_reg.optimize(static, moving, transform, params0, static_affine, moving_affine) transform = RigidTransform3D() rigid_map = affine_reg.optimize( static, moving, transform, params0, static_affine, moving_affine, starting_affine=translation.affine, ) transform = AffineTransform3D() # We bump up the iterations to get a more exact fit: affine_reg.level_iters = [1000, 1000, 100] affine_opt = affine_reg.optimize( static, moving, transform, params0, static_affine, moving_affine, starting_affine=rigid_map.affine, ) # We now perform the non-rigid deformation using the Symmetric Diffeomorphic Registration(SyN) Algorithm: metric = CCMetric(3) level_iters = [10, 10, 5] sdr = SymmetricDiffeomorphicRegistration(metric, level_iters) mapping = sdr.optimize(static, moving, static_affine, moving_affine, affine_opt.affine) warped_moving = mapping.transform(moving) # We show the registration result with: regtools.overlay_slices( static, warped_moving, None, 0, "Static", "Moving", f"{working_dir}/transformed_sagittal.png", ) regtools.overlay_slices( static, warped_moving, None, 1, "Static", "Moving", f"{working_dir}/transformed_coronal.png", ) regtools.overlay_slices( static, warped_moving, None, 2, "Static", "Moving", f"{working_dir}/transformed_axial.png", ) return mapping, affine_map