Skip to content

Commit 01b38d4

Browse files
committed
Refactoring.
1 parent 240fa25 commit 01b38d4

File tree

5 files changed

+174
-73
lines changed

5 files changed

+174
-73
lines changed

examples/smri_ants_build_template.py

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#!/usr/bin/env python
2+
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
3+
# vi: set ft=python sts=4 ts=4 sw=4 et:
4+
"""
5+
===============================================
6+
sMRI: Using new ANTS for creating a T1 template
7+
===============================================
8+
9+
In this tutorial we will use ANTS (old version aka "ANTS") based workflow to
10+
create a template out of multiple T1 volumes.
11+
12+
1. Tell python where to find the appropriate functions.
13+
"""
14+
15+
import os
16+
import nipype.interfaces.utility as util
17+
import nipype.interfaces.ants as ants
18+
import nipype.interfaces.io as io
19+
import nipype.pipeline.engine as pe # pypeline engine
20+
21+
from nipype.workflows.smri.ants import ANTSTemplateBuildSingleIterationWF
22+
23+
"""
24+
2. Download T1 volumes into home directory
25+
"""
26+
27+
import urllib2
28+
homeDir=os.getenv("HOME")
29+
requestedPath=os.path.join(homeDir,'nipypeTestPath')
30+
mydatadir=os.path.realpath(requestedPath)
31+
if not os.path.exists(mydatadir):
32+
os.makedirs(mydatadir)
33+
print mydatadir
34+
35+
MyFileURLs=[
36+
('http://slicer.kitware.com/midas3/download?bitstream=13121','01_T1_half.nii.gz'),
37+
('http://slicer.kitware.com/midas3/download?bitstream=13122','02_T1_half.nii.gz'),
38+
('http://slicer.kitware.com/midas3/download?bitstream=13124','03_T1_half.nii.gz'),
39+
('http://slicer.kitware.com/midas3/download?bitstream=13128','01_T1_inv_half.nii.gz'),
40+
('http://slicer.kitware.com/midas3/download?bitstream=13123','02_T1_inv_half.nii.gz'),
41+
('http://slicer.kitware.com/midas3/download?bitstream=13125','03_T1_inv_half.nii.gz'),
42+
]
43+
for tt in MyFileURLs:
44+
myURL=tt[0]
45+
localFilename=os.path.join(mydatadir,tt[1])
46+
if not os.path.exists(localFilename):
47+
remotefile = urllib2.urlopen(myURL)
48+
49+
localFile = open(localFilename, 'wb')
50+
localFile.write(remotefile.read())
51+
localFile.close()
52+
print("Downloaded file: {0}".format(localFilename))
53+
else:
54+
print("File previously downloaded {0}".format(localFilename))
55+
56+
input_images=[
57+
os.path.join(mydatadir,'01_T1_half.nii.gz'),
58+
os.path.join(mydatadir,'02_T1_half.nii.gz'),
59+
os.path.join(mydatadir,'03_T1_half.nii.gz')
60+
]
61+
input_passive_images=[
62+
{'INV_T1':os.path.join(mydatadir,'01_T1_inv_half.nii.gz')},
63+
{'INV_T1':os.path.join(mydatadir,'02_T1_inv_half.nii.gz')},
64+
{'INV_T1':os.path.join(mydatadir,'03_T1_inv_half.nii.gz')}
65+
]
66+
67+
68+
"""
69+
3. Define the workflow and its working directory
70+
"""
71+
tbuilder=pe.Workflow(name="ANTSTemplateBuilder")
72+
tbuilder.base_dir=requestedPath
73+
74+
"""
75+
4. Define data sources. In real life these would be replace by DataGrabbers
76+
"""
77+
datasource = pe.Node(interface=util.IdentityInterface(fields=
78+
['imageList', 'passiveImagesDictionariesList']),
79+
run_without_submitting=True,
80+
name='InputImages' )
81+
datasource.inputs.imageList=input_images
82+
datasource.inputs.passiveImagesDictionariesList=input_passive_images
83+
84+
"""
85+
5. Template is initialized by a simple average
86+
"""
87+
initAvg = pe.Node(interface=ants.AverageImages(), name ='initAvg')
88+
initAvg.inputs.dimension = 3
89+
initAvg.inputs.normalize = True
90+
91+
tbuilder.connect(datasource, "imageList", initAvg, "images")
92+
93+
"""
94+
6. Define the first iteration of template building
95+
"""
96+
97+
buildTemplateIteration1=ANTSTemplateBuildSingleIterationWF('iteration01')
98+
tbuilder.connect(initAvg, 'output_average_image', buildTemplateIteration1, 'InputSpec.fixed_image')
99+
tbuilder.connect(datasource, 'imageList', buildTemplateIteration1, 'InputSpec.images')
100+
tbuilder.connect(datasource, 'passiveImagesDictionariesList', buildTemplateIteration1, 'InputSpec.ListOfPassiveImagesDictionaries')
101+
102+
"""
103+
7. Define the second iteration of template building
104+
"""
105+
106+
buildTemplateIteration2 = ANTSTemplateBuildSingleIterationWF('iteration02')
107+
tbuilder.connect(buildTemplateIteration1, 'OutputSpec.template', buildTemplateIteration2, 'InputSpec.fixed_image')
108+
tbuilder.connect(datasource, 'imageList', buildTemplateIteration2, 'InputSpec.images')
109+
tbuilder.connect(datasource, 'passiveImagesDictionariesList', buildTemplateIteration2, 'InputSpec.ListOfPassiveImagesDictionaries')
110+
111+
"""
112+
8. Move selected files to a designated results folder
113+
"""
114+
115+
datasink = pe.Node(io.DataSink(), name="datasink")
116+
datasink.inputs.base_directory = os.path.join(requestedPath, "results")
117+
118+
tbuilder.connect(buildTemplateIteration2, 'OutputSpec.template',datasink,'PrimaryTemplate')
119+
tbuilder.connect(buildTemplateIteration2, 'OutputSpec.passive_deformed_templates',datasink,'PassiveTemplate')
120+
tbuilder.connect(initAvg, 'output_average_image', datasink,'PreRegisterAverage')
121+
122+
"""
123+
8. Run the workflow
124+
"""
125+
126+
tbuilder.run()

examples/smri_ants_build_template_new.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
======================================================
88
99
In this tutorial we will use ANTS (new ITK4 version aka "antsRegistration") based workflow to
10-
create a template out of multiple T1 volumes.
10+
create a template out of multiple T1 volumes. We will also showcase how to fine tune SGE jobs requirements.
1111
1212
1. Tell python where to find the appropriate functions.
1313
"""
@@ -95,6 +95,12 @@
9595
"""
9696

9797
buildTemplateIteration1=antsRegistrationTemplateBuildSingleIterationWF('iteration01')
98+
"""
99+
Here we are fine tuning parameters of the SGE job (memory limit, numebr of cores etc.)
100+
"""
101+
BeginANTS = buildTemplateIteration1.get_node("BeginANTS")
102+
BeginANTS.plugin_args={'qsub_args': '-S /bin/bash -pe smp1 8-12 -l mem_free=6000M -o /dev/null -e /dev/null queue_name', 'overwrite': True}
103+
98104
tbuilder.connect(initAvg, 'output_average_image', buildTemplateIteration1, 'InputSpec.fixed_image')
99105
tbuilder.connect(datasource, 'imageList', buildTemplateIteration1, 'InputSpec.images')
100106
tbuilder.connect(datasource, 'passiveImagesDictionariesList', buildTemplateIteration1, 'InputSpec.ListOfPassiveImagesDictionaries')
@@ -104,6 +110,8 @@
104110
"""
105111

106112
buildTemplateIteration2 = antsRegistrationTemplateBuildSingleIterationWF('iteration02')
113+
BeginANTS = buildTemplateIteration2.get_node("BeginANTS")
114+
BeginANTS.plugin_args={'qsub_args': '-S /bin/bash -pe smp1 8-12 -l mem_free=6000M -o /dev/null -e /dev/null queue_name', 'overwrite': True}
107115
tbuilder.connect(buildTemplateIteration1, 'OutputSpec.template', buildTemplateIteration2, 'InputSpec.fixed_image')
108116
tbuilder.connect(datasource, 'imageList', buildTemplateIteration2, 'InputSpec.images')
109117
tbuilder.connect(datasource, 'passiveImagesDictionariesList', buildTemplateIteration2, 'InputSpec.ListOfPassiveImagesDictionaries')
@@ -123,4 +131,4 @@
123131
8. Run the workflow
124132
"""
125133

126-
tbuilder.run()
134+
tbuilder.run(plugin="SGE")

nipype/workflows/smri/ants/ANTSBuildTemplate.py

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -91,19 +91,30 @@ def FlattenTransformAndImagesList(ListOfPassiveImagesDictionaries,transformation
9191
print("HACK: flattened nametypes {0}\n".format(flattened_image_nametypes))
9292
print("HACK: flattened txfms {0}\n".format(flattened_transforms))
9393
return flattened_images,flattened_transforms,flattened_image_nametypes
94-
##
95-
## NOTE: The modes can be either 'SINGLE_IMAGE' or 'MULTI'
96-
## 'SINGLE_IMAGE' is quick shorthand when you are building an atlas with a single subject, then registration can
97-
## be short-circuted
98-
## any other string indicates the normal mode that you would expect and replicates the shell script build_template_parallel.sh
99-
def ANTSTemplateBuildSingleIterationWF(iterationPhasePrefix='',CLUSTER_QUEUE='',mode='MULTI'):
94+
95+
def ANTSTemplateBuildSingleIterationWF(iterationPhasePrefix=''):
96+
"""
97+
98+
Inputs::
99+
100+
inputspec.images :
101+
inputspec.fixed_image :
102+
inputspec.ListOfPassiveImagesDictionaries :
103+
104+
Outputs::
105+
106+
outputspec.template :
107+
outputspec.transforms_list :
108+
outputspec.passive_deformed_templates :
109+
"""
110+
100111

101112
TemplateBuildSingleIterationWF = pe.Workflow(name = 'ANTSTemplateBuildSingleIterationWF_'+str(str(iterationPhasePrefix)) )
102113

103114
inputSpec = pe.Node(interface=util.IdentityInterface(fields=['images', 'fixed_image',
104115
'ListOfPassiveImagesDictionaries']),
105116
run_without_submitting=True,
106-
name='InputSpec')
117+
name='inputspec')
107118
## HACK: TODO: Need to move all local functions to a common untility file, or at the top of the file so that
108119
## they do not change due to re-indenting. Otherwise re-indenting for flow control will trigger
109120
## their hash to change.
@@ -112,40 +123,19 @@ def ANTSTemplateBuildSingleIterationWF(iterationPhasePrefix='',CLUSTER_QUEUE='',
112123
outputSpec = pe.Node(interface=util.IdentityInterface(fields=['template','transforms_list',
113124
'passive_deformed_templates']),
114125
run_without_submitting=True,
115-
name='OutputSpec')
116-
117-
if mode == 'SINGLE_IMAGEXX':
118-
### HACK: A more general utility that is reused should be created.
119-
print "HACK: DOING SINGLE_IMAGE ", mode
120-
TemplateBuildSingleIterationWF.connect( [ (inputSpec, outputSpec, [(('images', GetFirstListElement ), 'template')] ), ])
121-
##HACK THIS DOES NOT WORK BECAUSE FILE NAMES ARE WRONG.
122-
TemplateBuildSingleIterationWF.connect( [ (inputSpec, outputSpec, [(('ListOfPassiveImagesDictionaries', GetFirstListElement ), 'passive_deformed_templates')] ), ])
123-
return TemplateBuildSingleIterationWF
124-
125-
print "HACK: DOING MULTI_IMAGE ", mode
126-
##import sys
127-
##sys.exit(-1)
128-
129-
126+
name='outputspec')
130127

131128
### NOTE MAP NODE! warp each of the original images to the provided fixed_image as the template
132129
BeginANTS=pe.MapNode(interface=ANTS(), name = 'BeginANTS', iterfield=['moving_image'])
133-
many_cpu_BeginANTS_options_dictionary={'qsub_args': '-S /bin/bash -pe smp1 8-12 -l mem_free=6000M -o /dev/null -e /dev/null '+CLUSTER_QUEUE, 'overwrite': True}
134-
BeginANTS.plugin_args=many_cpu_BeginANTS_options_dictionary
135130
BeginANTS.inputs.dimension = 3
136131
BeginANTS.inputs.output_transform_prefix = str(iterationPhasePrefix)+'_tfm'
137132
BeginANTS.inputs.metric = ['CC']
138133
BeginANTS.inputs.metric_weight = [1.0]
139134
BeginANTS.inputs.radius = [5]
140135
BeginANTS.inputs.transformation_model = 'SyN'
141136
BeginANTS.inputs.gradient_step_length = 0.25
142-
if mode == 'SINGLE_IMAGE_IMAGE':
143-
## HACK: Just short circuit time consuming step if only registering a single image.
144-
BeginANTS.inputs.number_of_iterations = [1]
145-
BeginANTS.inputs.number_of_affine_iterations = [1]
146-
else:
147-
BeginANTS.inputs.number_of_iterations = [50, 35, 15]
148-
BeginANTS.inputs.number_of_affine_iterations = [10000,10000,10000,10000,10000]
137+
BeginANTS.inputs.number_of_iterations = [50, 35, 15]
138+
BeginANTS.inputs.number_of_affine_iterations = [10000,10000,10000,10000,10000]
149139
BeginANTS.inputs.use_histogram_matching = True
150140
BeginANTS.inputs.mi_option = [32, 16000]
151141
BeginANTS.inputs.regularization = 'Gauss'

nipype/workflows/smri/ants/antsRegistrationBuildTemplate.py

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,27 @@ def FlattenTransformAndImagesList(ListOfPassiveImagesDictionaries,transforms,inv
109109
## 'SINGLE_IMAGE' is quick shorthand when you are building an atlas with a single subject, then registration can
110110
## be short-circuted
111111
## any other string indicates the normal mode that you would expect and replicates the shell script build_template_parallel.sh
112-
def antsRegistrationTemplateBuildSingleIterationWF(iterationPhasePrefix='',CLUSTER_QUEUE='',mode='MULTI'):
112+
def antsRegistrationTemplateBuildSingleIterationWF(iterationPhasePrefix=''):
113+
"""
114+
115+
Inputs::
116+
117+
inputspec.images :
118+
inputspec.fixed_image :
119+
inputspec.ListOfPassiveImagesDictionaries :
120+
121+
Outputs::
113122
123+
outputspec.template :
124+
outputspec.transforms_list :
125+
outputspec.passive_deformed_templates :
126+
"""
114127
TemplateBuildSingleIterationWF = pe.Workflow(name = 'antsRegistrationTemplateBuildSingleIterationWF_'+str(iterationPhasePrefix) )
115128

116129
inputSpec = pe.Node(interface=util.IdentityInterface(fields=['images', 'fixed_image',
117130
'ListOfPassiveImagesDictionaries']),
118131
run_without_submitting=True,
119-
name='InputSpec')
132+
name='inputspec')
120133
## HACK: TODO: Need to move all local functions to a common untility file, or at the top of the file so that
121134
## they do not change due to re-indenting. Otherwise re-indenting for flow control will trigger
122135
## their hash to change.
@@ -125,20 +138,7 @@ def antsRegistrationTemplateBuildSingleIterationWF(iterationPhasePrefix='',CLUST
125138
outputSpec = pe.Node(interface=util.IdentityInterface(fields=['template','transforms_list',
126139
'passive_deformed_templates']),
127140
run_without_submitting=True,
128-
name='OutputSpec')
129-
130-
if mode == 'SINGLE_IMAGEXX':
131-
### HACK: A more general utility that is reused should be created.
132-
print "HACK: DOING SINGLE_IMAGE ", mode
133-
TemplateBuildSingleIterationWF.connect( [ (inputSpec, outputSpec, [(('images', GetFirstListElement ), 'template')] ), ])
134-
##HACK THIS DOES NOT WORK BECAUSE FILE NAMES ARE WRONG.
135-
TemplateBuildSingleIterationWF.connect( [ (inputSpec, outputSpec, [(('ListOfPassiveImagesDictionaries', GetFirstListElement ), 'passive_deformed_templates')] ), ])
136-
return TemplateBuildSingleIterationWF
137-
138-
print "HACK: DOING MULTI_IMAGE ", mode
139-
##import sys
140-
##sys.exit(-1)
141-
141+
name='outputspec')
142142

143143

144144
### NOTE MAP NODE! warp each of the original images to the provided fixed_image as the template
@@ -152,11 +152,7 @@ def antsRegistrationTemplateBuildSingleIterationWF(iterationPhasePrefix='',CLUST
152152
BeginANTS.inputs.metric = ['Mattes', 'CC']
153153
BeginANTS.inputs.metric_weight = [1.0, 1.0]
154154
BeginANTS.inputs.radius_or_number_of_bins = [32, 5]
155-
if mode == 'SINGLE_IMAGE_IMAGE':
156-
## HACK: Just short circuit time consuming step if only registering a single image.
157-
BeginANTS.inputs.number_of_iterations = [[1], [1]]
158-
else:
159-
BeginANTS.inputs.number_of_iterations = [[1000, 1000, 1000], [50, 35, 15]]
155+
BeginANTS.inputs.number_of_iterations = [[1000, 1000, 1000], [50, 35, 15]]
160156
BeginANTS.inputs.use_histogram_matching = [True, True]
161157
BeginANTS.inputs.use_estimate_learning_rate_once = [False, False]
162158
BeginANTS.inputs.shrink_factors = [[3,2,1], [3,2,1]]

nipype/workflows/smri/ants/antsSimpleAverageWF.py

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

0 commit comments

Comments
 (0)