def create_tensor_pipeline(): """ Estimate diffusion tensor coefficients and compute FA :return: """ # Nodes inputnode = pe.Node( utility.IdentityInterface(fields=["diffusion_volume", "mask"], mandatory_inputs=False), name="inputnode", ) # tensor coefficients estimation diffusion2tensor = pe.Node(interface=mrtrix3.reconst.FitTensor(), name="diffusion2tensor") # derived FA contrast (force nifti format to do registration with FSL or Ants) tensor2fa = pe.Node(interface=mrtrix3.TensorMetrics(out_fa="fa.nii.gz"), name="tensor2fa") outputnode = pe.Node( utility.IdentityInterface(fields=["tensor_coeff", "fa"], mandatory_inputs=False), name="outputnode", ) # Workflow structure tensor = pe.Workflow(name="tensor") tensor.connect(inputnode, "diffusion_volume", diffusion2tensor, "in_file") tensor.connect(inputnode, "mask", diffusion2tensor, "in_mask") tensor.connect(diffusion2tensor, "out_file", tensor2fa, "in_file") tensor.connect(diffusion2tensor, "out_file", outputnode, "tensor_coeff") tensor.connect(tensor2fa, "out_fa", outputnode, "fa") return tensor
def calculate_metrics(in_file: Path, out_files: dict): """ Calculate various DWI metrics based on Diffusion's kurtosis tensor estimation. Parameters ---------- in_file : Path Path to preprocessed DWI series out_files : dict A dictionary containing paths to various metrics to be calculated """ tensor = out_files.pop("tensor") tsr = mrt.FitTensor() tsr.inputs.in_file = in_file tsr.inputs.out_file = tensor tsr.inputs.args = "-quiet" if not tensor.exists(): tsr.run() comp = mrt.TensorMetrics() comp.inputs.in_file = tensor comp_args = "" for key, val in out_files.items(): comp_args += f"-{key} {val} " comp.inputs.args = comp_args return tsr, comp
def fit_tensors(dwi_file: str, mask_file: str, dti_file: str): dilated_mask = mask_file.replace(".mif", "_dilated.mif") cmd = f"maskfilter {mask_file} dilate {dilated_mask} -npass 3" os.system(cmd) tsr = mrt.FitTensor() tsr.inputs.in_file = dwi_file tsr.inputs.in_mask = dilated_mask tsr.inputs.out_file = dti_file print(tsr.cmdline) tsr.run() comp = mrt.TensorMetrics() comp.inputs.in_file = dti_file comp.inputs.out_fa = dti_file.replace("dti", "fa") comp.inputs.args = "-force" print(comp.cmdline) comp.run() return comp.inputs.out_fa
def fit_tensors(dwi_file: Path, mask_file: Path, dti_file: Path, fa_file: Path): dilated_mask = mask_file.parent / f"{mask_file.stem}_dilated.mif" cmd = f"maskfilter {mask_file} dilate {dilated_mask} -npass 3" os.system(cmd) tsr = mrt.FitTensor() tsr.inputs.in_file = dwi_file tsr.inputs.in_mask = dilated_mask tsr.inputs.out_file = dti_file print(tsr.cmdline) tsr.run() comp = mrt.TensorMetrics() comp.inputs.in_file = dti_file comp.inputs.out_fa = fa_file print(comp.cmdline) comp.run() dti_file.unlink() return comp.inputs.out_fa
# Data conversion from .nii to .mif file (allows to embed diffusion bvals et bvecs) mrconvert = pe.Node(interface=mrtrix3.MRConvert(), name="mrconvert") # Bias correction of the diffusion MRI data (for more quantitative approach) dwibiascorrect = pe.Node(interface=mrtrix3.preprocess.DWIBiasCorrect(), name="dwibiascorrect") dwibiascorrect.use_ants = True # gross brain mask stemming from DWI data dwi2mask = pe.Node(interface=mrtrix3.utils.BrainMask(), name="dwi2mask") # tensor coefficients estimation dwi2tensor = pe.Node(interface=mrtrix3.reconst.FitTensor(), name="dwi2tensor") # derived FA contrast for registration tensor2fa = pe.Node(interface=mrtrix3.TensorMetrics(), name="tensor2fa") # Tissue classification from T1 MRI data tissue_classif = pe.Node(interface=mrtrix3.Generate5tt(), name="tissue_classif") # rely on FSL for T1 tissue segmentation tissue_classif.inputs.algorithm = "fsl" # impulsionnal response estimation dwi2response = pe.Node(interface=mrtrix3.preprocess.ResponseSD(), name="dwi2response") dwi2response.inputs.algorithm = "msmt_5tt" # Multi-shell multi tissue spherical deconvolution of the diffusion MRI data dwi2fod = pe.Node( interface=mrtrix3.reconst.ConstrainedSphericalDeconvolution(),
def dholl_preproc_wf(shells=[0, 1000, 2000], lmax=[0, 8, 8], sshell=False, noreorient=False, template_dir=None, template_label=None, wdir=None, nthreads=1, name='dholl_preproc_wf'): """ Set up Dhollander response preproc workflow No assumption of registration to T1w space is made """ if template_dir is None or template_label is None: print("Missing template info") raise IOError # Grab template data templateGrabber = io.getTemplate(template_dir=template_dir, template_label=template_label, wdir=wdir) # Convert nii to mif dwiConvert = pe.Node(mrt.MRConvert(), name='dwiConvert') dwiConvert.base_dir = wdir dwiConvert.inputs.nthreads = nthreads dwiConvert.interface.num_threads = nthreads # dwi2response - included but not used dwi2response = pe.Node(mrt.ResponseSD(), name='dwi2response') dwi2response.base_dir = wdir dwi2response.inputs.algorithm = 'dhollander' dwi2response.inputs.wm_file = 'space-dwi_model-CSD_WMResp.txt' dwi2response.inputs.gm_file = 'space-dwi_model-CSD_GMResp.txt' dwi2response.inputs.csf_file = 'space-dwi_model-CSD_CSFResp.txt' dwi2response.inputs.max_sh = lmax dwi2response.inputs.shell = shells dwi2response.inputs.nthreads = nthreads dwi2response.interface.num_threads = nthreads # Convert mask (nii) to mif maskConvert = pe.Node(mrt.MRConvert(), name='maskConvert') maskConvert.base_dir = wdir maskConvert.inputs.nthreads = nthreads maskConvert.interface.num_threads = nthreads # dwi2fod dwi2fod = pe.Node(mrt.EstimateFOD(), name='dwi2fod') dwi2fod.base_dir = wdir dwi2fod.inputs.algorithm = 'msmt_csd' dwi2fod.inputs.shell = shells dwi2fod.inputs.wm_odf = 'space-dwi_model-CSD_WMFOD.mif' if sshell is False: dwi2fod.inputs.gm_odf = 'space-dwi_model-CSD_GMFOD.mif' dwi2fod.inputs.csf_odf = 'space-dwi_model-CSD_CSFFOD.mif' dwi2fod.inputs.nthreads = nthreads dwi2fod.interface.num_threads = nthreads # mtnormalise mtnormalise = pe.Node(mrt.MTNormalise(), name='mtnormalise') mtnormalise.base_dir = wdir mtnormalise.inputs.out_wm = 'space-dwi_model-CSD_WMFODNorm.mif' if sshell is False: mtnormalise.inputs.out_gm = 'space-dwi_model-CSD_GMFODNorm.mif' mtnormalise.inputs.out_csf = 'space-dwi_model-CSD_CSFFODNorm.mif' mtnormalise.inputs.nthreads = nthreads mtnormalise.interface.num_threads = nthreads # Registration MRRegister = pe.Node(mrt.MRRegister(), name='MRRegister') MRRegister.base_dir = wdir # MRRegister.inputs.ref_file = template MRRegister.inputs.nl_warp = [ 'from-dwi_to-Template_xfm.mif', 'from-Template_to-dwi_xfm.mif' ] if noreorient is not False: MRRegister.inputs.noreorientation = noreorient MRRegister.inputs.nthreads = nthreads MRRegister.interface.num_threads = nthreads # Transforms WarpSelect1 = pe.Node(niu.Select(), name='WarpSelect1') WarpSelect1.base_dir = wdir WarpSelect1.inputs.index = [0] WarpSelect1.interface.num_threads = nthreads WarpSelect2 = pe.Node(niu.Select(), name='WarpSelect2') WarpSelect2.base_dir = wdir WarpSelect2.inputs.index = [1] WarpSelect2.interface.num_threads = nthreads # Warp data MaskTransform = pe.Node(mrt.MRTransform(), name='MaskTransform') MaskTransform.base_dir = wdir MaskTransform.inputs.out_file = 'space-Template_brainmask.mif' MaskTransform.inputs.nthreads = nthreads MaskTransform.interface.num_threads = nthreads FODTransform = pe.Node(mrt.MRTransform(), name='FODTransform') FODTransform.base_dir = wdir FODTransform.inputs.out_file = 'space-Template_model-CSD_WMFODNorm.mif' FODTransform.inputs.nthreads = nthreads FODTransform.interface.num_threads = nthreads # Tensor processing DWINormalise = pe.Node(mrt.DWINormalise(), name='DWINormalise') DWINormalise.base_dir = wdir DWINormalise.inputs.out_file = 'space-dwi_dwiNorm.mif' DWINormalise.inputs.nthreads = nthreads DWINormalise.interface.num_threads = nthreads DWITransform = pe.Node(mrt.MRTransform(), name='DWITransform') DWITransform.base_dir = wdir DWITransform.inputs.out_file = 'space-Template_dwiNorm.mif' DWITransform.inputs.nthreads = nthreads DWITransform.interface.num_threads = nthreads FitTensor = pe.Node(mrt.FitTensor(), name='FitTensor') FitTensor.base_dir = wdir FitTensor.inputs.out_file = 'space-Template_desc-WLS_model-DTI_tensor.mif' FitTensor.inputs.nthreads = nthreads FitTensor.interface.num_threads = nthreads TensorMetrics = pe.Node(mrt.TensorMetrics(), name='TensorMetrics') TensorMetrics.base_dir = wdir TensorMetrics.inputs.out_fa = 'space-Template_model-DTI_FA.mif' TensorMetrics.inputs.out_adc = 'space-Template_model-DTI_MD.mif' TensorMetrics.inputs.out_ad = 'space-Template_model-DTI_AD.mif' TensorMetrics.inputs.out_rd = 'space-Template_model-DTI_RD.mif' TensorMetrics.inputs.nthreads = nthreads TensorMetrics.interface.num_threads = nthreads # Build workflow workflow = pe.Workflow(name=name) # Single shell if sshell is True: workflow.connect([ # Compute FOD (dwiConvert, dwi2response, [('out_file', 'in_file')]), (dwiConvert, dwi2fod, [('out_file', 'in_file')]), (dwi2response, dwi2fod, [('wm_file', 'wm_txt'), ('csf_file', 'csf_txt')]), (dwi2fod, mtnormalise, [('wm_odf', 'in_wm'), ('csf_odf', 'in_csf')]), (maskConvert, dwi2response, [('out_file', 'in_mask')]), (maskConvert, dwi2fod, [('out_file', 'mask_file')]), (maskConvert, mtnormalise, [('out_file', 'mask')]), (maskConvert, MRRegister, [('out_file', 'mask1')]), (templateGrabber, MRRegister, [('wm_fod', 'ref_file'), ('mask', 'mask2')]), (mtnormalise, MRRegister, [('out_wm', 'in_file')]), (MRRegister, WarpSelect1, [('nl_warp', 'inlist')]), (MRRegister, WarpSelect2, [('nl_warp', 'inlist')]), (maskConvert, MaskTransform, [('out_file', 'in_file')]), (WarpSelect1, MaskTransform, [('out', 'warp')]), (mtnormalise, FODTransform, [('out_wm', 'in_file')]), (WarpSelect1, FODTransform, [('out', 'warp')]), # Compute tensors (dwiConvert, DWINormalise, [('out_file', 'in_file')]), (maskConvert, DWINormalise, [('out_file', 'in_mask')]), (DWINormalise, DWITransform, [('out_file', 'in_file')]), (WarpSelect1, DWITransform, [('out', 'warp')]), (DWITransform, FitTensor, [('out_file', 'in_file')]), (MaskTransform, FitTensor, [('out_file', 'in_mask')]), (FitTensor, TensorMetrics, [('out_file', 'in_file')]), (MaskTransform, TensorMetrics, [('out_file', 'in_mask')]) ]) # For multi-shell else: workflow.connect([ # Compute FOD (dwiConvert, dwi2response, [('out_file', 'in_file')]), (dwiConvert, dwi2fod, [('out_file', 'in_file')]), (dwi2response, dwi2fod, [('wm_file', 'wm_txt'), ('gm_file', 'gm_txt'), ('csf_file', 'csf_txt')]), (dwi2fod, mtnormalise, [('wm_odf', 'in_wm'), ('gm_odf', 'in_gm'), ('csf_odf', 'in_csf')]), (maskConvert, dwi2response, [('out_file', 'in_mask')]), (maskConvert, dwi2fod, [('out_file', 'mask_file')]), (maskConvert, mtnormalise, [('out_file', 'mask')]), (maskConvert, MRRegister, [('out_file', 'mask1')]), (templateGrabber, MRRegister, [('wm_fod', 'ref_file'), ('mask', 'mask2')]), (mtnormalise, MRRegister, [('out_wm', 'in_file')]), (MRRegister, WarpSelect1, [('nl_warp', 'inlist')]), (MRRegister, WarpSelect2, [('nl_warp', 'inlist')]), (maskConvert, MaskTransform, [('out_file', 'in_file')]), (WarpSelect1, MaskTransform, [('out', 'warp')]), (mtnormalise, FODTransform, [('out_wm', 'in_file')]), (WarpSelect1, FODTransform, [('out', 'warp')]), # Compute tensors (dwiConvert, DWINormalise, [('out_file', 'in_file')]), (maskConvert, DWINormalise, [('out_file', 'in_mask')]), (DWINormalise, DWITransform, [('out_file', 'in_file')]), (WarpSelect1, DWITransform, [('out', 'warp')]), (DWITransform, FitTensor, [('out_file', 'in_file')]), (MaskTransform, FitTensor, [('out_file', 'in_mask')]), (FitTensor, TensorMetrics, [('out_file', 'in_file')]), (MaskTransform, TensorMetrics, [('out_file', 'in_mask')]) ]) return workflow