def test_Eddy_inputs(): input_map = dict(args=dict(argstr='%s', ), environ=dict(nohash=True, usedefault=True, ), flm=dict(argstr='--flm=%s', ), fwhm=dict(argstr='--fwhm=%s', ), ignore_exception=dict(nohash=True, usedefault=True, ), in_acqp=dict(argstr='--acqp=%s', mandatory=True, ), in_bval=dict(argstr='--bvals=%s', mandatory=True, ), in_bvec=dict(argstr='--bvecs=%s', mandatory=True, ), in_file=dict(argstr='--imain=%s', mandatory=True, ), in_index=dict(argstr='--index=%s', mandatory=True, ), in_mask=dict(argstr='--mask=%s', mandatory=True, ), in_topup_fieldcoef=dict(argstr='--topup=%s', requires=['in_topup_movpar'], ), in_topup_movpar=dict(requires=['in_topup_fieldcoef'], ), method=dict(argstr='--resamp=%s', ), niter=dict(argstr='--niter=%s', ), num_threads=dict(nohash=True, usedefault=True, ), out_base=dict(argstr='--out=%s', usedefault=True, ), output_type=dict(), repol=dict(argstr='--repol', ), session=dict(argstr='--session=%s', ), terminal_output=dict(mandatory=True, nohash=True, ), ) inputs = Eddy.input_spec() for key, metadata in input_map.items(): for metakey, value in metadata.items(): yield assert_equal, getattr(inputs.traits()[key], metakey), value
def test_Eddy_outputs(): output_map = dict(out_corrected=dict(), out_parameter=dict(), ) outputs = Eddy.output_spec() for key, metadata in output_map.items(): for metakey, value in metadata.items(): yield assert_equal, getattr(outputs.traits()[key], metakey), value
def test_Eddy_outputs(): output_map = dict( out_corrected=dict(), out_parameter=dict(), ) outputs = Eddy.output_spec() for key, metadata in output_map.items(): for metakey, value in metadata.items(): yield assert_equal, getattr(outputs.traits()[key], metakey), value
def test_Eddy_inputs(): input_map = dict( args=dict(argstr='%s', ), environ=dict( nohash=True, usedefault=True, ), flm=dict(argstr='--flm=%s', ), fwhm=dict(argstr='--fwhm=%s', ), ignore_exception=dict( nohash=True, usedefault=True, ), in_acqp=dict( argstr='--acqp=%s', mandatory=True, ), in_bval=dict( argstr='--bvals=%s', mandatory=True, ), in_bvec=dict( argstr='--bvecs=%s', mandatory=True, ), in_file=dict( argstr='--imain=%s', mandatory=True, ), in_index=dict( argstr='--index=%s', mandatory=True, ), in_mask=dict( argstr='--mask=%s', mandatory=True, ), in_topup=dict(argstr='--topup=%s', ), method=dict(argstr='--resamp=%s', ), niter=dict(argstr='--niter=%s', ), out_base=dict(argstr='--out=%s', ), output_type=dict(), repol=dict(argstr='--repol', ), session=dict(argstr='--session=%s', ), terminal_output=dict( mandatory=True, nohash=True, ), ) inputs = Eddy.input_spec() for key, metadata in input_map.items(): for metakey, value in metadata.items(): yield assert_equal, getattr(inputs.traits()[key], metakey), value
def build_core_nodes(self): """Build and connect the core nodes of the pipeline.""" import nipype.interfaces.ants as ants import nipype.interfaces.fsl as fsl import nipype.interfaces.mrtrix3 as mrtrix3 import nipype.interfaces.utility as nutil import nipype.interfaces.utility as niu import nipype.pipeline.engine as npe from nipype.interfaces.fsl.epi import Eddy from clinica.utils.dwi import ( compute_average_b0, generate_acq_file, generate_index_file, ) from .dwi_preprocessing_using_phasediff_fmap_utils import ( get_grad_fsl, init_input_node, print_end_pipeline, ) from .dwi_preprocessing_using_phasediff_fmap_workflows import ( prepare_phasediff_fmap, ) # Step 0: Initialization # ====================== # Initialize input parameters and print begin message init_node = npe.Node( interface=nutil.Function( input_names=self.get_input_fields(), output_names=[ "image_id", "dwi", "bvec", "bval", "total_readout_time", "phase_encoding_direction", "fmap_magnitude", "fmap_phasediff", "delta_echo_time", ], function=init_input_node, ), name="0-InitNode", ) # Generate (bvec, bval) tuple for MRtrix interfaces get_grad_fsl = npe.Node( nutil.Function( input_names=["bval", "bvec"], output_names=["grad_fsl"], function=get_grad_fsl, ), name="0-GetFslGrad", ) # Generate <image_id>_acq.txt for eddy gen_acq_txt = npe.Node( nutil.Function( input_names=[ "in_dwi", "fsl_phase_encoding_direction", "total_readout_time", "image_id", ], output_names=["out_acq"], function=generate_acq_file, ), name="0-GenerateAcqFile", ) # Generate <image_id>_index.txt for eddy gen_index_txt = npe.Node( nutil.Function( input_names=["in_bval", "low_bval", "image_id"], output_names=["out_index"], function=generate_index_file, ), name="0-GenerateIndexFile", ) gen_index_txt.inputs.low_bval = self.parameters["low_bval"] # Step 1: Computation of the reference b0 (i.e. average b0 but with EPI distortions) # ======================================= # Compute whole brain mask pre_mask_b0 = npe.Node(mrtrix3.BrainMask(), name="1a-PreMaskB0") pre_mask_b0.inputs.out_file = ( "brainmask.nii.gz" # On default, .mif file is generated ) # Run eddy without calibrated fmap pre_eddy = npe.Node(name="1b-PreEddy", interface=Eddy()) pre_eddy.inputs.repol = True pre_eddy.inputs.use_cuda = self.parameters["use_cuda"] pre_eddy.inputs.initrand = self.parameters["initrand"] # Compute the reference b0 compute_ref_b0 = npe.Node( niu.Function( input_names=["in_dwi", "in_bval"], output_names=["out_b0_average"], function=compute_average_b0, ), name="1c-ComputeReferenceB0", ) compute_ref_b0.inputs.low_bval = self.parameters["low_bval"] # Compute brain mask from reference b0 mask_ref_b0 = npe.Node(fsl.BET(mask=True, robust=True), name="1d-MaskReferenceB0") # Step 2: Calibrate and register FMap # =================================== # Bias field correction of the magnitude image bias_mag_fmap = npe.Node(ants.N4BiasFieldCorrection(dimension=3), name="2a-N4MagnitudeFmap") # Brain extraction of the magnitude image bet_mag_fmap = npe.Node(fsl.BET(frac=0.4, mask=True), name="2b-BetN4MagnitudeFmap") # Calibrate FMap calibrate_fmap = prepare_phasediff_fmap(name="2c-CalibrateFMap") # Register the BET magnitude fmap onto the BET b0 bet_mag_fmap2b0 = npe.Node(interface=fsl.FLIRT(), name="2d-RegistrationBetMagToB0") bet_mag_fmap2b0.inputs.dof = 6 bet_mag_fmap2b0.inputs.output_type = "NIFTI_GZ" # Apply the transformation on the calibrated fmap fmap2b0 = npe.Node(interface=fsl.ApplyXFM(), name="2e-1-FMapToB0") fmap2b0.inputs.output_type = "NIFTI_GZ" # Apply the transformation on the magnitude image mag_fmap2b0 = fmap2b0.clone("2e-2-MagFMapToB0") # Smooth the registered (calibrated) fmap smoothing = npe.Node(interface=fsl.maths.IsotropicSmooth(), name="2f-Smoothing") smoothing.inputs.sigma = 4.0 # Step 3: Run FSL eddy # ==================== eddy = pre_eddy.clone("3-Eddy") # Step 4: Bias correction # ======================= # Use implementation detailed in (Jeurissen et al., 2014) bias = npe.Node(mrtrix3.DWIBiasCorrect(use_ants=True), name="4-RemoveBias") # Step 5: Final brainmask # ======================= # Compute average b0 on corrected dataset (for brain mask extraction) compute_avg_b0 = compute_ref_b0.clone("5a-ComputeB0Average") # Compute b0 mask on corrected avg b0 mask_avg_b0 = mask_ref_b0.clone("5b-MaskB0") # Print end message print_end_message = npe.Node( interface=nutil.Function(input_names=["image_id", "final_file"], function=print_end_pipeline), name="99-WriteEndMessage", ) # Connection # ========== # fmt: off self.connect([ # Step 0: Initialization # ====================== # Initialize input parameters and print begin message (self.input_node, init_node, [("dwi", "dwi"), ("bvec", "bvec"), ("bval", "bval"), ("dwi_json", "dwi_json"), ("fmap_magnitude", "fmap_magnitude"), ("fmap_phasediff", "fmap_phasediff"), ("fmap_phasediff_json", "fmap_phasediff_json")]), # Generate (bvec, bval) tuple for MRtrix interfaces (init_node, get_grad_fsl, [("bval", "bval"), ("bvec", "bvec")]), # Generate <image_id>_acq.txt for eddy (init_node, gen_acq_txt, [("dwi", "in_dwi"), ("total_readout_time", "total_readout_time"), ("phase_encoding_direction", "fsl_phase_encoding_direction"), ("image_id", "image_id")]), # Generate <image_id>_index.txt for eddy (init_node, gen_index_txt, [("bval", "in_bval"), ("image_id", "image_id")]), # Step 1: Computation of the reference b0 (i.e. average b0 but with EPI distortions) # ======================================= # Compute whole brain mask (get_grad_fsl, pre_mask_b0, [("grad_fsl", "grad_fsl")]), (init_node, pre_mask_b0, [("dwi", "in_file")]), # Run eddy without calibrated fmap (init_node, pre_eddy, [("dwi", "in_file"), ("bval", "in_bval"), ("bvec", "in_bvec"), ("image_id", "out_base")]), (gen_acq_txt, pre_eddy, [("out_acq", "in_acqp")]), (gen_index_txt, pre_eddy, [("out_index", "in_index")]), (pre_mask_b0, pre_eddy, [("out_file", "in_mask")]), # Compute the reference b0 (init_node, compute_ref_b0, [("bval", "in_bval")]), (pre_eddy, compute_ref_b0, [("out_corrected", "in_dwi")]), # Compute brain mask from reference b0 (compute_ref_b0, mask_ref_b0, [("out_b0_average", "in_file")]), # Step 2: Calibrate and register FMap # =================================== # Bias field correction of the magnitude image (init_node, bias_mag_fmap, [("fmap_magnitude", "input_image")]), # Brain extraction of the magnitude image (bias_mag_fmap, bet_mag_fmap, [("output_image", "in_file")]), # Calibration of the FMap (bet_mag_fmap, calibrate_fmap, [("mask_file", "input_node.fmap_mask"), ("out_file", "input_node.fmap_magnitude")]), (init_node, calibrate_fmap, [("fmap_phasediff", "input_node.fmap_phasediff"), ("delta_echo_time", "input_node.delta_echo_time")]), # Register the BET magnitude fmap onto the BET b0 (bet_mag_fmap, bet_mag_fmap2b0, [("out_file", "in_file")]), (mask_ref_b0, bet_mag_fmap2b0, [("out_file", "reference")]), # Apply the transformation on the magnitude image (bet_mag_fmap2b0, mag_fmap2b0, [("out_matrix_file", "in_matrix_file")]), (bias_mag_fmap, mag_fmap2b0, [("output_image", "in_file")]), (mask_ref_b0, mag_fmap2b0, [("out_file", "reference")]), # Apply the transformation on the calibrated fmap (bet_mag_fmap2b0, fmap2b0, [("out_matrix_file", "in_matrix_file")] ), (calibrate_fmap, fmap2b0, [("output_node.calibrated_fmap", "in_file")]), (mask_ref_b0, fmap2b0, [("out_file", "reference")]), # # Smooth the registered (calibrated) fmap (fmap2b0, smoothing, [("out_file", "in_file")]), # Step 3: Run FSL eddy # ==================== (init_node, eddy, [("dwi", "in_file"), ("bval", "in_bval"), ("bvec", "in_bvec"), ("image_id", "out_base")]), (gen_acq_txt, eddy, [("out_acq", "in_acqp")]), (gen_index_txt, eddy, [("out_index", "in_index")]), (smoothing, eddy, [("out_file", "field")]), (pre_mask_b0, eddy, [("out_file", "in_mask")]), # Step 4: Bias correction # ======================= (init_node, bias, [("bval", "in_bval")]), (eddy, bias, [("out_rotated_bvecs", "in_bvec"), ("out_corrected", "in_file")]), # Step 5: Final brainmask # ======================= # Compute average b0 on corrected dataset (for brain mask extraction) (init_node, compute_avg_b0, [("bval", "in_bval")]), (bias, compute_avg_b0, [("out_file", "in_dwi")]), # Compute b0 mask on corrected avg b0 (compute_avg_b0, mask_avg_b0, [("out_b0_average", "in_file")]), # Print end message (init_node, print_end_message, [("image_id", "image_id")]), (mask_avg_b0, print_end_message, [("mask_file", "final_file")]), # Output node (init_node, self.output_node, [("bval", "preproc_bval")]), (eddy, self.output_node, [("out_rotated_bvecs", "preproc_bvec")]), (bias, self.output_node, [("out_file", "preproc_dwi")]), (mask_avg_b0, self.output_node, [("mask_file", "b0_mask")]), (bet_mag_fmap2b0, self.output_node, [("out_file", "magnitude_on_b0")]), (fmap2b0, self.output_node, [("out_file", "calibrated_fmap_on_b0") ]), (smoothing, self.output_node, [("out_file", "smoothed_fmap_on_b0") ]), ])
def eddy_fsl_pipeline(low_bval, use_cuda, initrand, name="eddy_fsl"): """Use FSL eddy for head motion correction and eddy current distortion correction.""" import nipype.interfaces.utility as niu import nipype.pipeline.engine as pe from nipype.interfaces.fsl.epi import Eddy from clinica.utils.dwi import generate_acq_file, generate_index_file inputnode = pe.Node( niu.IdentityInterface(fields=[ "in_file", "in_bvec", "in_bval", "in_mask", "ref_b0", "total_readout_time", "phase_encoding_direction", ]), name="inputnode", ) generate_acq = pe.Node( niu.Function( input_names=[ "in_dwi", "fsl_phase_encoding_direction", "total_readout_time", ], output_names=["out_file"], function=generate_acq_file, ), name="generate_acq", ) generate_index = pe.Node( niu.Function( input_names=["in_bval", "low_bval"], output_names=["out_file"], function=generate_index_file, ), name="generate_index", ) generate_index.inputs.low_bval = low_bval eddy = pe.Node(interface=Eddy(), name="eddy_fsl") eddy.inputs.repol = True eddy.inputs.use_cuda = use_cuda eddy.inputs.initrand = initrand outputnode = pe.Node( niu.IdentityInterface( fields=["out_parameter", "out_corrected", "out_rotated_bvecs"]), name="outputnode", ) wf = pe.Workflow(name=name) # fmt: off wf.connect([(inputnode, generate_acq, [('in_file', 'in_dwi')]), (inputnode, generate_acq, [('total_readout_time', 'total_readout_time')]), (inputnode, generate_acq, [('phase_encoding_direction', 'fsl_phase_encoding_direction')]), (inputnode, generate_index, [('in_bval', 'in_bval')]), (inputnode, eddy, [('in_bvec', 'in_bvec')]), (inputnode, eddy, [('in_bval', 'in_bval')]), (inputnode, eddy, [('in_file', 'in_file')]), (inputnode, eddy, [('in_mask', 'in_mask')]), (generate_acq, eddy, [('out_file', 'in_acqp')]), (generate_index, eddy, [('out_file', 'in_index')]), (eddy, outputnode, [('out_parameter', 'out_parameter')]), (eddy, outputnode, [('out_corrected', 'out_corrected')]), (eddy, outputnode, [('out_rotated_bvecs', 'out_rotated_bvecs') ])]) # fmt: on return wf