Skip to content

Commit 76b566b

Browse files
committed
move mrtrix3 commands into separate workflow
1 parent 752e6f0 commit 76b566b

File tree

8 files changed

+56
-171
lines changed

8 files changed

+56
-171
lines changed

dmriprep/cli.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ def __init__(
3434
omp_nthreads,
3535
eddy_niter,
3636
synb0_dir,
37-
acqp_file
37+
acqp_file,
38+
tbss,
39+
diffusivity_meas,
3840
):
3941

4042
self.layout = layout
@@ -45,13 +47,15 @@ def __init__(
4547
self.work_dir = work_dir
4648
self.ignore = ignore
4749
self.b0_thresh = b0_thresh
48-
self.output_resolution = resize_scale
50+
self.output_resolution = output_resolution
4951
self.bet_dwi = bet_dwi
5052
self.bet_mag = bet_mag
5153
self.omp_nthreads = omp_nthreads
5254
self.eddy_niter = eddy_niter
5355
self.synb0_dir = synb0_dir
5456
self.acqp_file = acqp_file
57+
self.tbss = (tbss,)
58+
self.diffusivity_meas = diffusivity_meas
5559

5660

5761
@click.command()
@@ -61,15 +65,11 @@ def __init__(
6165
"output_dir", type=click.Path(exists=True, file_okay=False, writable=True)
6266
)
6367
@click.argument(
64-
"analysis_level",
65-
default="participant",
66-
type=click.Choice(["participant", "group"]),
68+
"analysis_level", default="participant", type=click.Choice(["participant", "group"])
6769
)
6870
# optional arguments
6971
# options for filtering BIDS queries
70-
@click.option(
71-
"--skip_bids_validation", help="Skip BIDS validation", is_flag=True
72-
)
72+
@click.option("--skip_bids_validation", help="Skip BIDS validation", is_flag=True)
7373
@click.option(
7474
"--participant_label",
7575
default=None,
@@ -96,7 +96,7 @@ def __init__(
9696
@click.option(
9797
"--output_resolution",
9898
help="The isotropic voxel size in mm the data will be resampled to before eddy.",
99-
type=float
99+
type=float,
100100
)
101101
# specific options for eddy
102102
@click.option(
@@ -154,17 +154,13 @@ def __init__(
154154
help="working directory",
155155
type=click.Path(exists=True, file_okay=False, writable=True),
156156
)
157-
@click.option(
158-
"--tbss",
159-
help="Run TBSS"
160-
is_flag=True
161-
)
157+
@click.option("--tbss", help="Run TBSS", is_flag=True)
162158
@click.option(
163159
"--diffusivity_meas",
164160
help="Specify which measures to calculate.",
165161
default=("FA",),
166162
type=click.Choice(["FA", "MD", "AD", "RD"]),
167-
multiple=True
163+
multiple=True,
168164
)
169165
@click.option(
170166
"--synb0_dir",
@@ -188,6 +184,8 @@ def main(
188184
eddy_niter,
189185
synb0_dir,
190186
acqp_file,
187+
tbss,
188+
diffusivity_meas,
191189
):
192190
"""
193191
BIDS_DIR: The directory with the input dataset formatted according to the
@@ -237,10 +235,12 @@ def main(
237235
eddy_niter=eddy_niter,
238236
synb0_dir=synb0_dir,
239237
acqp_file=acqp_file,
238+
tbss=tbss,
239+
diffusivity_meas=list(diffusivity_meas),
240240
)
241241

242242
wf = init_dmriprep_wf(parameters)
243-
wf.write_graph(graph2use="colored")
243+
wf.write_graph()
244244
wf.config["execution"]["remove_unnecessary_outputs"] = False
245245
wf.config["execution"]["keep_inputs"] = True
246246
wf.config["execution"]["crashfile_format"] = "txt"

dmriprep/utils/hemisphere.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,26 @@
55

66

77
def is_hemispherical(vecs):
8-
"""Test whether all points on a unit sphere lie in the same hemisphere.
8+
"""
9+
Test whether all points on a unit sphere lie in the same hemisphere.
10+
11+
**Inputs**
912
10-
Parameters
11-
----------
1213
vecs : numpy.ndarray
1314
2D numpy array with shape (N, 3) where N is the number of points.
1415
All points must lie on the unit sphere.
1516
16-
Returns
17-
-------
17+
**Outputs**
18+
1819
is_hemi : bool
1920
If True, one can find a hemisphere that contains all the points.
2021
If False, then the points do not lie in any hemisphere
21-
2222
pole : numpy.ndarray
2323
If `is_hemi == True`, then pole is the "central" pole of the
2424
input vectors. Otherwise, pole is the zero vector.
2525
26-
References
27-
----------
26+
**References**
27+
2828
https://rstudio-pubs-static.s3.amazonaws.com/27121_a22e51b47c544980bad594d5e0bb2d04.html # noqa
2929
"""
3030
if vecs.shape[1] != 3:

dmriprep/workflows/dwi/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22

33
from .base import init_dwi_preproc_wf
4-
from .remove_artefacts import init_remove_artefacts_wf
4+
from .prep_dwi import init_prep_dwi_wf
55
from .tensor import init_tensor_wf
66
from .outputs import init_output_wf

dmriprep/workflows/dwi/base.py

Lines changed: 14 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from nipype.interfaces import ants, fsl, mrtrix3, utility as niu
1212
from numba import cuda
1313

14-
from .remove_artefacts import init_remove_artefacts_wf
14+
from .prep_dwi import init_prep_dwi_wf
1515
from .tensor import init_tensor_wf
1616

1717
# from ..fieldmap.base import init_sdc_prep_wf
@@ -91,13 +91,7 @@ def init_dwi_preproc_wf(subject_id, dwi_file, metadata, parameters):
9191
name="outputnode",
9292
)
9393

94-
denoise = pe.Node(mrtrix3.DWIDenoise(), name="denoise")
95-
96-
unring = pe.Node(mrtrix3.MRDeGibbs(), name="unring")
97-
98-
resample = pe.Node(
99-
mrtrix3.MRResize(voxel_size=parameters.output_resolution), name="resample"
100-
)
94+
dwi_prep_wf = init_prep_dwi_wf(parameters.ignore, parameters.output_resolution)
10195

10296
def gen_index(in_file):
10397
import os
@@ -242,51 +236,9 @@ def b0_average(in_dwi, in_bval, b0_thresh, out_file=None):
242236
]
243237
)
244238

245-
if "denoise" in parameters.ignore:
246-
unring_wf = init_unring_wf()
247-
248-
dwi_wf.connect(
249-
[
250-
(inputnode, unring_wf, [("dwi_file", "inputnode.dwi_file")]),
251-
(unring_wf, avg_b0_0, [("outputnode.out_file", "in_dwi")]),
252-
(unring_wf, ecc, [("outputnode.out_file", "in_file")]),
253-
]
254-
)
255-
256-
elif "unring" in parameters.ignore:
257-
denoise_wf = init_denoise_wf()
258-
259-
dwi_wf.connect(
260-
[
261-
(inputnode, denoise_wf, [("dwi_file", "inputnode.dwi_file")]),
262-
(denoise_wf, avg_b0_0, [("outputnode.out_file", "in_dwi")]),
263-
(denoise_wf, ecc, [("outputnode.out_file", "in_file")]),
264-
]
265-
)
266-
267-
else:
268-
denoise_wf = init_denoise_wf()
269-
unring_wf = init_unring_wf()
270-
271-
dwi_wf.connect(
272-
[
273-
(inputnode, denoise_wf, [("dwi_file", "inputnode.dwi_file")]),
274-
(
275-
denoise_wf,
276-
unring_wf,
277-
[("outputnode.out_file", "inputnode.dwi_file")],
278-
),
279-
(unring_wf, avg_b0_0, [("outputnode.out_file", "in_dwi")]),
280-
(unring_wf, ecc, [("outputnode.out_file", "in_file")]),
281-
]
282-
)
283-
284239
fslroi = pe.Node(fsl.ExtractROI(t_min=0, t_size=1), name="fslroi")
285240

286-
bias_correct = pe.Node(
287-
ants.N4BiasFieldCorrection(save_bias=True, copy_header=True, dimension=3),
288-
name="bias_correct",
289-
)
241+
bias_correct = pe.Node(mrtrix3.DWIBiasCorrect(use_ants=True), name="bias_correct")
290242

291243
def get_b0_mask_fn(b0_file):
292244
import os
@@ -312,16 +264,24 @@ def get_b0_mask_fn(b0_file):
312264

313265
dwi_wf.connect(
314266
[
267+
(inputnode, dwi_prep_wf, [("dwi_file", "inputnode.dwi_file")]),
268+
(dwi_prep_wf, avg_b0_0, [("outputnode.out_file", "in_dwi")]),
315269
(inputnode, avg_b0_0, [("bval_file", "in_bval")]),
316270
(avg_b0_0, bet_dwi0, [("out_file", "in_file")]),
271+
(dwi_prep_wf, ecc, [("outputnode.out_file", "in_file")]),
317272
(inputnode, ecc, [("bval_file", "in_bval"), ("bvec_file", "in_bvec")]),
318273
(bet_dwi0, ecc, [("mask_file", "in_mask")]),
319274
(gen_idx, ecc, [("out_file", "in_index")]),
320275
(acqp, ecc, [("out_file", "in_acqp")]),
321276
(ecc, denoise_eddy, [("out_corrected", "in_file")]),
322-
(ecc, fslroi, [("out_corrected", "in_file")]),
323-
(fslroi, bias_correct, [("roi_file", "input_image")]),
324-
(bias_correct, b0mask_node, [("output_image", "b0_file")]),
277+
(
278+
ecc,
279+
bias_correct,
280+
[("out_corrected", "in_file"), ("out_rotated_bvecs", "in_bvec")],
281+
),
282+
(inputnode, bias_correct, [("bval_file", "in_bval")]),
283+
(bias_correct, fslroi, [("out_file", "in_file")]),
284+
(fslroi, b0mask_node, [("roi_file", "b0_file")]),
325285
(
326286
ecc,
327287
eddy_quad,

dmriprep/workflows/dwi/denoise.py

Lines changed: 0 additions & 24 deletions
This file was deleted.

dmriprep/workflows/dwi/prep_dwi.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,49 +10,50 @@
1010
from nipype.interfaces import mrtrix3, utility as niu
1111

1212

13-
def init_remove_artefacts_wf(parameters):
13+
def init_prep_dwi_wf(ignore, output_resolution):
1414

15-
dwi_prep_wf = pe.Workflow(name="remove_artefacts_wf")
15+
prep_dwi_wf = pe.Workflow(name="prep_dwi_wf")
16+
17+
inputnode = pe.Node(niu.IdentityInterface(fields=["dwi_file"]), name="inputnode")
18+
19+
outputnode = pe.Node(niu.IdentityInterface(fields=["out_file"]), name="outputnode")
1620

1721
denoise = pe.Node(mrtrix3.DWIDenoise(), name="denoise")
1822

1923
unring = pe.Node(mrtrix3.MRDeGibbs(), name="unring")
2024

21-
resample = pe.Node(
22-
mrtrix3.MRResize(voxel_size=parameters.output_resolution), name="resample"
23-
)
25+
resample = pe.Node(mrtrix3.MRResize(voxel_size=[1, 1, 1]), name="resample")
2426

25-
inputnode = pe.Node(niu.IdentityInterface(fields=["dwi_file"]), name="inputnode")
26-
27-
outputnode = pe.Node(niu.IdentityInterface(fields=["out_file"]), name="outputnode")
27+
prep_full = ["denoise", "unring", "resample"]
2828

29-
prep_full = ["denoise", "unring"]
29+
if not output_resolution:
30+
ignore.append("resample")
3031

31-
prep_wanted_str = [node for node in prep_full if not (node in ignore_nodes)]
32+
prep_wanted_str = [node for node in prep_full if not (node in ignore)]
3233

3334
# Translate string input to node names
34-
str2node = {"denoise": denoise, "unring": unring}
35+
str2node = {"denoise": denoise, "unring": unring, "resample": resample}
3536

3637
prep_wanted = [str2node[str_node] for str_node in prep_wanted_str]
3738

3839
# If no steps selected, just connect input to output
3940
if not (prep_wanted):
40-
dwi_prep_wf.connect([(inputnode, outputnode, [("dwi_file", "out_file")])])
41+
prep_dwi_wf.connect([(inputnode, outputnode, [("dwi_file", "out_file")])])
4142

4243
# If there are steps
4344
else:
4445
# Must at least connect input node to first node
4546
first_node = prep_wanted[0]
46-
dwi_prep_wf.connect([(inputnode, first_node, [("dwi_file", "in_file")])])
47+
prep_dwi_wf.connect([(inputnode, first_node, [("dwi_file", "in_file")])])
4748
# Loop through the prep order
4849
# Note: only works if each node has in_file and out_file
4950
# Can work around this by wrapping in node/workflow with in_file+out_file
5051
prev = first_node
5152
for curr_node in prep_wanted[1:]:
52-
dwi_prep_wf.connect([(prev, curr_node, [("out_file", "in_file")])])
53+
prep_dwi_wf.connect([(prev, curr_node, [("out_file", "in_file")])])
5354
prev = curr_node
5455
# Connect last node to output node
5556
last_node = prep_wanted[-1]
56-
dwi_prep_wf.connect([(last_node, outputnode, [("out_file", "out_file")])])
57+
prep_dwi_wf.connect([(last_node, outputnode, [("out_file", "out_file")])])
5758

58-
return dwi_prep_wf
59+
return prep_dwi_wf

dmriprep/workflows/dwi/resample.py

Lines changed: 0 additions & 28 deletions
This file was deleted.

dmriprep/workflows/dwi/unring.py

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)