def register_affine(t_masked, m_masked, affreg=None, final_iters=(10000, 1000, 100)): """ Run affine registration between images `t_masked`, `m_masked` Parameters ---------- t_masked : image Template image object, with image data masked to set out-of-brain voxels to zero. m_masked : image Moving (individual) image object, with image data masked to set out-of-brain voxels to zero. affreg : None or AffineRegistration instance, optional AffineRegistration with which to register `m_masked` to `t_masked`. If None, we make an instance with default parameters. final_iters : tuple, optional Length 3 tuple of level iterations to use on final affine pass of the registration. Returns ------- affine : shape (4, 4) ndarray Final affine mapping from voxels in `t_masked` to voxels in `m_masked`. """ if affreg is None: metric = MutualInformationMetric(nbins=32, sampling_proportion=None) affreg = AffineRegistration(metric=metric) t_data = t_masked.get_data().astype(float) m_data = m_masked.get_data().astype(float) t_aff = t_masked.affine m_aff = m_masked.affine translation = affreg.optimize(t_data, m_data, TranslationTransform3D(), None, t_aff, m_aff) rigid = affreg.optimize(t_data, m_data, RigidTransform3D(), None, t_aff, m_aff, starting_affine=translation.affine) # Maybe bump up iterations for last step if final_iters is not None: affreg.level_iters = list(final_iters) affine = affreg.optimize(t_data, m_data, AffineTransform3D(), None, t_aff, m_aff, starting_affine=rigid.affine) return affine.affine
rigid_map = affine_reg.optimize(static, moving, transform, params0, static_affine, moving_affine, starting_affine=translation.affine) transformed = rigid_map.transform(moving) transform = AffineTransform3D() """ We bump up the iterations to get a more exact fit: """ affine_reg.level_iters = [1000, 1000, 100] highres_map = affine_reg.optimize(static, moving, transform, params0, static_affine, moving_affine, starting_affine=rigid_map.affine) transformed = highres_map.transform(moving) """ We now perform the non-rigid deformation using the Symmetric Diffeomorphic Registration (SyN) Algorithm proposed by Avants et al. [Avants09]_ (also implemented in the ANTs software [Avants11]_): """
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 img_reg(moving_img, target_img, reg='non-lin'): m_img = nib.load(moving_img) t_img = nib.load(target_img) m_img_data = m_img.get_data() t_img_data = t_img.get_data() m_img_affine = m_img.affine t_img_affine = t_img.affine identity = np.eye(4) affine_map = AffineMap(identity, t_img_data.shape, t_img_affine, m_img_data.shape, m_img_affine) m_img_resampled = affine_map.transform(m_img_data) c_of_mass = transform_centers_of_mass(t_img_data, t_img_affine, m_img_data, m_img_affine) tf_m_img_c_mass = c_of_mass.transform(m_img_data) 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] affreg = AffineRegistration(metric=metric, level_iters=level_iters, sigmas=sigmas, factors=factors) transform = TranslationTransform3D() params0 = None starting_affine = c_of_mass.affine translation = affreg.optimize(t_img_data, m_img_data, transform, params0, t_img_affine, m_img_affine, starting_affine=starting_affine) tf_m_img_translat = translation.transform(m_img_data) transform = RigidTransform3D() params0 = None starting_affine = translation.affine rigid = affreg.optimize(t_img_data, m_img_data, transform, params0, t_img_affine, m_img_affine, starting_affine=starting_affine) tf_m_img_rigid = rigid.transform(m_img_data) transform = AffineTransform3D() affreg.level_iters = [10, 10, 10] affine = affreg.optimize(t_img_data, m_img_data, transform, params0, t_img_affine, m_img_affine, starting_affine=rigid.affine) if reg is None or reg == 'non-lin': metric = CCMetric(3) level_iters = [10, 10, 5] sdr = SymmetricDiffeomorphicRegistration(metric, level_iters) mapping = sdr.optimize(t_img_data, m_img_data, t_img_affine, m_img_affine, affine.affine) tf_m_img = mapping.transform(m_img_data) elif reg == 'affine': tf_m_img_aff = affine.transform(m_img_data) return tf_m_img metric = CCMetric(3) level_iters = [10, 10, 5] sdr = SymmetricDiffeomorphicRegistration(metric, level_iters) mapping = sdr.optimize(t_img_data, m_img_data, t_img_affine, m_img_affine, starting_affine=affine.affine) tf_m_img = mapping.transform(m_img_data)
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