def test_ANTSRegistrationRPT(monkeypatch, reference, moving): """ the RobustMNINormalizationRPT report capable test """ import pkg_resources as pkgr def _agg(objekt, runtime): outputs = objekt.output_spec() outputs.warped_image = os.path.join( datadir, "testANTSRegistrationRPT-warped_image.nii.gz") outputs.out_report = os.path.join(runtime.cwd, objekt.inputs.out_report) return outputs # Patch the _run_interface method monkeypatch.setattr(ANTSRegistrationRPT, "_run_interface", _run_interface_mock) monkeypatch.setattr(ANTSRegistrationRPT, "aggregate_outputs", _agg) ants_rpt = ANTSRegistrationRPT( generate_report=True, moving_image=moving, fixed_image=reference, from_file=pkgr.resource_filename( "niworkflows.data", "t1w-mni_registration_testing_000.json"), ) _smoke_test_report(ants_rpt, "testANTSRegistrationRPT.svg")
def test_ANTSRegistrationRPT(self): """ the RobustMNINormalizationRPT report capable test """ ants_rpt = ANTSRegistrationRPT( generate_report=True, moving_image=self.moving, fixed_image=self.reference, from_file=pkgr.resource_filename( 'niworkflows.data', 't1-mni_registration_testing_000.json')) _smoke_test_report(ants_rpt, 'testANTSRegistrationRPT.svg')
def test_ANTSRegistrationRPT(monkeypatch, reference, moving): """ the RobustMNINormalizationRPT report capable test """ import pkg_resources as pkgr def _agg(objekt, runtime): outputs = Bunch(warped_image=os.path.join( datadir, 'testANTSRegistrationRPT-warped_image.nii.gz')) return outputs # Patch the _run_interface method monkeypatch.setattr(ANTSRegistrationRPT, '_run_interface', _run_interface_mock) monkeypatch.setattr(ANTSRegistrationRPT, 'aggregate_outputs', _agg) ants_rpt = ANTSRegistrationRPT(generate_report=True, moving_image=moving, fixed_image=reference, from_file=pkgr.resource_filename( 'niworkflows.data', 't1-mni_registration_testing_000.json')) _smoke_test_report(ants_rpt, 'testANTSRegistrationRPT.svg')
def init_sdc_unwarp_wf(reportlets_dir, omp_nthreads, fmap_bspline, 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. .. workflow :: :graph2use: orig :simple_form: yes from fmriprep.workflows.fieldmap.unwarp import init_sdc_unwarp_wf wf = init_sdc_unwarp_wf(reportlets_dir='.', omp_nthreads=8, fmap_bspline=False, fmap_demean=True, debug=False) Inputs in_reference the reference image in_mask a brain mask corresponding to ``in_reference`` name_source path to the original _bold file being unwarped 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_mask_report reportled for the skullstripping """ workflow = pe.Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface(fields=[ 'in_reference', 'in_reference_brain', 'in_mask', 'name_source', '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_mask_report' ]), name='outputnode') meta = pe.Node(ReadSidecarJSON(), name='meta') # Register the reference of the fieldmap to the reference # of the target image (the one that shall be corrected) ants_settings = pkgr.resource_filename('fmriprep', 'data/fmap-any_registration.json') if debug: ants_settings = pkgr.resource_filename( 'fmriprep', '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, num_threads=omp_nthreads), name='fmap2ref_reg') fmap2ref_reg.interface.num_threads = omp_nthreads ds_reg = pe.Node(DerivativesDataSink(base_directory=reportlets_dir, suffix='fmap_reg'), name='ds_reg') # 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='NearestNeighbor', float=True), name='fmap_mask2ref_apply') ds_reg_vsm = pe.Node(DerivativesDataSink(base_directory=reportlets_dir, suffix='fmap_reg_vsm'), name='ds_reg_vsm') # Fieldmap to rads and then to voxels (VSM - voxel shift map) torads = pe.Node(niu.Function(function=_hz2rads), name='torads') gen_vsm = pe.Node(fsl.FUGUE(save_unmasked_shift=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(niu.Function(function=_fill_with_ones), 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_epi_wf = init_enhance_and_skullstrip_epi_wf() workflow.connect([ (inputnode, meta, [('name_source', 'in_file')]), (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')]), (inputnode, ds_reg_vsm, [('name_source', 'source_file')]), (fmap2ref_apply, ds_reg_vsm, [('out_report', 'in_file')]), (inputnode, fmap2ref_reg, [('in_reference_brain', 'fixed_image')]), (inputnode, ds_reg, [('name_source', 'source_file')]), (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')]), (meta, gen_vsm, [(('out_dict', _get_ec), 'dwell_time'), (('out_dict', _get_pedir_fugue), 'unwarp_direction') ]), (meta, vsm2dfm, [(('out_dict', _get_pedir_bids), 'pe_dir')]), (torads, gen_vsm, [('out', 'fmap_in_file')]), (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', '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_epi_wf, [('out_file', 'inputnode.in_file')]), (apply_fov_mask, outputnode, [('out_file', 'out_reference')]), (enhance_and_skullstrip_epi_wf, outputnode, [('outputnode.mask_file', 'out_mask'), ('outputnode.out_report', 'out_mask_report'), ('outputnode.skull_stripped_file', 'out_reference_brain')]), (jac_dfm, outputnode, [('jacobian_image', 'out_jacobian')]), ]) if not fmap_bspline: workflow.connect([(fmap_mask2ref_apply, gen_vsm, [('output_image', 'mask_file')])]) if fmap_demean: # Demean within mask demean = pe.Node(niu.Function(function=_demean), name='demean') workflow.connect([ (gen_vsm, demean, [('shift_out_file', 'in_file')]), (fmap_mask2ref_apply, demean, [('output_image', 'in_mask')]), (demean, vsm2dfm, [('out', 'in_file')]), ]) else: workflow.connect([ (gen_vsm, vsm2dfm, [('shift_out_file', 'in_file')]), ]) return workflow
def init_sdc_unwarp_wf(omp_nthreads, fmap_demean, debug, name='sdc_unwarp_wf'): """ Apply the warping given by a displacements fieldmap. 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. .. workflow :: :graph2use: orig :simple_form: yes from sdcflows.workflows.unwarp import init_sdc_unwarp_wf wf = init_sdc_unwarp_wf(omp_nthreads=8, fmap_demean=True, debug=False) 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 """ 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' ]), 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('sdcflows', 'data/fmap-any_registration.json') if debug: ants_settings = pkgr.resource_filename( 'sdcflows', '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_report_reg = pe.Node(DerivativesDataSink(desc='magnitude', suffix='bold'), 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_report_vsm = pe.Node(DerivativesDataSink(desc='fieldmap', suffix='bold'), 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') 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), 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_bold_wf( omp_nthreads=omp_nthreads, pre_mask=True) 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_report_vsm, [('out_report', 'in_file')]), (inputnode, fmap2ref_reg, [('in_reference_brain', 'fixed_image')]), (fmap2ref_reg, ds_report_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')]), (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')]), (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
def init_fmap2field_wf(omp_nthreads, debug, name='fmap2field_wf', generate_report=True): """ Convert the estimated fieldmap in Hz into a displacements field. This workflow takes in a fieldmap and calculates the corresponding displacements field (in other words, an ANTs-compatible warp file). Workflow Graph .. workflow :: :graph2use: orig :simple_form: yes from sdcflows.workflows.fmap import init_fmap2field_wf wf = init_fmap2field_wf(omp_nthreads=8, debug=False) Parameters ---------- omp_nthreads : int Maximum number of threads an individual process may use. debug : bool Run fast configurations of registrations. name : str Unique name of this workflow. Inputs ------ in_reference the reference image in_reference_brain the reference image (skull-stripped) 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 """ workflow = Workflow(name=name) workflow.__desc__ = """\ The *fieldmap* was then co-registered to the target EPI (echo-planar imaging) reference run and converted to a displacements field map (amenable to registration tools such as ANTs) with FSL's `fugue` and other *SDCflows* tools. """ inputnode = pe.Node(niu.IdentityInterface(fields=[ 'in_reference', 'in_reference_brain', 'metadata', 'fmap_ref', 'fmap_mask', 'fmap' ]), name='inputnode') outputnode = pe.Node(niu.IdentityInterface(fields=['out_warp']), 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('sdcflows', 'data/fmap-any_registration.json') if debug: ants_settings = pkgr.resource_filename( 'sdcflows', 'data/fmap-any_registration_testing.json') fmap2ref_reg = pe.Node(ANTSRegistrationRPT( generate_report=False, from_file=ants_settings, output_inverse_warped_image=True, output_warped_image=True), name='fmap2ref_reg', n_procs=omp_nthreads) # Map the VSM into the EPI space fmap2ref_apply = pe.Node(ANTSApplyTransformsRPT(generate_report=False, 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') # Fieldmap to rads and then to voxels (VSM - voxel shift map) torads = pe.Node(FieldToRadS(fmap_range=0.5), name='torads') 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), name='gen_vsm') # Convert the VSM into a DFM (displacements field map) # or: FUGUE shift to ANTS warping. vsm2dfm = pe.Node(FUGUEvsm2ANTSwarp(), name='vsm2dfm') workflow.connect([ (inputnode, fmap2ref_reg, [('fmap_ref', 'moving_image'), ('in_reference_brain', 'fixed_image')]), (inputnode, fmap2ref_apply, [('fmap', 'input_image'), ('in_reference', 'reference_image')]), (inputnode, fmap_mask2ref_apply, [('in_reference', 'reference_image'), ('fmap_mask', 'input_image')]), (inputnode, get_ees, [('in_reference', 'in_file'), ('metadata', 'in_meta')]), (inputnode, gen_vsm, [(('metadata', _get_pedir_fugue), 'unwarp_direction')]), (inputnode, vsm2dfm, [(('metadata', _get_pedir_bids), 'pe_dir')]), (fmap2ref_reg, fmap2ref_apply, [('composite_transform', 'transforms') ]), (fmap2ref_reg, fmap_mask2ref_apply, [('composite_transform', 'transforms')]), (fmap2ref_apply, torads, [('output_image', 'in_file')]), (fmap_mask2ref_apply, gen_vsm, [('output_image', 'mask_file')]), (gen_vsm, vsm2dfm, [('shift_out_file', 'in_file')]), (get_ees, gen_vsm, [('ees', 'dwell_time')]), (torads, gen_vsm, [('out_file', 'fmap_in_file')]), (vsm2dfm, outputnode, [('out_file', 'out_warp')]), ]) if generate_report: from niworkflows.interfaces.bids import DerivativesDataSink from ..interfaces.reportlets import FieldmapReportlet fmap_rpt = pe.Node(FieldmapReportlet(reference_label='EPI Reference', moving_label='Magnitude', show='both'), name='fmap_rpt') ds_report_sdc = pe.Node(DerivativesDataSink(desc='fieldmap', suffix='bold'), name='ds_report_fmap', mem_gb=0.01, run_without_submitting=True) workflow.connect([ (inputnode, fmap_rpt, [('in_reference', 'reference')]), (fmap2ref_reg, fmap_rpt, [('warped_image', 'moving')]), (fmap_mask2ref_apply, fmap_rpt, [('output_image', 'mask')]), (vsm2dfm, fmap_rpt, [('fieldmap', 'fieldmap')]), (fmap_rpt, ds_report_sdc, [('out_report', 'in_file')]), ]) return workflow