Skip to content

Commit ec55934

Browse files
committed
fix fmri_spm_nested #1538
1 parent 6247d12 commit ec55934

File tree

3 files changed

+72
-48
lines changed

3 files changed

+72
-48
lines changed

circle.yml

+5-5
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ dependencies:
1919
test:
2020
override:
2121
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/scratch:/scratch -w /scratch --entrypoint="/usr/bin/run_builddocs.sh" nipype/testbench
22-
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/scratch:/scratch -w /scratch nipype/testbench test_spm Linear /root/examples/ workflow3d workflow4d :
22+
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/scratch:/scratch -w /scratch nipype/testbench test_spm MultiProc /root/examples/ workflow3d workflow4d :
2323
timeout: 1600
24-
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/scratch:/scratch -w /scratch nipype/testbench fmri_fsl_feeds Linear /root/examples/ l1pipeline
25-
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/scratch:/scratch -w /scratch nipype/testbench fmri_spm_dartel Linear /root/examples/ level1 l2pipeline :
24+
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/scratch:/scratch -w /scratch nipype/testbench fmri_fsl_feeds MultiProc /root/examples/ l1pipeline
25+
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/scratch:/scratch -w /scratch nipype/testbench fmri_spm_dartel MultiProc /root/examples/ level1 l2pipeline :
2626
timeout: 1600
27-
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/scratch:/scratch -w /scratch nipype/testbench fmri_fsl_reuse Linear /root/examples/ level1_workflow
28-
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/scratch:/scratch -w /scratch nipype/testbench fmri_spm_nested Linear /root/examples/ level1 l2pipeline
27+
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/scratch:/scratch -w /scratch nipype/testbench fmri_fsl_reuse MultiProc /root/examples/ level1_workflow
28+
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/scratch:/scratch -w /scratch nipype/testbench fmri_spm_nested MultiProc /root/examples/ level1 l2pipeline
2929
- docker run -i -v /etc/localtime:/etc/localtime:ro -v ~/scratch:/scratch -w /scratch --entrypoint="/usr/bin/run_nosetests.sh" nipype/testbench :
3030
timeout: 2600
3131
post:

examples/fmri_spm_nested.py

+54-39
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,16 @@
1717

1818
from __future__ import print_function
1919
from builtins import range
20+
import os.path as op # system functions
2021

21-
import nipype.interfaces.io as nio # Data i/o
22-
import nipype.interfaces.spm as spm # spm
23-
import nipype.interfaces.matlab as mlab # how to run matlab
24-
import nipype.interfaces.fsl as fsl # fsl
25-
import nipype.interfaces.utility as niu # utility
26-
import nipype.pipeline.engine as pe # pypeline engine
27-
import nipype.algorithms.rapidart as ra # artifact detection
28-
import nipype.algorithms.modelgen as model # model specification
29-
import os # system functions
22+
from nipype.interfaces import io as nio # Data i/o
23+
from nipype.interfaces import spm as spm # spm
24+
# from nipype.interfaces import matlab as mlab # how to run matlab
25+
from nipype.interfaces import fsl as fsl # fsl
26+
from nipype.interfaces import utility as niu # utility
27+
from nipype.pipeline import engine as pe # pypeline engine
28+
from nipype.algorithms import rapidart as ra # artifact detection
29+
from nipype.algorithms import modelgen as model # model specification
3030

3131
"""
3232
@@ -65,19 +65,27 @@
6565

6666
preproc = pe.Workflow(name='preproc')
6767

68+
"""
69+
A node called :code:`inputnode` is set to designate the path in which input data
70+
are located:
71+
"""
72+
73+
inputnode = pe.Node(niu.IdentityInterface(fields=['in_data']), name='inputnode')
74+
75+
6876
"""Use :class:`nipype.interfaces.spm.Realign` for motion correction
6977
and register all images to the mean image.
7078
"""
7179

72-
realign = pe.Node(interface=spm.Realign(), name="realign")
80+
realign = pe.Node(spm.Realign(), name="realign")
7381
realign.inputs.register_to_mean = True
7482

7583
"""Use :class:`nipype.algorithms.rapidart` to determine which of the
7684
images in the functional series are outliers based on deviations in
7785
intensity or movement.
7886
"""
7987

80-
art = pe.Node(interface=ra.ArtifactDetect(), name="art")
88+
art = pe.Node(ra.ArtifactDetect(), name="art")
8189
art.inputs.use_differences = [True, False]
8290
art.inputs.use_norm = True
8391
art.inputs.norm_threshold = 1
@@ -89,14 +97,14 @@
8997
:class:`nipype.interfaces.fsl.BET`.
9098
"""
9199

92-
skullstrip = pe.Node(interface=fsl.BET(), name="skullstrip")
100+
skullstrip = pe.Node(fsl.BET(), name="skullstrip")
93101
skullstrip.inputs.mask = True
94102

95103
"""Use :class:`nipype.interfaces.spm.Coregister` to perform a rigid
96104
body registration of the functional data to the structural data.
97105
"""
98106

99-
coregister = pe.Node(interface=spm.Coregister(), name="coregister")
107+
coregister = pe.Node(spm.Coregister(), name="coregister")
100108
coregister.inputs.jobtype = 'estimate'
101109

102110

@@ -105,19 +113,19 @@
105113
includes the template image, T1.nii.
106114
"""
107115

108-
normalize = pe.Node(interface=spm.Normalize(), name="normalize")
109-
normalize.inputs.template = os.path.abspath('nipype-tutorial/data/T1.nii')
116+
normalize = pe.Node(spm.Normalize(), name="normalize")
110117

111118

112119
"""Smooth the functional data using
113120
:class:`nipype.interfaces.spm.Smooth`.
114121
"""
115122

116-
smooth = pe.Node(interface=spm.Smooth(), name="smooth")
123+
smooth = pe.Node(spm.Smooth(), name="smooth")
117124
fwhmlist = [4]
118125
smooth.iterables = ('fwhm', fwhmlist)
119126

120-
preproc.connect([(realign, coregister, [('mean_image', 'source'),
127+
preproc.connect([(inputnode, normalize, [(('in_data', _template_path), 'template')]),
128+
(realign, coregister, [('mean_image', 'source'),
121129
('realigned_files', 'apply_to_files')]),
122130
(coregister, normalize, [('coregistered_files', 'apply_to_files')]),
123131
(normalize, smooth, [('normalized_files', 'in_files')]),
@@ -140,40 +148,40 @@
140148
:class:`nipype.interfaces.spm.SpecifyModel`.
141149
"""
142150

143-
modelspec = pe.Node(interface=model.SpecifySPMModel(), name="modelspec")
151+
modelspec = pe.Node(model.SpecifySPMModel(), name="modelspec")
144152
modelspec.inputs.concatenate_runs = True
145153

146154
"""Generate a first level SPM.mat file for analysis
147155
:class:`nipype.interfaces.spm.Level1Design`.
148156
"""
149157

150-
level1design = pe.Node(interface=spm.Level1Design(), name="level1design")
158+
level1design = pe.Node(spm.Level1Design(), name="level1design")
151159
level1design.inputs.bases = {'hrf': {'derivs': [0, 0]}}
152160

153161
"""Use :class:`nipype.interfaces.spm.EstimateModel` to determine the
154162
parameters of the model.
155163
"""
156164

157-
level1estimate = pe.Node(interface=spm.EstimateModel(), name="level1estimate")
165+
level1estimate = pe.Node(spm.EstimateModel(), name="level1estimate")
158166
level1estimate.inputs.estimation_method = {'Classical': 1}
159167

160168
"""Use :class:`nipype.interfaces.spm.EstimateContrast` to estimate the
161169
first level contrasts specified in a few steps above.
162170
"""
163171

164-
contrastestimate = pe.Node(interface=spm.EstimateContrast(), name="contrastestimate")
172+
contrastestimate = pe.Node(spm.EstimateContrast(), name="contrastestimate")
165173

166174
"""Use :class: `nipype.interfaces.utility.Select` to select each contrast for
167175
reporting.
168176
"""
169177

170-
selectcontrast = pe.Node(interface=niu.Select(), name="selectcontrast")
178+
selectcontrast = pe.Node(niu.Select(), name="selectcontrast")
171179

172180
"""Use :class:`nipype.interfaces.fsl.Overlay` to combine the statistical output of
173181
the contrast estimate and a background image into one volume.
174182
"""
175183

176-
overlaystats = pe.Node(interface=fsl.Overlay(), name="overlaystats")
184+
overlaystats = pe.Node(fsl.Overlay(), name="overlaystats")
177185
overlaystats.inputs.stat_thresh = (3, 10)
178186
overlaystats.inputs.show_negative_stats = True
179187
overlaystats.inputs.auto_thresh_bg = True
@@ -182,7 +190,7 @@
182190
statistical volumes for a report of the first-level results.
183191
"""
184192

185-
slicestats = pe.Node(interface=fsl.Slicer(), name="slicestats")
193+
slicestats = pe.Node(fsl.Slicer(), name="slicestats")
186194
slicestats.inputs.all_axial = True
187195
slicestats.inputs.image_width = 750
188196

@@ -243,8 +251,7 @@
243251
info = dict(func=[['subject_id', ['f3', 'f5', 'f7', 'f10']]],
244252
struct=[['subject_id', 'struct']])
245253

246-
inputnode = pe.Node(niu.IdentityInterface(fields=['in_data']), name='inputnode')
247-
infosource = pe.Node(interface=niu.IdentityInterface(fields=['subject_id']), name="infosource")
254+
infosource = pe.Node(niu.IdentityInterface(fields=['subject_id']), name="infosource")
248255

249256
"""Here we set up iteration over all the subjects. The following line
250257
is a particular example of the flexibility of the system. The
@@ -265,7 +272,7 @@
265272
functionality.
266273
"""
267274

268-
datasource = pe.Node(interface=nio.DataGrabber(infields=['subject_id'],
275+
datasource = pe.Node(nio.DataGrabber(infields=['subject_id'],
269276
outfields=['func', 'struct']),
270277
name='datasource')
271278
datasource.inputs.template = 'nipype-tutorial/data/%s/%s.nii'
@@ -357,7 +364,7 @@ def subjectinfo(subject_id):
357364
"""
358365

359366
level1 = pe.Workflow(name="level1")
360-
level1.base_dir = os.path.abspath('spm_tutorial2/workingdir')
367+
level1.base_dir = op.abspath('spm_tutorial2/workingdir')
361368

362369
level1.connect([(inputnode, datasource, [('in_data', 'base_directory')]),
363370
(infosource, datasource, [('subject_id', 'subject_id')]),
@@ -389,16 +396,16 @@ def subjectinfo(subject_id):
389396
the mean image would be copied to that directory.
390397
"""
391398

392-
datasink = pe.Node(interface=nio.DataSink(), name="datasink")
393-
datasink.inputs.base_directory = os.path.abspath('spm_tutorial2/l1output')
394-
report = pe.Node(interface=nio.DataSink(), name='report')
395-
report.inputs.base_directory = os.path.abspath('spm_tutorial2/report')
399+
datasink = pe.Node(nio.DataSink(), name="datasink")
400+
datasink.inputs.base_directory = op.abspath('spm_tutorial2/l1output')
401+
report = pe.Node(nio.DataSink(), name='report')
402+
report.inputs.base_directory = op.abspath('spm_tutorial2/report')
396403
report.inputs.parameterization = False
397404

398405

399406
def getstripdir(subject_id):
400-
import os
401-
return os.path.join(os.path.abspath('spm_tutorial2/workingdir'), '_subject_id_%s' % subject_id)
407+
import os.path as op
408+
return op.join(op.abspath('spm_tutorial2/workingdir'), '_subject_id_%s' % subject_id)
402409

403410
# store relevant outputs from various stages of the 1st level analysis
404411
level1.connect([(infosource, datasink, [('subject_id', 'container'),
@@ -440,7 +447,7 @@ def getstripdir(subject_id):
440447
contrast_ids = list(range(1, len(contrasts) + 1))
441448
l2source = pe.Node(nio.DataGrabber(infields=['fwhm', 'con']), name="l2source")
442449
# we use .*i* to capture both .img (SPM8) and .nii (SPM12)
443-
l2source.inputs.template = os.path.abspath('spm_tutorial2/l1output/*/con*/*/_fwhm_%d/con_%04d.*i*')
450+
l2source.inputs.template = op.abspath('spm_tutorial2/l1output/*/con*/*/_fwhm_%d/con_%04d.*i*')
444451
# iterate over all contrast images
445452
l2source.iterables = [('fwhm', fwhmlist),
446453
('con', contrast_ids)]
@@ -453,10 +460,10 @@ def getstripdir(subject_id):
453460
"""
454461

455462
# setup a 1-sample t-test node
456-
onesamplettestdes = pe.Node(interface=spm.OneSampleTTestDesign(), name="onesampttestdes")
457-
l2estimate = pe.Node(interface=spm.EstimateModel(), name="level2estimate")
463+
onesamplettestdes = pe.Node(spm.OneSampleTTestDesign(), name="onesampttestdes")
464+
l2estimate = pe.Node(spm.EstimateModel(), name="level2estimate")
458465
l2estimate.inputs.estimation_method = {'Classical': 1}
459-
l2conestimate = pe.Node(interface=spm.EstimateContrast(), name="level2conestimate")
466+
l2conestimate = pe.Node(spm.EstimateContrast(), name="level2conestimate")
460467
cont1 = ('Group', 'T', ['mean'], [1])
461468
l2conestimate.inputs.contrasts = [cont1]
462469
l2conestimate.inputs.group_contrast = True
@@ -467,14 +474,22 @@ def getstripdir(subject_id):
467474
"""
468475

469476
l2pipeline = pe.Workflow(name="level2")
470-
l2pipeline.base_dir = os.path.abspath('spm_tutorial2/l2output')
477+
l2pipeline.base_dir = op.abspath('spm_tutorial2/l2output')
471478
l2pipeline.connect([(l2source, onesamplettestdes, [('outfiles', 'in_files')]),
472479
(onesamplettestdes, l2estimate, [('spm_mat_file', 'spm_mat_file')]),
473480
(l2estimate, l2conestimate, [('spm_mat_file', 'spm_mat_file'),
474481
('beta_images', 'beta_images'),
475482
('residual_image', 'residual_image')]),
476483
])
477484

485+
"""
486+
Inlining functions in connect()
487+
-------------------------------
488+
"""
489+
def _template_path(in_data):
490+
return op.abspath(op.join(in_data, 'nipype-tutorial/data/T1.nii'))
491+
492+
478493
"""
479494
Execute the second level pipeline
480495
---------------------------------

tools/run_examples.py

+13-4
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,25 @@
22
import os
33
import sys
44
from shutil import rmtree
5+
from multiprocessing import cpu_count
56

67

7-
def run_examples(example, pipelines, data_path, plugin):
8-
print('running example: %s with plugin: %s' % (example, plugin))
8+
def run_examples(example, pipelines, data_path, plugin=None):
99
from nipype import config
10+
from nipype.interfaces.base import CommandLine
11+
12+
if plugin is None:
13+
plugin = 'MultiProc'
14+
15+
print('running example: %s with plugin: %s' % (example, plugin))
1016
config.enable_debug_mode()
1117
config.enable_provenance()
12-
from nipype.interfaces.base import CommandLine
1318
CommandLine.set_default_terminal_output("stream")
1419

20+
plugin_args = {}
21+
if plugin == 'MultiProc':
22+
plugin_args['n_procs'] = cpu_count()
23+
1524
__import__(example)
1625
for pipeline in pipelines:
1726
wf = getattr(sys.modules[example], pipeline)
@@ -22,7 +31,7 @@ def run_examples(example, pipelines, data_path, plugin):
2231
'stop_on_first_rerun': 'true',
2332
'write_provenance': 'true'}}
2433
wf.inputs.inputnode.in_data = os.path.abspath(data_path)
25-
wf.run(plugin=plugin, plugin_args={'n_procs': 4})
34+
wf.run(plugin=plugin, plugin_args=plugin_args)
2635
# run twice to check if nothing is rerunning
2736
wf.run(plugin=plugin)
2837

0 commit comments

Comments
 (0)