Skip to content

Commit 6792e96

Browse files
authored
Merge pull request #110 from oesteban/maint/refactor-individual-runs
ENH: Minor refactor reorganizing base workflows, in prep for #97
2 parents 25a20ba + 83f6ed1 commit 6792e96

File tree

3 files changed

+52
-21
lines changed

3 files changed

+52
-21
lines changed

dmriprep/workflows/base.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
BIDSInfo, BIDSFreeSurferDir
1313
)
1414
from niworkflows.utils.misc import fix_multi_T1w_source_name
15+
from niworkflows.utils.spaces import Reference
1516
from smriprep.workflows.anatomical import init_anat_preproc_wf
1617

17-
from niworkflows.utils.spaces import Reference
1818
from ..interfaces import DerivativesDataSink, BIDSDataGrabber
1919
from ..interfaces.reports import SubjectSummary, AboutSummary
2020
from ..utils.bids import collect_data
@@ -253,21 +253,28 @@ def init_single_subject_wf(subject_id):
253253
anat_preproc_wf.__postdesc__ = (anat_preproc_wf.__postdesc__ or "") + f"""
254254
Diffusion data preprocessing
255255
256-
: For each of the {len(subject_data["dwi"])} dwi scans found per subject
257-
(across all sessions), the following preprocessing was performed."""
256+
: For each of the {len(subject_data["dwi"])} DWI scans found per subject
257+
(across all sessions), the gradient table was vetted and converted into the *RASb*
258+
format (i.e., given in RAS+ scanner coordinates, normalized b-vectors and scaled b-values),
259+
and a *b=0* average for reference to the subsequent steps of preprocessing was calculated.
260+
"""
258261

259262
layout = config.execution.layout
263+
dwi_data = tuple([
264+
(dwi, layout.get_metadata(dwi), layout.get_bvec(dwi), layout.get_bval(dwi))
265+
for dwi in subject_data["dwi"]
266+
])
267+
260268
inputnode = pe.Node(niu.IdentityInterface(fields=["dwi_data"]),
261269
name="inputnode")
262-
inputnode.iterables = [(
263-
"dwi_data", tuple([
264-
(dwi, layout.get_bvec(dwi), layout.get_bval(dwi),
265-
layout.get_metadata(dwi)["PhaseEncodingDirection"])
266-
for dwi in subject_data["dwi"]
267-
])
268-
)]
270+
inputnode.iterables = [("dwi_data", dwi_data)]
271+
272+
referencenode = pe.JoinNode(niu.IdentityInterface(
273+
fields=["dwi_file", "metadata", "dwi_reference", "dwi_mask", "gradients_rasb"]),
274+
name="referencenode", joinsource="inputnode", run_without_submitting=True)
275+
269276
split_info = pe.Node(niu.Function(
270-
function=_unpack, output_names=["dwi_file", "bvec", "bval", "pedir"]),
277+
function=_unpack, output_names=["dwi_file", "metadata", "bvec", "bval"]),
271278
name="split_info", run_without_submitting=True)
272279

273280
early_b0ref_wf = init_early_b0ref_wf()
@@ -276,6 +283,13 @@ def init_single_subject_wf(subject_id):
276283
(split_info, early_b0ref_wf, [("dwi_file", "inputnode.dwi_file"),
277284
("bvec", "inputnode.in_bvec"),
278285
("bval", "inputnode.in_bval")]),
286+
(split_info, referencenode, [("dwi_file", "dwi_file"),
287+
("metadata", "metadata")]),
288+
(early_b0ref_wf, referencenode, [
289+
("outputnode.dwi_reference", "dwi_reference"),
290+
("outputnode.dwi_mask", "dwi_mask"),
291+
("outputnode.gradients_rasb", "gradients_rasb"),
292+
]),
279293
])
280294

281295
return workflow

dmriprep/workflows/dwi/base.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,6 @@ def init_early_b0ref_wf(
5353
"""
5454
# Build workflow
5555
workflow = Workflow(name=name)
56-
workflow.__postdesc__ = """
57-
For every run and subject, the gradient table was vetted and converted into the *RASb*
58-
format (i.e., given in RAS+ scanner coordinates, normalized b-vectors and scaled b-values),
59-
and a *b=0* average for reference to the subsequent steps of preprocessing was calculated.
60-
"""
6156

6257
inputnode = pe.Node(niu.IdentityInterface(
6358
fields=['dwi_file', 'in_bvec', 'in_bval']),
@@ -84,7 +79,7 @@ def init_early_b0ref_wf(
8479
(dwi_reference_wf, outputnode, [
8580
('outputnode.ref_image', 'dwi_reference'),
8681
('outputnode.dwi_mask', 'dwi_mask')]),
87-
(gradient_table, outputnode, [('out_rasb', 'out_rasb')])
82+
(gradient_table, outputnode, [('out_rasb', 'gradients_rasb')])
8883
])
8984

9085
# REPORTING ############################################################

dmriprep/workflows/dwi/util.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from niworkflows.engine.workflows import LiterateWorkflow as Workflow
77
from niworkflows.interfaces.images import ValidateImage
88
from niworkflows.interfaces.fixes import FixN4BiasFieldCorrection as N4BiasFieldCorrection
9+
from niworkflows.interfaces.nibabel import ApplyMask
910
from niworkflows.interfaces.utils import CopyXForm
1011

1112
from ...interfaces.images import ExtractB0, RescaleB0
@@ -212,8 +213,10 @@ def init_enhance_and_skullstrip_dwi_wf(
212213
combine_masks = pe.Node(fsl.BinaryMaths(operation='mul'),
213214
name='combine_masks')
214215

216+
normalize = pe.Node(niu.Function(function=_normalize), name="normalize")
217+
215218
# Compute masked brain
216-
apply_mask = pe.Node(fsl.ApplyMask(), name='apply_mask')
219+
apply_mask = pe.Node(ApplyMask(), name='apply_mask')
217220

218221
workflow.connect([
219222
(inputnode, n4_correct, [('in_file', 'input_image'),
@@ -230,11 +233,30 @@ def init_enhance_and_skullstrip_dwi_wf(
230233
(skullstrip_first_pass, combine_masks, [('mask_file', 'in_file')]),
231234
(skullstrip_second_pass, fixhdr_skullstrip2, [('out_file', 'in_file')]),
232235
(fixhdr_skullstrip2, combine_masks, [('out_file', 'operand_file')]),
233-
(fixhdr_unifize, apply_mask, [('out_file', 'in_file')]),
234-
(combine_masks, apply_mask, [('out_file', 'mask_file')]),
236+
(combine_masks, apply_mask, [('out_file', 'in_mask')]),
235237
(combine_masks, outputnode, [('out_file', 'mask_file')]),
238+
(n4_correct, normalize, [('output_image', 'in_file')]),
239+
(normalize, apply_mask, [('out', 'in_file')]),
240+
(normalize, outputnode, [('out', 'bias_corrected_file')]),
236241
(apply_mask, outputnode, [('out_file', 'skull_stripped_file')]),
237-
(n4_correct, outputnode, [('output_image', 'bias_corrected_file')]),
238242
])
239243

240244
return workflow
245+
246+
247+
def _normalize(in_file, newmax=2000, perc=98.0):
248+
from pathlib import Path
249+
import numpy as np
250+
import nibabel as nb
251+
252+
nii = nb.load(in_file)
253+
data = nii.get_fdata()
254+
data[data < 0] = 0
255+
if data.max() >= 2**15 - 1:
256+
data *= newmax / np.percentile(data.reshape(-1), perc)
257+
258+
out_file = str(Path("normalized.nii.gz").absolute())
259+
hdr = nii.header.copy()
260+
hdr.set_data_dtype('int16')
261+
nii.__class__(data.astype('int16'), nii.affine, hdr).to_filename(out_file)
262+
return out_file

0 commit comments

Comments
 (0)