def init_sdc_unwarp_wf(omp_nthreads, fmap_demean, debug, name='sdc_unwarp_wf'): """ This workflow takes in a displacements fieldmap and calculates the corresponding displacements field (in other words, an ANTs-compatible warp file). It also calculates a new mask for the input dataset that takes into account the distortions. The mask is restricted to the field of view of the fieldmap since outside of it corrections could not be performed. Inputs in_reference the reference image in_reference_brain the reference image (skull-stripped) in_mask a brain mask corresponding to ``in_reference`` metadata metadata associated to the ``in_reference`` EPI input fmap the fieldmap in Hz fmap_ref the reference (anatomical) image corresponding to ``fmap`` fmap_mask a brain mask corresponding to ``fmap`` Outputs out_reference the ``in_reference`` after unwarping out_reference_brain the ``in_reference`` after unwarping and skullstripping out_warp the corresponding :abbr:`DFM (displacements field map)` compatible with ANTs out_jacobian the jacobian of the field (for drop-out alleviation) out_mask mask of the unwarped input file out_hz fieldmap in Hz that can be sent to eddy """ workflow = Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface( fields=['in_reference', 'in_reference_brain', 'in_mask', 'metadata', 'fmap_ref', 'fmap_mask', 'fmap']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface( fields=['out_reference', 'out_reference_brain', 'out_warp', 'out_mask', 'out_jacobian', 'out_hz']), name='outputnode') # Register the reference of the fieldmap to the reference # of the target image (the one that shall be corrected) ants_settings = pkgr.resource_filename('qsiprep', 'data/fmap-any_registration.json') if debug: ants_settings = pkgr.resource_filename( 'qsiprep', 'data/fmap-any_registration_testing.json') fmap2ref_reg = pe.Node( ANTSRegistrationRPT(generate_report=True, from_file=ants_settings, output_inverse_warped_image=True, output_warped_image=True), name='fmap2ref_reg', n_procs=omp_nthreads) ds_reg = pe.Node(DerivativesDataSink(suffix='fmap_reg'), name='ds_report_reg', mem_gb=0.01, run_without_submitting=True) # Map the VSM into the EPI space fmap2ref_apply = pe.Node(ANTSApplyTransformsRPT( generate_report=True, dimension=3, interpolation='BSpline', float=True), name='fmap2ref_apply') fmap_mask2ref_apply = pe.Node(ANTSApplyTransformsRPT( generate_report=False, dimension=3, interpolation='MultiLabel', float=True), name='fmap_mask2ref_apply') ds_reg_vsm = pe.Node(DerivativesDataSink(suffix='fmap_reg_vsm'), name='ds_report_vsm', mem_gb=0.01, run_without_submitting=True) # Fieldmap to rads and then to voxels (VSM - voxel shift map) torads = pe.Node(FieldToRadS(fmap_range=0.5), name='torads') # Make one in Hz for eddy tohz = pe.Node(FieldToHz(range_hz=1), name='tohz') get_ees = pe.Node(niu.Function(function=_get_ees, output_names=['ees']), name='get_ees') gen_vsm = pe.Node(fsl.FUGUE(save_unmasked_shift=True, save_fmap=True), name='gen_vsm') # Convert the VSM into a DFM (displacements field map) # or: FUGUE shift to ANTS warping. vsm2dfm = pe.Node(itk.FUGUEvsm2ANTSwarp(), name='vsm2dfm') jac_dfm = pe.Node(ants.CreateJacobianDeterminantImage( imageDimension=3, outputImage='jacobian.nii.gz'), name='jac_dfm') unwarp_reference = pe.Node(ANTSApplyTransformsRPT(dimension=3, generate_report=False, float=True, interpolation='LanczosWindowedSinc'), name='unwarp_reference') fieldmap_fov_mask = pe.Node(FilledImageLike(dtype='uint8'), name='fieldmap_fov_mask') fmap_fov2ref_apply = pe.Node(ANTSApplyTransformsRPT( generate_report=False, dimension=3, interpolation='NearestNeighbor', float=True), name='fmap_fov2ref_apply') apply_fov_mask = pe.Node(fsl.ApplyMask(), name="apply_fov_mask") enhance_and_skullstrip_bold_wf = init_enhance_and_skullstrip_dwi_wf(omp_nthreads=omp_nthreads) workflow.connect([ (inputnode, fmap2ref_reg, [('fmap_ref', 'moving_image')]), (inputnode, fmap2ref_apply, [('in_reference', 'reference_image')]), (fmap2ref_reg, fmap2ref_apply, [ ('composite_transform', 'transforms')]), (inputnode, fmap_mask2ref_apply, [('in_reference', 'reference_image')]), (fmap2ref_reg, fmap_mask2ref_apply, [ ('composite_transform', 'transforms')]), (fmap2ref_apply, ds_reg_vsm, [('out_report', 'in_file')]), (inputnode, fmap2ref_reg, [('in_reference_brain', 'fixed_image')]), (fmap2ref_reg, ds_reg, [('out_report', 'in_file')]), (inputnode, fmap2ref_apply, [('fmap', 'input_image')]), (inputnode, fmap_mask2ref_apply, [('fmap_mask', 'input_image')]), (fmap2ref_apply, torads, [('output_image', 'in_file')]), (fmap2ref_apply, tohz, [('output_image', 'in_file')]), (tohz, outputnode, [('out_file', 'out_hz')]), (inputnode, get_ees, [('in_reference', 'in_file'), ('metadata', 'in_meta')]), (fmap_mask2ref_apply, gen_vsm, [('output_image', 'mask_file')]), (get_ees, gen_vsm, [('ees', 'dwell_time')]), (inputnode, gen_vsm, [(('metadata', _get_pedir_fugue), 'unwarp_direction')]), (inputnode, vsm2dfm, [(('metadata', _get_pedir_bids), 'pe_dir')]), (torads, gen_vsm, [('out_file', 'fmap_in_file')]), (gen_vsm, outputnode, [('fmap_out_file', 'fieldcoef')]), (vsm2dfm, unwarp_reference, [('out_file', 'transforms')]), (inputnode, unwarp_reference, [('in_reference', 'reference_image')]), (inputnode, unwarp_reference, [('in_reference', 'input_image')]), (vsm2dfm, outputnode, [('out_file', 'out_warp')]), (vsm2dfm, jac_dfm, [('out_file', 'deformationField')]), (inputnode, fieldmap_fov_mask, [('fmap_ref', 'in_file')]), (fieldmap_fov_mask, fmap_fov2ref_apply, [('out_file', 'input_image')]), (inputnode, fmap_fov2ref_apply, [('in_reference', 'reference_image')]), (fmap2ref_reg, fmap_fov2ref_apply, [('composite_transform', 'transforms')]), (fmap_fov2ref_apply, apply_fov_mask, [('output_image', 'mask_file')]), (unwarp_reference, apply_fov_mask, [('output_image', 'in_file')]), (apply_fov_mask, enhance_and_skullstrip_bold_wf, [('out_file', 'inputnode.in_file')]), (fmap_mask2ref_apply, enhance_and_skullstrip_bold_wf, [('output_image', 'inputnode.pre_mask')]), (apply_fov_mask, outputnode, [('out_file', 'out_reference')]), (enhance_and_skullstrip_bold_wf, outputnode, [ ('outputnode.mask_file', 'out_mask'), ('outputnode.skull_stripped_file', 'out_reference_brain')]), (jac_dfm, outputnode, [('jacobian_image', 'out_jacobian')]), ]) if fmap_demean: # Demean within mask demean = pe.Node(DemeanImage(), name='demean') workflow.connect([ (gen_vsm, demean, [('shift_out_file', 'in_file')]), (fmap_mask2ref_apply, demean, [('output_image', 'in_mask')]), (demean, vsm2dfm, [('out_file', 'in_file')]), ]) else: workflow.connect([ (gen_vsm, vsm2dfm, [('shift_out_file', 'in_file')]), ]) return workflow
# calc_warp_field.inputs.dimension = 3 # calc_warp_field.inputs.print_out_composite_warp_file = True # calc_warp_field.inputs.output_image = 'Warp_Field.nii.gz' #----------------------------------------------------------------------------------------------------- # In[1] # Here we just get the warp field # Notice I changed reg_sub_to_temp.inputs.write_composite_transform to False # So, it outputs the warpfield seperate from the affine transform get_warp_field = Node(Select(), name='get_warp_field') get_warp_field.inputs.index = [1] #----------------------------------------------------------------------------------------------------- # In[1]: #Create jacobian determinant jacobian = Node(ants.CreateJacobianDeterminantImage(), name='Calculate_Jacobian_Determinant') jacobian.inputs.imageDimension = 3 jacobian.inputs.outputImage = 'Jacobian.nii.gz' #----------------------------------------------------------------------------------------------------- # In[1]: #Tissue segmentation atropos = Node(ants.Atropos(), name='Atropos') atropos.inputs.dimension = 3 atropos.inputs.initialization = 'PriorProbabilityImages' atropos.inputs.prior_probability_images = [CSF, GM, WM] atropos.inputs.number_of_tissue_classes = 3 atropos.inputs.prior_weighting = 0.8 atropos.inputs.prior_probability_threshold = 0.0000001