Source code for sdcflows.workflows.apply.correction

# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
#
# Copyright 2021 The NiPreps Developers <nipreps@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# We support and encourage derived works from this project, please read
# about our expectations at
#
#     https://www.nipreps.org/community/licensing/
#
"""Applying a fieldmap given its B-Spline coefficients in Hz."""
from nipype.pipeline import engine as pe
from nipype.interfaces import utility as niu
from niworkflows.engine.workflows import LiterateWorkflow as Workflow


[docs] def init_unwarp_wf(*, free_mem=None, omp_nthreads=1, debug=False, name="unwarp_wf"): r""" Set up a workflow that unwarps the input :abbr:`EPI (echo-planar imaging)` dataset. Workflow Graph .. workflow:: :graph2use: orig :simple_form: yes from sdcflows.workflows.apply.correction import init_unwarp_wf wf = init_unwarp_wf(omp_nthreads=2) Parameters ---------- omp_nthreads : :obj:`int` Maximum number of threads an individual process may use. name : :obj:`str` Unique name of this workflow. debug : :obj:`bool` Whether to run in *sloppy* mode. Inputs ------ distorted the target EPI image. metadata dictionary of metadata corresponding to the target EPI image fmap_coeff fieldmap coefficients in distorted EPI space. hmc_xforms list of head-motion correction matrices (in ITK format) Outputs ------- fieldmap the actual B\ :sub:`0` inhomogeneity map (also called *fieldmap*) interpolated from the B-Spline coefficients into the target EPI's grid, given in Hz units. fieldwarp the displacements field interpolated from the B-Spline coefficients and scaled by the appropriate parameters (readout time of the EPI target and voxel size along PE). corrected the target EPI reference image, after applying unwarping. corrected_mask a fast mask calculated from the corrected EPI reference. """ from niworkflows.interfaces.images import RobustAverage from niworkflows.interfaces.nibabel import MergeSeries from sdcflows.interfaces.epi import GetReadoutTime from sdcflows.interfaces.bspline import ApplyCoeffsField from sdcflows.workflows.ancillary import init_brainextraction_wf from sdcflows.utils.misc import front as _pop workflow = Workflow(name=name) inputnode = pe.Node( niu.IdentityInterface( fields=[ "distorted", "metadata", "fmap_coeff", "fmap2data_xfm", "data2fmap_xfm", "hmc_xforms", ] ), name="inputnode", ) outputnode = pe.Node( niu.IdentityInterface( fields=[ "fieldmap", "fieldwarp", "corrected", "corrected_ref", "corrected_mask", ] ), name="outputnode", ) rotime = pe.Node(GetReadoutTime(), name="rotime") rotime.interface._always_run = debug # resample is memory-hungry; choose a smaller number of threads # if we know how much memory we have to work with mem_per_thread = 5 # True for a 128x128x84 image; should generalize if debug: num_threads = 1 elif free_mem is not None: mem_gb = min(0.9 * free_mem, mem_per_thread * omp_nthreads) num_threads = max(int(mem_gb // mem_per_thread), 1) else: num_threads = omp_nthreads resample = pe.Node( ApplyCoeffsField(num_threads=num_threads), mem_gb=mem_per_thread * num_threads, name="resample", ) merge = pe.Node(MergeSeries(), name="merge") average = pe.Node(RobustAverage(mc_method=None), name="average") brainextraction_wf = init_brainextraction_wf() # fmt:off workflow.connect([ (inputnode, rotime, [(("distorted", _pop), "in_file"), ("metadata", "metadata")]), (inputnode, resample, [("distorted", "in_data"), ("fmap_coeff", "in_coeff"), ("fmap2data_xfm", "fmap2data_xfm"), ("data2fmap_xfm", "data2fmap_xfm"), ("hmc_xforms", "in_xfms")]), (rotime, resample, [("readout_time", "ro_time"), ("pe_direction", "pe_dir")]), (resample, merge, [("out_corrected", "in_files")]), (merge, average, [("out_file", "in_file")]), (average, brainextraction_wf, [("out_file", "inputnode.in_file")]), (merge, outputnode, [("out_file", "corrected")]), (resample, outputnode, [("out_field", "fieldmap")]), (brainextraction_wf, outputnode, [ ("outputnode.out_file", "corrected_ref"), ("outputnode.out_mask", "corrected_mask"), ]), ]) # fmt:on return workflow