Skip to content

Commit 8896ae2

Browse files
committed
Merge branch 'enh/vbm'
Conflicts: CHANGES
2 parents f51d9c3 + b774813 commit 8896ae2

File tree

3 files changed

+276
-2
lines changed

3 files changed

+276
-2
lines changed

CHANGES

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
Next release
22
============
3-
* ENH: New interfaces: nipy.Trim, fsl.GLM, fsl.SigLoss
3+
4+
* ENH: New interfaces: nipy.Trim, fsl.GLM, fsl.SigLoss, spm.VBMSegment
45
* ENH: Allow control over terminal output for commandline interfaces
56
* ENH: New workflows for dMRI and fMRI pre-processing: added motion artifact correction
67
with rotation of the B-matrix, and susceptibility correction for EPI imaging using

nipype/interfaces/spm/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
scans_for_fnames)
77
from .preprocess import (SliceTiming, Realign, Coregister, Normalize, Segment,
88
Smooth, NewSegment, DARTEL, DARTELNorm2MNI,
9-
CreateWarped)
9+
CreateWarped, VBMSegment)
1010
from .model import (Level1Design, EstimateModel, EstimateContrast, Threshold,
1111
OneSampleTTestDesign, TwoSampleTTestDesign,
1212
PairedTTestDesign, MultipleRegressionDesign)

nipype/interfaces/spm/preprocess.py

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,3 +1088,276 @@ def _list_outputs(self):
10881088
_, fname = os.path.split(filename)
10891089
outputs['out_files'].append(os.path.realpath('w%s'%fname))
10901090
return outputs
1091+
1092+
class VBMSegmentInputSpec(SPMCommandInputSpec):
1093+
1094+
in_files = InputMultiPath(
1095+
File(exists=True),
1096+
desc="A list of files to be segmented",
1097+
field='estwrite.data', copyfile=False, mandatory=True)
1098+
1099+
tissues = File(
1100+
exists=True, field='estwrite.tpm',
1101+
desc='tissue probability map')
1102+
gaussians_per_class = traits.Tuple(
1103+
(2, 2, 2, 3, 4, 2), *([traits.Int()]*6),
1104+
usedefault=True,
1105+
desc='number of gaussians for each tissue class')
1106+
bias_regularization = traits.Enum(
1107+
0.0001,
1108+
(0, 0.00001, 0.0001, 0.001, 0.01, 0.1, 1, 10),
1109+
field='estwrite.opts.biasreg', usedefault=True,
1110+
desc='no(0) - extremely heavy (10)')
1111+
1112+
bias_fwhm = traits.Enum(
1113+
60,
1114+
(30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 'Inf'),
1115+
field='estwrite.opts.biasfwhm',
1116+
usedefault=True,
1117+
desc='FWHM of Gaussian smoothness of bias')
1118+
sampling_distance = traits.Float(
1119+
3, usedefault=True, field='estwrite.opts.samp',
1120+
desc='Sampling distance on data for parameter estimation')
1121+
warping_regularization = traits.Float(
1122+
4, usedefault=True, field='estwrite.opts.warpreg',
1123+
desc='Controls balance between parameters and data')
1124+
1125+
spatial_normalization = traits.Enum(
1126+
'high', 'low', usedefault=True,)
1127+
dartel_template = File(
1128+
exists=True,
1129+
field='estwrite.extopts.dartelwarp.normhigh.darteltpm')
1130+
use_sanlm_denoising_filter = traits.Range(
1131+
0, 2, 2, usedefault=True, field='estwrite.extopts.sanlm',
1132+
desc="0=No denoising, 1=denoising,2=denoising multi-threaded")
1133+
mrf_weighting = traits.Float(
1134+
0.15, usedefault=True, field='estwrite.extopts.mrf')
1135+
cleanup_partitions = traits.Int(
1136+
1, usedefault=True, field='estwrite.extopts.cleanup',
1137+
desc="0=None,1=light,2=thorough")
1138+
display_results = traits.Bool(
1139+
True, usedefault=True, field='estwrite.extopts.print')
1140+
1141+
gm_native = traits.Bool(
1142+
False, usedefault=True, field='estwrite.output.GM.native',)
1143+
gm_normalized = traits.Bool(
1144+
False, usedefault=True, field='estwrite.output.GM.warped',)
1145+
gm_modulated_normalized = traits.Range(
1146+
0, 2, 2, usedefault=True, field='estwrite.output.GM.modulated',
1147+
desc='0=none,1=affine+non-linear(SPM8 default),2=non-linear only')
1148+
gm_dartel = traits.Range(
1149+
0, 2, 0, usedefault=True, field='estwrite.output.GM.dartel',
1150+
desc="0=None,1=rigid(SPM8 default),2=affine")
1151+
1152+
wm_native = traits.Bool(
1153+
False, usedefault=True, field='estwrite.output.WM.native',)
1154+
wm_normalized = traits.Bool(
1155+
False, usedefault=True, field='estwrite.output.WM.warped',)
1156+
wm_modulated_normalized = traits.Range(
1157+
0, 2, 2, usedefault=True, field='estwrite.output.WM.modulated',
1158+
desc='0=none,1=affine+non-linear(SPM8 default),2=non-linear only')
1159+
wm_dartel = traits.Range(
1160+
0, 2, 0, usedefault=True, field='estwrite.output.WM.dartel',
1161+
desc="0=None,1=rigid(SPM8 default),2=affine")
1162+
1163+
csf_native = traits.Bool(
1164+
False, usedefault=True, field='estwrite.output.CSF.native',)
1165+
csf_normalized = traits.Bool(
1166+
False, usedefault=True, field='estwrite.output.CSF.warped',)
1167+
csf_modulated_normalized = traits.Range(
1168+
0, 2, 2, usedefault=True, field='estwrite.output.CSF.modulated',
1169+
desc='0=none,1=affine+non-linear(SPM8 default),2=non-linear only')
1170+
csf_dartel = traits.Range(
1171+
0, 2, 0, usedefault=True, field='estwrite.output.CSF.dartel',
1172+
desc="0=None,1=rigid(SPM8 default),2=affine")
1173+
1174+
bias_corrected_native = traits.Bool(
1175+
False, usedefault=True, field='estwrite.output.bias.native',)
1176+
bias_corrected_normalized = traits.Bool(
1177+
True, usedefault=True, field='estwrite.output.bias.warped',)
1178+
bias_corrected_affine = traits.Bool(
1179+
False, usedefault=True, field='estwrite.output.bias.affine',)
1180+
1181+
pve_label_native = traits.Bool(
1182+
False, usedefault=True, field='estwrite.output.label.native')
1183+
pve_label_normalized = traits.Bool(
1184+
False, usedefault=True, field='estwrite.output.label.warped')
1185+
pve_label_dartel = traits.Range(
1186+
0, 2, 0, usedefault=True, field='estwrite.output.label.dartel',
1187+
desc="0=None,1=rigid(SPM8 default),2=affine")
1188+
1189+
jacobian_determinant = traits.Bool(
1190+
False, usedefault=True, field='estwrite.jacobian.warped')
1191+
1192+
deformation_field = traits.Tuple(
1193+
(0, 0), traits.Bool, traits.Bool, usedefault=True,
1194+
field='estwrite.output.warps',
1195+
desc='forward and inverse field')
1196+
1197+
class VBMSegmentOuputSpec(TraitedSpec):
1198+
1199+
native_class_images = traits.List(traits.List(File(exists=True)),
1200+
desc='native space probability maps')
1201+
dartel_input_images = traits.List(traits.List(File(exists=True)),
1202+
desc='dartel imported class images')
1203+
normalized_class_images = traits.List(traits.List(File(exists=True)),
1204+
desc='normalized class images')
1205+
modulated_class_images = traits.List(traits.List(File(exists=True)),
1206+
desc='modulated+normalized class images')
1207+
transformation_mat = OutputMultiPath(File(exists=True),
1208+
desc='Normalization transformation')
1209+
1210+
bias_corrected_images = OutputMultiPath(
1211+
File(exists=True),
1212+
desc='bias corrected images')
1213+
normalized_bias_corrected_images = OutputMultiPath(
1214+
File(exists=True),
1215+
desc='bias corrected images')
1216+
1217+
pve_label_native_images = OutputMultiPath(File(exists=True))
1218+
pve_label_normalized_images = OutputMultiPath(File(exists=True))
1219+
pve_label_registered_images = OutputMultiPath(File(exists=True))
1220+
1221+
forward_deformation_field = OutputMultiPath(File(exists=True))
1222+
inverse_deformation_field = OutputMultiPath(File(exists=True))
1223+
1224+
jacobian_determinant_images = OutputMultiPath(File(exists=True))
1225+
1226+
class VBMSegment(SPMCommand):
1227+
1228+
"""Use VBM8 toolbox to separate structural images into different
1229+
tissue classes.
1230+
1231+
Example
1232+
-------
1233+
>>> import nipype.interfaces.spm as spm
1234+
>>> seg = spm.VBMSegment()
1235+
>>> seg.inputs.tissues = 'TPM.nii'
1236+
>>> seg.inputs.dartel_template = 'Template_1_IXI550_MNI152.nii'
1237+
>>> seg.inputs.bias_corrected_native = True
1238+
>>> seg.inputs.gm_native = True
1239+
>>> seg.inputs.wm_native = True
1240+
>>> seg.inputs.csf_native = True
1241+
>>> seg.inputs.pve_label_native = True
1242+
>>> seg.inputs.deformation_field = (True, False)
1243+
>>> seg.run() # doctest: +SKIP
1244+
"""
1245+
1246+
input_spec = VBMSegmentInputSpec
1247+
output_spec = VBMSegmentOuputSpec
1248+
1249+
_jobtype = 'tools'
1250+
_jobname = 'vbm8'
1251+
1252+
def _list_outputs(self):
1253+
outputs = self._outputs().get()
1254+
1255+
do_dartel = self.inputs.spatial_normalization
1256+
dartel_px = ''
1257+
if do_dartel:
1258+
dartel_px = 'r'
1259+
1260+
outputs['native_class_images'] = [[], [], []]
1261+
outputs['dartel_input_images'] = [[], [], []]
1262+
outputs['normalized_class_images'] = [[], [], []]
1263+
outputs['modulated_class_images'] = [[], [], []]
1264+
1265+
outputs['transformation_mat'] = []
1266+
1267+
outputs['bias_corrected_images'] = []
1268+
outputs['normalized_bias_corrected_images'] = []
1269+
1270+
outputs['inverse_deformation_field'] = []
1271+
outputs['forward_deformation_field'] = []
1272+
outputs['jacobian_determinant_images'] = []
1273+
1274+
outputs['pve_label_native_images'] = []
1275+
outputs['pve_label_normalized_images'] = []
1276+
outputs['pve_label_registered_images'] = []
1277+
1278+
for filename in self.inputs.in_files:
1279+
pth, base, ext = split_filename(filename)
1280+
1281+
outputs['transformation_mat'].append(
1282+
os.path.join(pth, "%s_seg8.mat" % base))
1283+
1284+
for i, tis in enumerate(['gm', 'wm', 'csf']):
1285+
# native space
1286+
1287+
if getattr(self.inputs, '%s_native' % tis):
1288+
outputs['native_class_images'][i].append(
1289+
os.path.join(pth, "p%d%s.nii" % (i+1, base)))
1290+
if getattr(self.inputs, '%s_dartel' % tis) == 1:
1291+
outputs['dartel_input_images'][i].append(
1292+
os.path.join(pth, "rp%d%s.nii" % (i+1, base)))
1293+
elif getattr(self.inputs, '%s_dartel' % tis) == 2:
1294+
outputs['dartel_input_images'][i].append(
1295+
os.path.join(pth, "rp%d%s_affine.nii" % (i+1, base)))
1296+
1297+
# normalized space
1298+
if getattr(self.inputs, '%s_normalized' % tis):
1299+
outputs['normalized_class_images'][i].append(
1300+
os.path.join(pth, "w%sp%d%s.nii" % (dartel_px, i+1, base)))
1301+
1302+
if getattr(self.inputs, '%s_modulated_normalized' % tis) == 1:
1303+
outputs['modulated_class_images'][i].append(os.path.join(
1304+
pth, "mw%sp%d%s.nii" % (dartel_px, i+1, base)))
1305+
elif getattr(self.inputs, '%s_modulated_normalized' % tis) == 2:
1306+
outputs['normalized_class_images'][i].append(os.path.join(
1307+
pth, "m0w%sp%d%s.nii" % (dartel_px, i+1, base)))
1308+
1309+
if self.inputs.pve_label_native:
1310+
outputs['pve_label_native_images'].append(
1311+
os.path.join(pth, "p0%s.nii" % (base)))
1312+
if self.inputs.pve_label_normalized:
1313+
outputs['pve_label_normalized_images'].append(
1314+
os.path.join(pth, "w%sp0%s.nii" % (dartel_px, base)))
1315+
if self.inputs.pve_label_dartel == 1:
1316+
outputs['pve_label_registered_images'].append(
1317+
os.path.join(pth, "rp0%s.nii" % (base)))
1318+
elif self.inputs.pve_label_dartel == 2:
1319+
outputs['pve_label_registered_images'].append(
1320+
os.path.join(pth, "rp0%s_affine.nii" % (base)))
1321+
1322+
if self.inputs.bias_corrected_native:
1323+
outputs['bias_corrected_images'].append(
1324+
os.path.join(pth, "m%s.nii" % (base)))
1325+
if self.inputs.bias_corrected_normalized:
1326+
outputs['normalized_bias_corrected_images'].append(
1327+
os.path.join(pth, "wm%s%s.nii" % (dartel_px, base)))
1328+
1329+
if self.inputs.deformation_field[0]:
1330+
outputs['forward_deformation_field'].append(
1331+
os.path.join(pth, "y_%s%s.nii" % (dartel_px, base)))
1332+
if self.inputs.deformation_field[1]:
1333+
outputs['inverse_deformation_field'].append(
1334+
os.path.join(pth, "iy_%s%s.nii" % (dartel_px, base)))
1335+
1336+
if self.inputs.jacobian_determinant and do_dartel:
1337+
outputs['jacobian_determinant_images'].append(
1338+
os.path.join(pth, "jac_wrp1%s.nii" % (base)))
1339+
return outputs
1340+
1341+
def _format_arg(self, opt, spec, val):
1342+
"""Convert input to appropriate format for spm
1343+
"""
1344+
if opt in ['in_files']:
1345+
return scans_for_fnames(val, keep4d=True)
1346+
elif opt in ['spatial_normalization']:
1347+
if val == 'low':
1348+
return {'normlow': []}
1349+
elif opt in ['dartel_template']:
1350+
return np.array([val], dtype=object)
1351+
elif opt in ['deformation_field']:
1352+
return super(VBMSegment, self)._format_arg(opt, spec, [int(val[0]), int(val[1])])
1353+
else:
1354+
return super(VBMSegment, self)._format_arg(opt, spec, val)
1355+
1356+
def _parse_inputs(self):
1357+
if self.inputs.spatial_normalization == 'low':
1358+
einputs = super(VBMSegment, self)._parse_inputs(
1359+
skip=('spatial_normalization', 'dartel_template'))
1360+
einputs[0]['estwrite']['extopts']['dartelwarp'] = {'normlow': 1}
1361+
return einputs
1362+
else:
1363+
return super(VBMSegment, self)._parse_inputs(skip=('spatial_normalization'))

0 commit comments

Comments
 (0)