Skip to content

Commit d38cf9d

Browse files
committed
tst: keep expanding coverage, add tiny doctests
1 parent 4636791 commit d38cf9d

File tree

3 files changed

+106
-53
lines changed

3 files changed

+106
-53
lines changed

sdcflows/utils/misc.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""Basic miscelaneous utilities."""
2+
3+
4+
def front(inlist):
5+
"""
6+
Pop from a list or tuple, otherwise return untouched.
7+
8+
Examples
9+
--------
10+
>>> _front([1, 0])
11+
1
12+
13+
>>> _front("/path/somewhere")
14+
'/path/somewhere'
15+
16+
"""
17+
if isinstance(inlist, (list, tuple)):
18+
return inlist[0]
19+
return inlist
20+
21+
22+
def last(inlist):
23+
"""
24+
Return the last element from a list or tuple, otherwise return untouched.
25+
26+
Examples
27+
--------
28+
>>> _last([1, 0])
29+
0
30+
31+
>>> _last("/path/somewhere")
32+
'/path/somewhere'
33+
34+
"""
35+
if isinstance(inlist, (list, tuple)):
36+
return inlist[-1]
37+
return inlist

sdcflows/workflows/fit/pepolar.py

Lines changed: 68 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,7 @@ def init_topup_wf(omp_nthreads=1, debug=False, name="pepolar_estimate_wf"):
7575
)
7676
outputnode = pe.Node(
7777
niu.IdentityInterface(
78-
fields=[
79-
"fmap",
80-
"fmap_ref",
81-
"fmap_coeff",
82-
"jacobians",
83-
"xfms",
84-
"out_warps",
85-
]
78+
fields=["fmap", "fmap_ref", "fmap_coeff", "jacobians", "xfms", "out_warps"]
8679
),
8780
name="outputnode",
8881
)
@@ -166,40 +159,50 @@ def init_3dQwarp_wf(omp_nthreads=1, name="pepolar_estimate_wf"):
166159
)
167160
from niworkflows.interfaces.freesurfer import StructuralReference
168161
from niworkflows.func.util import init_enhance_and_skullstrip_bold_wf
162+
from ...utils.misc import front as _front, last as _last
169163
from ...interfaces.utils import Flatten
170164

171165
workflow = Workflow(name=name)
172166
workflow.__desc__ = f"""{_PEPOLAR_DESC} \
173167
with `3dQwarp` @afni (AFNI {''.join(['%02d' % v for v in afni.Info().version() or []])}).
174168
"""
175169

176-
inputnode = pe.Node(niu.IdentityInterface(fields=["in_data", "metadata"]),
177-
name="inputnode")
170+
inputnode = pe.Node(
171+
niu.IdentityInterface(fields=["in_data", "metadata"]), name="inputnode"
172+
)
178173

179174
outputnode = pe.Node(
180175
niu.IdentityInterface(fields=["fmap", "fmap_ref"]), name="outputnode"
181176
)
182177

183178
flatten = pe.Node(Flatten(), name="flatten")
184-
sort_pe = pe.Node(niu.Function(
185-
function=_sorted_pe, output_names=["sorted", "qwarp_args"]),
186-
name="sort_pe", run_without_submitting=True)
187-
188-
merge_pes = pe.MapNode(StructuralReference(
189-
auto_detect_sensitivity=True,
190-
initial_timepoint=1,
191-
fixed_timepoint=True, # Align to first image
192-
intensity_scaling=True,
193-
# 7-DOF (rigid + intensity)
194-
no_iteration=True,
195-
subsample_threshold=200,
196-
out_file='template.nii.gz'),
197-
name='merge_pes',
179+
sort_pe = pe.Node(
180+
niu.Function(function=_sorted_pe, output_names=["sorted", "qwarp_args"]),
181+
name="sort_pe",
182+
run_without_submitting=True,
183+
)
184+
185+
merge_pes = pe.MapNode(
186+
StructuralReference(
187+
auto_detect_sensitivity=True,
188+
initial_timepoint=1,
189+
fixed_timepoint=True, # Align to first image
190+
intensity_scaling=True,
191+
# 7-DOF (rigid + intensity)
192+
no_iteration=True,
193+
subsample_threshold=200,
194+
out_file="template.nii.gz",
195+
),
196+
name="merge_pes",
198197
iterfield=["in_files"],
199198
)
200199

201-
pe0_wf = init_enhance_and_skullstrip_bold_wf(omp_nthreads=omp_nthreads, name="pe0_wf")
202-
pe1_wf = init_enhance_and_skullstrip_bold_wf(omp_nthreads=omp_nthreads, name="pe1_wf")
200+
pe0_wf = init_enhance_and_skullstrip_bold_wf(
201+
omp_nthreads=omp_nthreads, name="pe0_wf"
202+
)
203+
pe1_wf = init_enhance_and_skullstrip_bold_wf(
204+
omp_nthreads=omp_nthreads, name="pe1_wf"
205+
)
203206

204207
align_pes = pe.Node(
205208
Registration(
@@ -228,11 +231,7 @@ def init_3dQwarp_wf(omp_nthreads=1, name="pepolar_estimate_wf"):
228231
cphdr_warp = pe.Node(CopyHeader(), name="cphdr_warp", mem_gb=0.01)
229232

230233
unwarp_reference = pe.Node(
231-
ApplyTransforms(
232-
dimension=3,
233-
float=True,
234-
interpolation="LanczosWindowedSinc",
235-
),
234+
ApplyTransforms(dimension=3, float=True, interpolation="LanczosWindowedSinc",),
236235
name="unwarp_reference",
237236
)
238237

@@ -278,7 +277,15 @@ def _fix_hdr(in_file, newpath=None):
278277

279278

280279
def _pe2fsl(metadata):
281-
"""Convert ijk notation to xyz."""
280+
"""
281+
Convert ijk notation to xyz.
282+
283+
Example
284+
-------
285+
>>> _pe2fsl([{"PhaseEncodingDirection": "j-"}, {"PhaseEncodingDirection": "i"}])
286+
['y-', 'x']
287+
288+
"""
282289
return [
283290
m["PhaseEncodingDirection"]
284291
.replace("i", "x")
@@ -289,6 +296,29 @@ def _pe2fsl(metadata):
289296

290297

291298
def _sorted_pe(inlist):
299+
"""
300+
Generate suitable inputs to ``3dQwarp``.
301+
302+
Example
303+
-------
304+
>>> paths, args = _sorted_pe([
305+
... ("dir-AP_epi.nii.gz", {"PhaseEncodingDirection": "j-"}),
306+
... ("dir-AP_bold.nii.gz", {"PhaseEncodingDirection": "j-"}),
307+
... ("dir-PA_epi.nii.gz", {"PhaseEncodingDirection": "j"}),
308+
... ("dir-PA_bold.nii.gz", {"PhaseEncodingDirection": "j"}),
309+
... ("dir-AP_sbref.nii.gz", {"PhaseEncodingDirection": "j-"}),
310+
... ("dir-PA_sbref.nii.gz", {"PhaseEncodingDirection": "j"}),
311+
... ])
312+
>>> paths[0]
313+
['dir-AP_epi.nii.gz', 'dir-AP_bold.nii.gz', 'dir-AP_sbref.nii.gz']
314+
315+
>>> paths[1]
316+
['dir-PA_epi.nii.gz', 'dir-PA_bold.nii.gz', 'dir-PA_sbref.nii.gz']
317+
318+
>>> args
319+
'-noXdis -noZdis'
320+
321+
"""
292322
out_ref = [inlist[0][0]]
293323
out_opp = []
294324

@@ -302,20 +332,9 @@ def _sorted_pe(inlist):
302332
else:
303333
raise ValueError("Cannot handle orthogonal PE encodings.")
304334

305-
return [out_ref, out_opp], {
306-
"i": "-noYdis -noZdis",
307-
"j": "-noXdis -noZdis",
308-
"k": "-noXdis -noYdis",
309-
}[ref_pe[0]]
310-
311-
312-
def _front(inlist):
313-
if isinstance(inlist, (list, tuple)):
314-
return inlist[0]
315-
return inlist
316-
317-
318-
def _last(inlist):
319-
if isinstance(inlist, (list, tuple)):
320-
return inlist[-1]
321-
return inlist
335+
return (
336+
[out_ref, out_opp],
337+
{"i": "-noYdis -noZdis", "j": "-noXdis -noZdis", "k": "-noXdis -noYdis"}[
338+
ref_pe[0]
339+
],
340+
)

sdcflows/workflows/fit/syn.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ def init_syn_sdc_wf(
120120
FixHeaderRegistration as Registration,
121121
)
122122
from niworkflows.interfaces.nibabel import Binarize
123+
from ...utils.misc import front as _pop
123124

124125
workflow = Workflow(name=name)
125126
workflow.__desc__ = f"""\
@@ -230,7 +231,3 @@ def _fixed_masks_arg(mask):
230231
231232
"""
232233
return ["NULL", mask]
233-
234-
235-
def _pop(inlist):
236-
return inlist[0]

0 commit comments

Comments
 (0)