Skip to content

Commit 97e1021

Browse files
author
David Ellis
committed
FIX: Switches around the intensity normalization for 5.3
1 parent e81d637 commit 97e1021

File tree

4 files changed

+101
-54
lines changed

4 files changed

+101
-54
lines changed

nipype/workflows/smri/freesurfer/autorecon1.py

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ def checkT1s(T1_files, cw256=False):
3636
return T1_files, cw256, resample_type, origvol_names
3737

3838
def create_AutoRecon1(name="AutoRecon1", longitudinal=False, distance=200,
39-
custom_atlas=None, plugin_args=None, shrink=2, stop=0.0001):
39+
custom_atlas=None, plugin_args=None, shrink=2, stop=0.0001,
40+
fsvernum=5.3):
4041
"""Creates the AutoRecon1 workflow in nipype.
4142
4243
Inputs::
@@ -239,14 +240,9 @@ def createTemplate(in_files, out_file):
239240
bias_correction.inputs.protocol_iterations = 1000
240241
bias_correction.inputs.distance = distance
241242
if stop:
242-
# per c.larsen, decrease convergence threshold (default is 0.001)
243243
bias_correction.inputs.stop = stop
244244
if shrink:
245-
# per c.larsen, decrease shrink parameter: finer sampling (default is 4)
246245
bias_correction.inputs.shrink = shrink
247-
# add the mask, as per c.larsen, bias-field correction is known to work
248-
# much better when the brain area is properly masked, in this case by
249-
# brainmask.mgz.
250246
bias_correction.inputs.no_rescale = True
251247
bias_correction.inputs.out_file = 'orig_nu.mgz'
252248

@@ -340,6 +336,28 @@ def awkfile(in_file, log_file):
340336
tal_qc = pe.Node(TalairachQC(), name="Detect_Aligment_Failures")
341337
ar1_wf.connect([(awk_logfile, tal_qc, [('log_file', 'log_file')])])
342338

339+
340+
if fsvernum < 6:
341+
# intensity correction is performed before normalization
342+
intensity_correction = pe.Node(
343+
MNIBiasCorrection(), name="Intensity_Correction")
344+
intensity_correction.inputs.out_file = 'nu.mgz'
345+
intensity_correction.inputs.iterations = 2
346+
ar2_wf.connect([(inputspec, intensity_correction, [('orig', 'in_file'),
347+
('brainmask', 'mask'),
348+
('transform', 'transform')])])
349+
350+
351+
add_to_header_nu = pe.Node(AddXFormToHeader(), name="Add_XForm_to_NU")
352+
add_to_header_nu.inputs.copy_name = True
353+
add_to_header_nu.inputs.out_file = 'nu.mgz'
354+
ar2_wf.connect([(intensity_correction, add_to_header_nu, [('out_file', 'in_file'),
355+
]),
356+
(copy_transform, add_to_header_nu,
357+
[('out_file', 'transform')])
358+
])
359+
360+
343361
# Intensity Normalization
344362
# Performs intensity normalization of the orig volume and places the result in mri/T1.mgz.
345363
# Attempts to correct for fluctuations in intensity that would otherwise make intensity-based
@@ -349,10 +367,13 @@ def awkfile(in_file, log_file):
349367
mri_normalize = pe.Node(Normalize(), name="Normalize_T1")
350368
mri_normalize.inputs.gradient = 1
351369
mri_normalize.inputs.out_file = 'T1.mgz'
352-
ar1_wf.connect([(add_xform_to_orig_nu, mri_normalize, [('out_file', 'in_file')]),
353-
(copy_transform, mri_normalize,
354-
[('out_file', 'transform')]),
355-
])
370+
371+
if fsvernum < 6:
372+
ar1_wf.connect([(add_to_header_nu, mri_normalize, [('out_file', 'in_file')])])
373+
else:
374+
ar1_wf.connect([(add_xform_to_orig_nu, mri_normalize, [('out_file', 'in_file')])])
375+
376+
ar1_wf.connect([(copy_transform, mri_normalize, [('out_file', 'transform')])])
356377

357378
# Skull Strip
358379
"""
@@ -422,8 +443,14 @@ def awkfile(in_file, log_file):
422443
'brainmask_auto',
423444
'brainmask',
424445
'braintemplate']
425-
outputspec = pe.Node(IdentityInterface(fields=outputs),
426-
name="outputspec")
446+
447+
if fsvernum < 6:
448+
outputspec = pe.Node(IdentityInterface(fields=outputs + 'nu'),
449+
name="outputspec")
450+
ar1_wf.connect([(add_to_header_nu, outputspec, [('out_file', 'nu')])])
451+
else:
452+
outputspec = pe.Node(IdentityInterface(fields=outputs),
453+
name="outputspec")
427454

428455
ar1_wf.connect([(T1_image_preparation, outputspec, [('out_file', 'origvols')]),
429456
(T2_convert, outputspec, [('out_file', 't2_raw')]),

nipype/workflows/smri/freesurfer/autorecon2.py

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ def copy_ltas(in_file, subjects_dir, subject_id, long_template):
1111
return out_file
1212

1313
def create_AutoRecon2(name="AutoRecon2", longitudinal=False,
14-
field_strength="1.5T", plugin_args=None):
14+
plugin_args=None, fsvernum=5.3):
1515
# AutoRecon2
1616
# Workflow
1717
ar2_wf = pe.Workflow(name=name)
1818

1919
inputspec = pe.Node(IdentityInterface(fields=['orig',
20+
'nu', # version < 6
2021
'brainmask',
2122
'transform',
2223
'subject_id',
@@ -47,40 +48,39 @@ def create_AutoRecon2(name="AutoRecon2", longitudinal=False,
4748
inputspec.inputs.timepoints = config['timepoints']
4849

4950

50-
# NU Intensity Correction
51-
"""
52-
Non-parametric Non-uniform intensity Normalization (N3), corrects for
53-
intensity non-uniformity in MR data, making relatively few assumptions about
54-
the data. This runs the MINC tool 'nu_correct'.
55-
"""
56-
intensity_correction = pe.Node(
57-
MNIBiasCorrection(), name="Intensity_Correction")
58-
intensity_correction.inputs.iterations = 1
59-
intensity_correction.inputs.protocol_iterations = 1000
60-
intensity_correction.inputs.stop = 0.0001
61-
intensity_correction.inputs.shrink = 2
62-
if field_strength == '3T':
63-
intensity_correction.inputs.distance = 50
64-
else:
65-
# default for 1.5T scans
66-
intensity_correction.inputs.distance = 200
67-
68-
intensity_correction.inputs.out_file = 'nu.mgz'
69-
ar2_wf.connect([(inputspec, intensity_correction, [('orig', 'in_file'),
70-
('brainmask', 'mask'),
71-
('transform', 'transform')
72-
])
73-
])
74-
75-
add_to_header_nu = pe.Node(AddXFormToHeader(), name="Add_XForm_to_NU")
76-
add_to_header_nu.inputs.copy_name = True
77-
add_to_header_nu.inputs.out_file = 'nu.mgz'
78-
ar2_wf.connect([(intensity_correction, add_to_header_nu, [('out_file', 'in_file'),
51+
if fsvernum >= 6:
52+
# NU Intensity Correction
53+
"""
54+
Non-parametric Non-uniform intensity Normalization (N3), corrects for
55+
intensity non-uniformity in MR data, making relatively few assumptions about
56+
the data. This runs the MINC tool 'nu_correct'.
57+
"""
58+
intensity_correction = pe.Node(
59+
MNIBiasCorrection(), name="Intensity_Correction")
60+
intensity_correction.inputs.out_file = 'nu.mgz'
61+
ar2_wf.connect([(inputspec, intensity_correction, [('orig', 'in_file'),
62+
('brainmask', 'mask'),
63+
('transform', 'transform')])])
64+
65+
# intensity correction parameters are more specific in 6+
66+
intensity_correction.inputs.iterations = 1
67+
intensity_correction.inputs.protocol_iterations = 1000
68+
if stop:
69+
intensity_correction.inputs.stop = stop
70+
if shrink:
71+
intensity_correction.inputs.shrink = shrink
72+
intensity_correction.inputs.distance = distance
73+
74+
add_to_header_nu = pe.Node(AddXFormToHeader(), name="Add_XForm_to_NU")
75+
add_to_header_nu.inputs.copy_name = True
76+
add_to_header_nu.inputs.out_file = 'nu.mgz'
77+
ar2_wf.connect([(intensity_correction, add_to_header_nu, [('out_file', 'in_file'),
7978
]),
80-
(inputspec, add_to_header_nu,
81-
[('transform', 'transform')])
79+
(inputspec, add_to_header_nu,
80+
[('transform', 'transform')])
8281
])
8382

83+
8484
# EM Registration
8585
"""
8686
Computes the transform to align the mri/nu.mgz volume to the default GCA
@@ -103,8 +103,12 @@ def create_AutoRecon2(name="AutoRecon2", longitudinal=False,
103103
align_transform.plugin_args = plugin_args
104104
ar2_wf.connect([(inputspec, align_transform, [('brainmask', 'mask'),
105105
('reg_template', 'template'),
106-
('num_threads', 'num_threads')]),
107-
(add_to_header_nu, align_transform, [('out_file', 'in_file')])])
106+
('num_threads', 'num_threads')])])
107+
if fsvernum >= 6:
108+
ar2_wf.connect([(add_to_header_nu, align_transform, [('out_file', 'in_file')])])
109+
else:
110+
ar2_wf.connect([(inputspec, align_transform, [('nu', 'in_file')])])
111+
108112

109113
# CA Normalize
110114
"""
@@ -128,8 +132,12 @@ def create_AutoRecon2(name="AutoRecon2", longitudinal=False,
128132

129133
ar2_wf.connect([(align_transform, ca_normalize, [('out_file', 'transform')]),
130134
(inputspec, ca_normalize, [('brainmask', 'mask'),
131-
('reg_template', 'atlas')]),
132-
(add_to_header_nu, ca_normalize, [('out_file', 'in_file')])])
135+
('reg_template', 'atlas')])])
136+
if fsvernum >= 6:
137+
ar2_wf.connect([(add_to_header_nu, ca_normalize, [('out_file', 'in_file')])])
138+
else:
139+
ar2_wf.connect([(inputspec, ca_normalize, [('nu', 'in_file')])])
140+
133141

134142
# CA Register
135143
# Computes a nonlinear transform to align with GCA atlas.
@@ -159,8 +167,11 @@ def create_AutoRecon2(name="AutoRecon2", longitudinal=False,
159167
remove_neck.inputs.radius = 25
160168
remove_neck.inputs.out_file = 'nu_noneck.mgz'
161169
ar2_wf.connect([(ca_register, remove_neck, [('out_file', 'transform')]),
162-
(add_to_header_nu, remove_neck, [('out_file', 'in_file')]),
163170
(inputspec, remove_neck, [('reg_template', 'template')])])
171+
if fsvernum >= 6:
172+
ar2_wf.connect([(add_to_header_nu, remove_neck, [('out_file', 'in_file')])])
173+
else:
174+
ar2_wf.connect([(inputspec, remove_neck, [('nu', 'in_file')])])
164175

165176
# SkullLTA (EM Registration, with Skull)
166177
# Computes transform to align volume mri/nu_noneck.mgz with GCA volume
@@ -680,8 +691,14 @@ def create_AutoRecon2(name="AutoRecon2", longitudinal=False,
680691
outputspec = pe.Node(IdentityInterface(fields=outputs),
681692
name="outputspec")
682693

683-
ar2_wf.connect([(add_to_header_nu, outputspec, [('out_file', 'nu')]),
684-
(align_transform, outputspec, [('out_file', 'tal_lta')]),
694+
if fsvernum >= 6:
695+
ar2_wf.connect([(add_to_header_nu, outputspec, [('out_file', 'nu')])])
696+
else:
697+
# add to outputspec to perserve datasinking
698+
ar2_wf.connect([(inputspec, outputspec, [('nu', 'nu')])])
699+
700+
701+
ar2_wf.connect([(align_transform, outputspec, [('out_file', 'tal_lta')]),
685702
(ca_normalize, outputspec, [('out_file', 'norm')]),
686703
(ca_normalize, outputspec, [('control_points', 'ctrl_pts')]),
687704
(ca_register, outputspec, [('out_file', 'tal_m3z')]),

nipype/workflows/smri/freesurfer/ba_maps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def create_ba_maps_wf(name="Brodmann_Area_Maps", th3=True, exvivo=True,
6767
out_files = list()
6868
if threshold:
6969
for label in labels:
70-
if label == 'perirhinal' and entorhinal:
70+
if label == 'perirhinal' and not entorhinal:
7171
# versions < 6.0 do not use thresh.perirhinal
7272
continue
7373
if exvivo:

nipype/workflows/smri/freesurfer/recon.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ def create_reconall_workflow(name="ReconAll", plugin_args=None,
139139
fs_version_full = Info.version()
140140
if 'v6.0' in fs_version_full or 'dev' in fs_version_full:
141141
# assuming that dev is 6.0
142+
fsvernum = 6.0
142143
fs_version = 'v6.0'
143144
th3 = True
144145
shrink = 2
@@ -149,6 +150,7 @@ def create_reconall_workflow(name="ReconAll", plugin_args=None,
149150
rb_date = "2014-08-21"
150151
else:
151152
# 5.3 is default
153+
fsvernum = 5.3
152154
if 'v5.3' in fs_version_full:
153155
fs_version = 'v5.3'
154156
else:
@@ -245,7 +247,8 @@ def checkarg(arg, default):
245247

246248
# create AutoRecon1
247249
ar1_wf, ar1_outputs = create_AutoRecon1(plugin_args=plugin_args, stop=stop,
248-
distance=distance, shrink=shrink)
250+
distance=distance, shrink=shrink,
251+
fsvernum=fsvernum)
249252
# connect inputs for AutoRecon1
250253
reconall.connect([(inputspec, ar1_wf, [('T1_files', 'inputspec.T1_files'),
251254
('T2_file', 'inputspec.T2_file'),
@@ -257,7 +260,7 @@ def checkarg(arg, default):
257260
('awk_file', 'inputspec.awk_file')])])
258261

259262
# create AutoRecon2
260-
ar2_wf, ar2_outputs = create_AutoRecon2(plugin_args=plugin_args)
263+
ar2_wf, ar2_outputs = create_AutoRecon2(plugin_args=plugin_args, fsvernum=fsvernum)
261264
# connect inputs for AutoRecon2
262265
reconall.connect([(inputspec, ar2_wf, [('num_threads', 'inputspec.num_threads')]),
263266
(config_node, ar2_wf, [('reg_template_withskull',

0 commit comments

Comments
 (0)