Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions qsiprep/interfaces/eddy.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,14 +417,17 @@ def boilerplate_from_eddy_config(eddy_config, fieldmap_type, pepolar_method):
)

# Format the interpolation
lsr_ref = ' [@fsllsr]' if ext_eddy.inputs.method == 'lsr' else ''
if doing_2stage:
desc.append(
'Interpolation after head motion and initial susceptibility distortion correction'
'Resampling after head motion and initial susceptibility '
'distortion correction was performed using '
)
else:
desc.append('Final interpolation')
desc.append(f'was performed using the `{ext_eddy.inputs.method}` method{lsr_ref}.')
desc.append('Final resamping was performed using ')
if ext_eddy.inputs.method == 'lsr':
desc.append('Least-Squares Reconstruction with spline interpolation ([@fsllsr]).')
else:
desc.append('Jacobian modulation with spline interpolation.')
if not doing_2stage:
desc.append('\n\n')
return ' '.join(desc)
Expand Down
88 changes: 62 additions & 26 deletions qsiprep/workflows/anatomical/volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,26 +229,11 @@ def init_anat_preproc_wf(
workflow.add_nodes([inputnode])
return workflow

contrast = config.workflow.anat_modality[:-1]
desc = """

#### Anatomical data preprocessing

"""
desc += (
f"""\
A total of {num_anat_images} {contrast}-weighted ({contrast}w) images were found within the input
BIDS dataset.
All of them were corrected for intensity non-uniformity (INU)
using `N4BiasFieldCorrection` [@n4, ANTs {ANTS_VERSION}].
"""
if num_anat_images > 1
else f"""\
The {contrast}-weighted ({contrast}w) image was corrected for intensity non-uniformity (INU)
using `N4BiasFieldCorrection` [@n4, ANTs {ANTS_VERSION}],
and used as an anatomical reference throughout the workflow.
"""
)

# Ensure there is 1 and only 1 anatomical reference
anat_reference_wf = init_anat_template_wf(num_images=num_anat_images)
Expand Down Expand Up @@ -579,17 +564,6 @@ def init_anat_template_wf(num_images) -> Workflow:
workflow = Workflow(name='anat_template_wf')
contrast = config.workflow.anat_modality

if num_images > 1:
workflow.__desc__ = f"""\
A {contrast}-reference map was computed after registration of
{num_images} {contrast} images (after INU-correction) using
`antsRegistration` [ANTs {ANTS_VERSION}; @ants].
""".format(
contrast=config.workflow.anat_modality,
num_images=num_images,
ants_ver=BrainExtraction().version or '<ver>',
)

inputnode = pe.Node(niu.IdentityInterface(fields=['images']), name='inputnode')
outputnode = pe.Node(
niu.IdentityInterface(
Expand All @@ -607,6 +581,22 @@ def init_anat_template_wf(num_images) -> Workflow:
omp_nthreads = config.nipype.omp_nthreads

# 0. Reorient anatomical image(s) to LPS and resample to common voxel space
if num_images > 1:
desc = f"""\
All {num_images} {contrast} images were
""".format(
contrast=config.workflow.anat_modality,
num_images=num_images,
)
else:
desc = f"""\
The {contrast} image was
""".format(contrast=config.workflow.anat_modality)

desc += """\
reoriented to LPS orientation and resampled to an isotropic voxel size using AFNI tools [@afni].
"""

template_dimensions = pe.Node(TemplateDimensions(), name='template_dimensions')
anat_conform = pe.MapNode(
Conform(deoblique_header=True), iterfield='in_file', name='anat_conform'
Expand Down Expand Up @@ -640,6 +630,18 @@ def init_anat_template_wf(num_images) -> Workflow:
)

if num_images == 1:
desc += f"""\
Intensity non-uniformity (INU) correction was applied to the {contrast}
image using ANTs' (ANTs version {ANTS_VERSION}; @ants) _N4BiasFieldCorrection_ (@n4)
algorithm with the following parameters: 50 iterations of convergence
at each level, a convergence threshold of 0.0000001, a shrink factor of 4,
and a B-spline fitting distance of 200 voxels. This imaged served as the
anatomical reference for subsequent steps.
\n\n
""".format(
contrast=config.workflow.anat_modality,
ANTS_VERSION=BrainExtraction().version or '<ver>',
)

def _get_first(in_list):
if isinstance(in_list, list | tuple):
Expand All @@ -656,8 +658,22 @@ def _get_first(in_list):
(n4_correct, outputnode, [('output_image', 'bias_corrected')]),
]) # fmt:skip

workflow.__desc__ = desc
return workflow

# More than one image
desc += f"""\
Intensity non-uniformity (INU) correction was applied to each {contrast} image
using ANTs' (ANTs version {ANTS_VERSION}; @ants)
_N4BiasFieldCorrection_ (@n4) algorithm with the following parameters:
50 iterations of convergence at each level, a convergence threshold
of 0.0000001, a shrink factor of 4, and a B-spline fitting distance
of 200 voxels.
""".format(
contrast=config.workflow.anat_modality,
ANTS_VERSION=BrainExtraction().version or '<ver>',
)

# 1. Template (only if several images)
# 1a. Correct for bias field: the bias field is an additive factor
# in log-transformed intensity units. Therefore, it is not a linear
Expand All @@ -669,6 +685,25 @@ def _get_first(in_list):

# Make an unbiased template, same as used for b=0 registration
align_to = config.workflow.subject_anatomical_reference

if align_to == 'first-alphabetically':
desc += f"""\
The INU-corrected {config.workflow.anat_modality} images were
then aligned using a rigid-body transformation to the first
image (alphabetically) as the reference using rigid body registration
in ANTs (@ants), and merged to create a single {config.workflow.anat_modality}
reference image.
\n\n
"""
else:
desc += f"""\
The INU-corrected {config.workflow.anat_modality} images were
then aligned using a rigid-body transformation to an iteratively refined
template using rigid body registration in ANTs (@ants), and merged to create
a single {config.workflow.anat_modality} reference image.
\n\n
"""

anat_merge_wf = init_b0_hmc_wf(
align_to='first' if (align_to == 'first-alphabetically') else 'iterative',
transform='Rigid',
Expand All @@ -687,6 +722,7 @@ def _get_first(in_list):
]),
]) # fmt:skip

workflow.__desc__ = desc
return workflow


Expand Down
18 changes: 12 additions & 6 deletions qsiprep/workflows/dwi/confounds.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,18 @@ def init_dwi_confs_wf():
"""
workflow = Workflow(name='dwi_confs_wf')
workflow.__desc__ = """\
Several confounding time-series were calculated based on the
preprocessed DWI: framewise displacement (FD) using the
implementation in *Nipype* [following the definitions by @power_fd_dvars].
The head-motion estimates calculated in the correction step were also
placed within the corresponding confounds file. Slicewise cross correlation
was also calculated.
Several confounding time-series were calculated based on the preprocessed DWI.
Framewise displacement (FD) was computed from head-motion parameters using the
implementation in *Nipype* [following @power_fd_dvars]. The head-motion estimates
calculated in the correction step, including six rigid-body motion parameters
(three translations in mm, three rotations in radians) were also included in the
confounds file. Note that estimated motion parameters in the phase-encoding
direction have high undercertainty due to the effect of a constant (mean)
eddy-current field. Additional slice-level quality metrics (eddy standard
deviations) were included in the confounds file along with the original gradient
vectors, b-values, and image-level quality measures (mean intensity, b=0 mean,
b=0 correction). Preprocessing-related metrics (pre/post/change for denoising and
Gibbs unringing methods) were also included.
"""
inputnode = pe.Node(
niu.IdentityInterface(
Expand Down
6 changes: 5 additions & 1 deletion qsiprep/workflows/dwi/merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,11 @@ def get_buffernode():
n_procs=omp_nthreads,
)
elif unringing_method == 'rpg':
desc += f'{last_step}Gibbs ringing was removed using TORTOISE [@pfgibbs]. '
desc += (
f'{last_step}partial-Fourier induced Gibbs ringing was '
'removed using the approach implemented in TORTOISE v4 '
'[@tortoisev4; @pfgibbs]. '
)

pe_code = {
'i': 0,
Expand Down