def test_align(): """ Test align functionality """ import pkg_resources # Linear registration base_dir = os.path.abspath( pkg_resources.resource_filename("pynets", "../data/examples")) anat_dir = f"{base_dir}/003/anat" inp = f"{anat_dir}/sub-003_T1w_brain.nii.gz" ref = pkg_resources.resource_filename( "pynets", f"templates/MNI152_T1_brain_" f"2mm.nii.gz") out = f"{anat_dir}/highres2standard.nii.gz" xfm_out = f"{anat_dir}/highres2standard.mat" utils.align(inp, ref, xfm=xfm_out, out=out, dof=12, searchrad=True, bins=256, interp=None, cost="mutualinfo", sch=None, wmseg=None, init=None) highres2standard_linear = nib.load(out) assert highres2standard_linear is not None
def RegisterParcellation2MNIFunc_align(uatlas, template, template_mask, t1w_brain, t1w2mni_xfm, aligned_atlas_t1w, aligned_atlas_mni, t1w2mni_warp, simple): """ A function to perform atlas alignment from T1w atlas --> MNI. """ import time from pynets.registration import utils as regutils from nilearn.image import resample_to_img atlas_img = nib.load(uatlas) t1w_brain_img = nib.load(t1w_brain) uatlas_res_template = resample_to_img(atlas_img, t1w_brain_img, interpolation="nearest") uatlas_res_template = nib.Nifti1Image( np.asarray(uatlas_res_template.dataobj).astype('uint16'), affine=uatlas_res_template.affine, header=uatlas_res_template.header, ) nib.save(uatlas_res_template, aligned_atlas_t1w) if simple is False: try: regutils.apply_warp( template, aligned_atlas_t1w, aligned_atlas_mni, warp=t1w2mni_warp, interp="nn", sup=True, ) time.sleep(0.5) except BaseException: print("Warning: Atlas is not in correct dimensions, or input is " "low quality,\nusing linear template registration.") regutils.align( aligned_atlas_t1w, template, init=t1w2mni_xfm, out=aligned_atlas_mni, dof=6, searchrad=True, interp="nearestneighbour", cost="mutualinfo", ) time.sleep(0.5) else: regutils.align( aligned_atlas_t1w, template, init=t1w2mni_xfm, out=aligned_atlas_mni, dof=6, searchrad=True, interp="nearestneighbour", cost="mutualinfo", ) time.sleep(0.5) return aligned_atlas_mni
def tissue2dwi_align(self): """ A function to perform alignment of ventricle ROI's from MNI space --> dwi and CSF from T1w space --> dwi. First generates and performs dwi space alignment of avoidance/waypoint masks for tractography. First creates ventricle ROI. Then creates transforms from stock MNI template to dwi space. For this to succeed, must first have called both t1w2dwi_align. """ import sys import time import os.path as op import pkg_resources from pynets.core.utils import load_runconfig from nilearn.image import resample_to_img from nipype.utils.filemanip import fname_presuffix, copyfile from pynets.core.nodemaker import three_to_four_parcellation from nilearn.image import math_img, index_img hardcoded_params = load_runconfig() tiss_class = hardcoded_params['tracking']["tissue_classifier"][0] fa_template_path = pkg_resources.resource_filename( "pynets", f"templates/standard/FA_{self.vox_size}.nii.gz") if sys.platform.startswith('win') is False: try: fa_template_img = nib.load(fa_template_path) except indexed_gzip.ZranError as e: print( e, f"\nCannot load FA template. Do you have git-lfs " f"installed?") else: try: fa_template_img = nib.load(fa_template_path) except ImportError as e: print(e, f"\nCannot load FA template. Do you have git-lfs ") mni_template_img = nib.load(self.input_mni_brain) if not np.allclose(fa_template_img.affine, mni_template_img.affine) \ or not \ np.allclose(fa_template_img.shape, mni_template_img.shape): fa_template_img_res = resample_to_img(fa_template_img, mni_template_img) nib.save(fa_template_img_res, self.fa_template_res) else: self.fa_template_res = fname_presuffix(fa_template_path, suffix="_tmp", newpath=op.dirname( self.reg_path_img)) copyfile(fa_template_path, self.fa_template_res, copy=True, use_hardlink=False) # Register Lateral Ventricles and Corpus Callosum rois to t1w resample_to_img(nib.load(self.mni_atlas), nib.load(self.input_mni_brain), interpolation='nearest').to_filename(self.mni_roi_ref) roi_parcels = three_to_four_parcellation(self.mni_roi_ref) ventricle_roi = math_img("img1 + img2", img1=index_img(roi_parcels, 2), img2=index_img(roi_parcels, 13)) self.mni_vent_loc = fname_presuffix(self.mni_vent_loc, suffix="_tmp", newpath=op.dirname( self.reg_path_img)) ventricle_roi.to_filename(self.mni_vent_loc) del roi_parcels, ventricle_roi # Create transform from the HarvardOxford atlas in MNI to T1w. # This will be used to transform the ventricles to dwi space. regutils.align( self.mni_roi_ref, self.input_mni_brain, xfm=self.xfm_roi2mni_init, init=None, bins=None, dof=6, cost="mutualinfo", searchrad=True, interp="spline", out=None, ) # Create transform to align roi to mni and T1w using flirt regutils.applyxfm( self.input_mni_brain, self.mni_vent_loc, self.xfm_roi2mni_init, self.vent_mask_mni, ) time.sleep(0.5) if self.simple is False: # Apply warp resulting from the inverse MNI->T1w created earlier regutils.apply_warp( self.t1w_brain, self.vent_mask_mni, self.vent_mask_t1w, warp=self.mni2t1w_warp, interp="nn", sup=True, ) time.sleep(0.5) if sys.platform.startswith('win') is False: try: nib.load(self.corpuscallosum) except indexed_gzip.ZranError as e: print( e, f"\nCannot load Corpus Callosum ROI. " f"Do you have git-lfs installed?") else: try: nib.load(self.corpuscallosum) except ImportError as e: print( e, f"\nCannot load Corpus Callosum ROI. " f"Do you have git-lfs installed?") regutils.apply_warp( self.t1w_brain, self.corpuscallosum, self.corpuscallosum_mask_t1w, warp=self.mni2t1w_warp, interp="nn", sup=True, ) else: regutils.applyxfm(self.vent_mask_mni, self.t1w_brain, self.mni2t1_xfm, self.vent_mask_t1w) time.sleep(0.5) regutils.applyxfm( self.corpuscallosum, self.t1w_brain, self.mni2t1_xfm, self.corpuscallosum_mask_t1w, ) time.sleep(0.5) # Applyxfm to map FA template image to T1w space regutils.applyxfm(self.t1w_brain, self.fa_template_res, self.mni2t1_xfm, self.fa_template_t1w) time.sleep(0.5) # Applyxfm tissue maps to dwi space if self.t1w_brain_mask is not None: regutils.applyxfm( self.ap_path, self.t1w_brain_mask, self.t1wtissue2dwi_xfm, self.t1w_brain_mask_in_dwi, ) time.sleep(0.5) regutils.applyxfm(self.ap_path, self.vent_mask_t1w, self.t1wtissue2dwi_xfm, self.vent_mask_dwi) time.sleep(0.5) regutils.applyxfm(self.ap_path, self.csf_mask, self.t1wtissue2dwi_xfm, self.csf_mask_dwi) time.sleep(0.5) regutils.applyxfm(self.ap_path, self.gm_mask, self.t1wtissue2dwi_xfm, self.gm_in_dwi) time.sleep(0.5) regutils.applyxfm(self.ap_path, self.wm_mask, self.t1wtissue2dwi_xfm, self.wm_in_dwi) time.sleep(0.5) regutils.applyxfm( self.ap_path, self.corpuscallosum_mask_t1w, self.t1wtissue2dwi_xfm, self.corpuscallosum_dwi, ) time.sleep(0.5) csf_thr = 0.95 wm_thr = 0.05 gm_thr = 0.05 # Threshold WM to binary in dwi space nib.save(math_img(f"img > {wm_thr}", img=nib.load(self.wm_in_dwi)), self.wm_in_dwi_bin) # Threshold GM to binary in dwi space nib.save(math_img(f"img > {gm_thr}", img=nib.load(self.gm_in_dwi)), self.gm_in_dwi_bin) # Threshold CSF to binary in dwi space nib.save(math_img(f"img > {csf_thr}", img=nib.load(self.csf_mask_dwi)), self.csf_mask_dwi_bin) # Threshold WM to binary in dwi space self.wm_in_dwi = regutils.apply_mask_to_image(self.wm_in_dwi, self.wm_in_dwi_bin, self.wm_in_dwi) # Threshold GM to binary in dwi space self.gm_in_dwi = regutils.apply_mask_to_image(self.gm_in_dwi, self.gm_in_dwi_bin, self.gm_in_dwi) # Threshold CSF to binary in dwi space self.csf_mask = regutils.apply_mask_to_image(self.csf_mask_dwi, self.csf_mask_dwi_bin, self.csf_mask_dwi) # Create ventricular CSF mask print("Creating Ventricular CSF mask...") math_img("(img1 + img2) > 0.0001", img1=nib.load(self.csf_mask_dwi), img2=nib.load(self.vent_mask_dwi)).to_filename( self.vent_csf_in_dwi) print("Creating Corpus Callosum mask...") math_img("(img1*img2 - img3) > 0.0001", img1=nib.load(self.corpuscallosum_dwi), img2=nib.load(self.wm_in_dwi_bin), img3=nib.load(self.vent_csf_in_dwi)).to_filename( self.corpuscallosum_dwi) # Create GM-WM interface image math_img("((img1*img2 + img3)*img4) > 0.0001", img1=nib.load(self.gm_in_dwi_bin), img2=nib.load(self.wm_in_dwi_bin), img3=nib.load(self.corpuscallosum_dwi), img4=nib.load(self.B0_mask)).to_filename( self.wm_gm_int_in_dwi) return
def t1w2dwi_align(self): """ A function to perform alignment from T1w_MNI --> DWI. Uses a local optimization cost function to get the two images close, and then uses bbr to obtain a good alignment of brain boundaries. Assumes input dwi is already preprocessed and brain extracted. """ import time self.ap_path = regutils.apply_mask_to_image(self.ap_path, self.B0_mask, self.ap_path) self.fa_path = regutils.apply_mask_to_image(self.fa_path, self.B0_mask, self.fa_path) # Align T1w-->DWI regutils.align( self.ap_path, self.t1w_brain, xfm=self.t1w2dwi_xfm, bins=None, interp="spline", dof=6, cost="mutualinfo", out=None, searchrad=True, sch=None, ) time.sleep(0.5) self.dwi2t1w_xfm = regutils.invert_xfm(self.t1w2dwi_xfm, self.dwi2t1w_xfm) time.sleep(0.5) if self.simple is False: # Flirt bbr try: print("Learning a Boundary-Based Mapping from T1w-->DWI ...") regutils.align( self.fa_path, self.t1w_brain, wmseg=self.wm_edge, xfm=self.dwi2t1w_bbr_xfm, init=self.dwi2t1w_xfm, bins=256, dof=7, searchrad=True, interp="spline", out=None, cost="bbr", sch="${FSLDIR}/etc/flirtsch/bbr.sch", ) time.sleep(0.5) self.t1w2dwi_bbr_xfm = regutils.invert_xfm( self.dwi2t1w_bbr_xfm, self.t1w2dwi_bbr_xfm) time.sleep(0.5) # Apply the alignment regutils.align( self.t1w_brain, self.ap_path, init=self.t1w2dwi_bbr_xfm, xfm=self.t1wtissue2dwi_xfm, bins=None, interp="spline", dof=6, cost="mutualinfo", out=self.t1w2dwi, searchrad=True, sch=None, ) time.sleep(0.5) except BaseException: # Apply the alignment regutils.align( self.t1w_brain, self.ap_path, init=self.t1w2dwi_xfm, xfm=self.t1wtissue2dwi_xfm, bins=None, interp="spline", dof=6, cost="mutualinfo", out=self.t1w2dwi, searchrad=True, sch=None, ) time.sleep(0.5) else: # Apply the alignment regutils.align( self.t1w_brain, self.ap_path, init=self.t1w2dwi_xfm, xfm=self.t1wtissue2dwi_xfm, bins=None, interp="spline", dof=6, cost="mutualinfo", out=self.t1w2dwi, searchrad=True, sch=None, ) time.sleep(0.5) self.t1w2dwi = regutils.apply_mask_to_image(self.t1w2dwi, self.B0_mask, self.t1w2dwi) return
def t1w2mni_align(self): """ A function to perform alignment from T1w --> MNI template. """ import time # Create linear transform/ initializer T1w-->MNI regutils.align( self.t1w_brain, self.input_mni_brain, xfm=self.t12mni_xfm_init, bins=None, interp="spline", out=None, dof=12, cost="mutualinfo", searchrad=True, ) time.sleep(0.5) # Attempt non-linear registration of T1 to MNI template if self.simple is False: try: print(f"Learning a non-linear mapping from T1w --> " f"{self.template_name} ...") # Use FNIRT to nonlinearly align T1 to MNI template regutils.align_nonlinear( self.t1w_brain, self.input_mni, xfm=self.t12mni_xfm_init, out=self.t1_aligned_mni, warp=self.warp_t1w2mni, ref_mask=self.input_mni_mask, ) time.sleep(0.5) # Get warp from MNI -> T1 regutils.inverse_warp(self.t1w_brain, self.mni2t1w_warp, self.warp_t1w2mni) time.sleep(0.5) # Get mat from MNI -> T1 self.mni2t1_xfm = regutils.invert_xfm(self.t12mni_xfm_init, self.mni2t1_xfm) time.sleep(0.5) except BaseException: # Falling back to linear registration regutils.align( self.t1w_brain, self.input_mni_brain, xfm=self.mni2t1_xfm, init=self.t12mni_xfm_init, bins=None, dof=12, cost="mutualinfo", searchrad=True, interp="spline", out=self.t1_aligned_mni, sch=None, ) time.sleep(0.5) # Get mat from MNI -> T1 self.mni2t1_xfm = regutils.invert_xfm(self.t12mni_xfm, self.mni2t1_xfm) time.sleep(0.5) else: # Falling back to linear registration regutils.align( self.t1w_brain, self.input_mni_brain, xfm=self.t12mni_xfm, init=self.t12mni_xfm_init, bins=None, dof=12, cost="mutualinfo", searchrad=True, interp="spline", out=self.t1_aligned_mni, sch=None, ) time.sleep(0.5) # Get mat from MNI -> T1 self.t12mni_xfm = regutils.invert_xfm(self.mni2t1_xfm, self.t12mni_xfm) time.sleep(0.5)
def tissue2dwi_align(self): """ A function to perform alignment of ventricle ROI's from MNI space --> dwi and CSF from T1w space --> dwi. First generates and performs dwi space alignment of avoidance/waypoint masks for tractography. First creates ventricle ROI. Then creates transforms from stock MNI template to dwi space. For this to succeed, must first have called both t1w2dwi_align. """ import sys import time import os.path as op import pkg_resources from pynets.core.utils import load_runconfig from nilearn.image import resample_to_img hardcoded_params = load_runconfig() tiss_class = hardcoded_params['tracking']["tissue_classifier"][0] fa_template_path = pkg_resources.resource_filename( "pynets", f"templates/FA_{self.vox_size}.nii.gz") if sys.platform.startswith('win') is False: try: fa_template_img = nib.load(fa_template_path) except indexed_gzip.ZranError as e: print( e, f"\nCannot load FA template. Do you have git-lfs " f"installed?") else: try: fa_template_img = nib.load(fa_template_path) except ImportError as e: print(e, f"\nCannot load FA template. Do you have git-lfs ") mni_template_img = nib.load(self.input_mni_brain) fa_template_img_res = resample_to_img(fa_template_img, mni_template_img) nib.save(fa_template_img_res, self.fa_template_res) # Register Lateral Ventricles and Corpus Callosum rois to t1w if not op.isfile(self.mni_atlas): raise FileNotFoundError("FSL atlas for ventricle reference not" " found!") # Create transform to MNI atlas to T1w using flirt. This will be use to # transform the ventricles to dwi space. regutils.align( self.mni_atlas, self.input_mni_brain, xfm=self.xfm_roi2mni_init, init=None, bins=None, dof=6, cost="mutualinfo", searchrad=True, interp="spline", out=None, ) time.sleep(0.5) if sys.platform.startswith('win') is False: try: nib.load(self.mni_vent_loc) except indexed_gzip.ZranError as e: print( e, f"\nCannot load ventricle ROI. Do you have git-lfs " f"installed?") else: try: nib.load(self.mni_vent_loc) except ImportError as e: print( e, f"\nCannot load ventricle ROI. Do you have git-lfs " f"installed?") # Create transform to align roi to mni and T1w using flirt regutils.applyxfm( self.input_mni_brain, self.mni_vent_loc, self.xfm_roi2mni_init, self.vent_mask_mni, ) time.sleep(0.5) if self.simple is False: # Apply warp resulting from the inverse MNI->T1w created earlier regutils.apply_warp( self.t1w_brain, self.vent_mask_mni, self.vent_mask_t1w, warp=self.mni2t1w_warp, interp="nn", sup=True, ) time.sleep(0.5) if sys.platform.startswith('win') is False: try: nib.load(self.corpuscallosum) except indexed_gzip.ZranError as e: print( e, f"\nCannot load Corpus Callosum ROI. " f"Do you have git-lfs installed?") else: try: nib.load(self.corpuscallosum) except ImportError as e: print( e, f"\nCannot load Corpus Callosum ROI. " f"Do you have git-lfs installed?") regutils.apply_warp( self.t1w_brain, self.corpuscallosum, self.corpuscallosum_mask_t1w, warp=self.mni2t1w_warp, interp="nn", sup=True, ) else: regutils.applyxfm(self.vent_mask_mni, self.t1w_brain, self.mni2t1_xfm, self.vent_mask_t1w) time.sleep(0.5) regutils.applyxfm( self.corpuscallosum, self.t1w_brain, self.mni2t1_xfm, self.corpuscallosum_mask_t1w, ) time.sleep(0.5) # Applyxfm to map FA template image to T1w space regutils.applyxfm(self.t1w_brain, self.fa_template_res, self.mni2t1_xfm, self.fa_template_t1w) time.sleep(0.5) # Applyxfm tissue maps to dwi space if self.t1w_brain_mask is not None: regutils.applyxfm( self.ap_path, self.t1w_brain_mask, self.t1wtissue2dwi_xfm, self.t1w_brain_mask_in_dwi, ) time.sleep(0.5) regutils.applyxfm(self.ap_path, self.vent_mask_t1w, self.t1wtissue2dwi_xfm, self.vent_mask_dwi) time.sleep(0.5) regutils.applyxfm(self.ap_path, self.csf_mask, self.t1wtissue2dwi_xfm, self.csf_mask_dwi) time.sleep(0.5) regutils.applyxfm(self.ap_path, self.gm_mask, self.t1wtissue2dwi_xfm, self.gm_in_dwi) time.sleep(0.5) regutils.applyxfm(self.ap_path, self.wm_mask, self.t1wtissue2dwi_xfm, self.wm_in_dwi) time.sleep(0.5) regutils.applyxfm( self.ap_path, self.corpuscallosum_mask_t1w, self.t1wtissue2dwi_xfm, self.corpuscallosum_dwi, ) time.sleep(0.5) if tiss_class == 'wb' or tiss_class == 'cmc': csf_thr = 0.50 wm_thr = 0.15 gm_thr = 0.10 else: csf_thr = 0.99 wm_thr = 0.10 gm_thr = 0.075 # Threshold WM to binary in dwi space thr_img = nib.load(self.wm_in_dwi) thr_img = math_img(f"img > {wm_thr}", img=thr_img) nib.save(thr_img, self.wm_in_dwi_bin) # Threshold GM to binary in dwi space thr_img = nib.load(self.gm_in_dwi) thr_img = math_img(f"img > {gm_thr}", img=thr_img) nib.save(thr_img, self.gm_in_dwi_bin) # Threshold CSF to binary in dwi space thr_img = nib.load(self.csf_mask_dwi) thr_img = math_img(f"img > {csf_thr}", img=thr_img) nib.save(thr_img, self.csf_mask_dwi_bin) # Threshold WM to binary in dwi space self.wm_in_dwi = regutils.apply_mask_to_image(self.wm_in_dwi, self.wm_in_dwi_bin, self.wm_in_dwi) time.sleep(0.5) # Threshold GM to binary in dwi space self.gm_in_dwi = regutils.apply_mask_to_image(self.gm_in_dwi, self.gm_in_dwi_bin, self.gm_in_dwi) time.sleep(0.5) # Threshold CSF to binary in dwi space self.csf_mask = regutils.apply_mask_to_image(self.csf_mask_dwi, self.csf_mask_dwi_bin, self.csf_mask_dwi) time.sleep(0.5) # Create ventricular CSF mask print("Creating Ventricular CSF mask...") os.system(f"fslmaths {self.vent_mask_dwi} -kernel sphere 10 -ero " f"-bin {self.vent_mask_dwi}") time.sleep(1) os.system(f"fslmaths {self.csf_mask_dwi} -add {self.vent_mask_dwi} " f"-bin {self.vent_csf_in_dwi}") time.sleep(1) print("Creating Corpus Callosum mask...") os.system( f"fslmaths {self.corpuscallosum_dwi} -mas {self.wm_in_dwi_bin} " f"-sub {self.vent_csf_in_dwi} " f"-bin {self.corpuscallosum_dwi}") time.sleep(1) # Create gm-wm interface image os.system(f"fslmaths {self.gm_in_dwi_bin} -mul {self.wm_in_dwi_bin} " f"-add {self.corpuscallosum_dwi} " f"-mas {self.B0_mask} -bin {self.wm_gm_int_in_dwi}") time.sleep(1) return