Skip to content

Commit a0112fb

Browse files
author
erikz
committed
Updates and a few fixes
1 parent 38a8bb7 commit a0112fb

File tree

9 files changed

+263
-187
lines changed

9 files changed

+263
-187
lines changed

examples/connectivity_tutorial_advanced.py

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,8 @@
5353
import nibabel as nb
5454
import os, os.path as op # system functions
5555
import cmp # connectome mapper
56-
57-
"""
58-
We import several voxel, data, and affine grabbing functions from the Camino workflows, as well as
59-
some functions to select the correct files (in our case, aparc+aseg.mgz) from the list outputted by the FreeSurferSource interfaces.
60-
"""
61-
62-
from nipype.workflows.camino.connectivity_mapping import (get_vox_dims, get_data_dims,
63-
get_affine, select_aparc, select_aparc_annot, get_first_image)
56+
from nipype.workflows.camino.connectivity_mapping import select_aparc_annot, get_first_image
57+
from nipype.workflows.mrtrix.diffusion import get_vox_dims_as_tuple
6458

6559
"""
6660
This needs to point to the freesurfer subjects directory (Recon-all must have been run on subj1 from the FSL course data)
@@ -177,6 +171,14 @@
177171

178172
fsl2mrtrix = pe.Node(interface=mrtrix.FSL2MRTrix(),name='fsl2mrtrix')
179173

174+
"""
175+
Distortions induced by eddy currents are corrected prior to fitting the tensors.
176+
The first image is used as a reference for which to warp the others.
177+
"""
178+
179+
eddycorrect = pe.Node(interface=fsl.EddyCorrect(),name='eddycorrect')
180+
eddycorrect.inputs.ref_num = 1
181+
180182
"""
181183
Tensors are fitted to each voxel in the diffusion-weighted image and from these three maps are created:
182184
* Major eigenvector in each voxel
@@ -252,6 +254,8 @@
252254
tracks2prob = pe.Node(interface=mrtrix.Tracks2Prob(),name='tracks2prob')
253255
tracks2prob.inputs.colour = True
254256
tck2trk = pe.Node(interface=mrtrix.MRTrix2TrackVis(),name='tck2trk')
257+
tck2trk.inputs.flipy = True
258+
tck2trk.inputs.flipz = True
255259

256260
"""
257261
Structural segmentation nodes
@@ -283,6 +287,7 @@
283287
inverse.inputs.interp = ('nearestneighbour')
284288
inverse.inputs.apply_xfm = True
285289
inverse_AparcAseg = inverse.clone('inverse_AparcAseg')
290+
inverseROIsToB0 = inverse.clone('inverseROIsToB0')
286291

287292
"""
288293
Parcellation is performed given the aparc+aseg image from Freesurfer.
@@ -403,7 +408,8 @@
403408

404409
mapping.connect([(inputnode, fsl2mrtrix, [("bvecs", "bvec_file"),
405410
("bvals", "bval_file")])])
406-
mapping.connect([(inputnode, dwi2tensor,[("dwi","in_file")])])
411+
mapping.connect([(inputnode, eddycorrect,[("dwi","in_file")])])
412+
mapping.connect([(eddycorrect, dwi2tensor,[("eddy_corrected","in_file")])])
407413
mapping.connect([(fsl2mrtrix, dwi2tensor,[("encoding_file","encoding_file")])])
408414

409415
mapping.connect([(dwi2tensor, tensor2vector,[['tensor','in_file']]),
@@ -417,7 +423,7 @@
417423
fractional anisotropy image, and thresholds it to get the single-fiber voxels.
418424
"""
419425

420-
mapping.connect([(inputnode, MRconvert,[("dwi","in_file")])])
426+
mapping.connect([(eddycorrect, MRconvert,[("eddy_corrected","in_file")])])
421427
mapping.connect([(MRconvert, threshold_b0,[("converted","in_file")])])
422428
mapping.connect([(threshold_b0, median3d,[("out_file","in_file")])])
423429
mapping.connect([(median3d, erode_mask_firstpass,[("out_file","in_file")])])
@@ -430,8 +436,8 @@
430436
Here the thresholded white matter mask is created for seeding the tractography.
431437
"""
432438

433-
mapping.connect([(inputnode, bet,[("dwi","in_file")])])
434-
mapping.connect([(inputnode, gen_WM_mask,[("dwi","in_file")])])
439+
mapping.connect([(eddycorrect, bet,[("eddy_corrected","in_file")])])
440+
mapping.connect([(eddycorrect, gen_WM_mask,[("eddy_corrected","in_file")])])
435441
mapping.connect([(bet, gen_WM_mask,[("mask_file","binary_mask")])])
436442
mapping.connect([(fsl2mrtrix, gen_WM_mask,[("encoding_file","encoding_file")])])
437443
mapping.connect([(gen_WM_mask, threshold_wmmask,[("WMprobabilitymap","in_file")])])
@@ -440,15 +446,15 @@
440446
Next we estimate the fiber response distribution.
441447
"""
442448

443-
mapping.connect([(inputnode, estimateresponse,[("dwi","in_file")])])
449+
mapping.connect([(eddycorrect, estimateresponse,[("eddy_corrected","in_file")])])
444450
mapping.connect([(fsl2mrtrix, estimateresponse,[("encoding_file","encoding_file")])])
445451
mapping.connect([(threshold_FA, estimateresponse,[("out_file","mask_image")])])
446452

447453
"""
448454
Run constrained spherical deconvolution.
449455
"""
450456

451-
mapping.connect([(inputnode, csdeconv,[("dwi","in_file")])])
457+
mapping.connect([(eddycorrect, csdeconv,[("eddy_corrected","in_file")])])
452458
mapping.connect([(gen_WM_mask, csdeconv,[("WMprobabilitymap","mask_image")])])
453459
mapping.connect([(estimateresponse, csdeconv,[("response","response_file")])])
454460
mapping.connect([(fsl2mrtrix, csdeconv,[("encoding_file","encoding_file")])])
@@ -460,42 +466,45 @@
460466
mapping.connect([(threshold_wmmask, probCSDstreamtrack,[("out_file","seed_file")])])
461467
mapping.connect([(csdeconv, probCSDstreamtrack,[("spherical_harmonics_image","in_file")])])
462468
mapping.connect([(probCSDstreamtrack, tracks2prob,[("tracked","in_file")])])
463-
mapping.connect([(inputnode, tracks2prob,[("dwi","template_file")])])
469+
mapping.connect([(eddycorrect, tracks2prob,[("eddy_corrected","template_file")])])
464470

465471
"""
466472
Structural Processing
467473
---------------------
468474
First, we coregister the structural image to the diffusion image and then obtain the inverse of transformation.
469475
"""
470476

471-
mapping.connect([(inputnode, coregister,[('dwi','in_file')])])
477+
mapping.connect([(eddycorrect, coregister,[("eddy_corrected","in_file")])])
472478
mapping.connect([(mri_convert_Brain, coregister,[('out_file','reference')])])
473479
mapping.connect([(coregister, convertxfm,[('out_matrix_file','in_file')])])
474-
mapping.connect([(inputnode, inverse,[('dwi','reference')])])
480+
mapping.connect([(eddycorrect, inverse,[("eddy_corrected","reference")])])
475481
mapping.connect([(convertxfm, inverse,[('out_file','in_matrix_file')])])
476482
mapping.connect([(mri_convert_Brain, inverse,[('out_file','in_file')])])
477483

478484
"""
479485
The b0 image is upsampled to the same dimensions as the parcellated structural image to improve their coregistration.
480486
"""
481487

482-
mapping.connect([(inputnode, resampleb0,[(('dwi', get_first_image), 'in_file')])])
488+
mapping.connect([(eddycorrect, resampleb0,[(('eddy_corrected', get_first_image), 'in_file')])])
483489
mapping.connect([(resampleb0, inverse_AparcAseg,[('out_file','reference')])])
484490
mapping.connect([(convertxfm, inverse_AparcAseg,[('out_file','in_matrix_file')])])
491+
mapping.connect([(eddycorrect, inverseROIsToB0,[(('eddy_corrected', get_first_image), 'reference')])])
492+
mapping.connect([(convertxfm, inverseROIsToB0,[('out_file','in_matrix_file')])])
485493

486494
"""
487495
The parcellation is connected for transformation into diffusion space.
488496
"""
489497

490498
mapping.connect([(inputnode, parcellate,[("subject_id","subject_id")])])
491499
mapping.connect([(parcellate, inverse_AparcAseg,[('roi_file','in_file')])])
500+
mapping.connect([(parcellate, inverseROIsToB0,[('roi_file','in_file')])])
492501

493502
"""
494503
The MRtrix-tracked fibers are converted to TrackVis format (with voxel and data dimensions grabbed from the DWI).
495504
The connectivity matrix is created with the .trk fibers and the coregistered parcellation file.
496505
"""
497506

498-
mapping.connect([(inputnode, tck2trk,[("dwi","image_file")])])
507+
mapping.connect([(eddycorrect, tck2trk,[("eddy_corrected","image_file")])])
499508
mapping.connect([(probCSDstreamtrack, tck2trk,[("tracked","in_file")])])
500509
mapping.connect([(tck2trk, creatematrix,[("out_file","tract_file")])])
501510
mapping.connect([(inputnode, creatematrix,[("subject_id","out_matrix_file")])])
@@ -519,7 +528,8 @@
519528
mapping.connect([(mris_convertLHlabels, giftiLabels,[("converted","in1")])])
520529
mapping.connect([(mris_convertRHlabels, giftiLabels,[("converted","in2")])])
521530

522-
mapping.connect([(inputnode, niftiVolumes,[("dwi","in2")])])
531+
mapping.connect([(eddycorrect, niftiVolumes,[("eddy_corrected","in2")])])
532+
523533
mapping.connect([(mri_convert_Brain, niftiVolumes,[("out_file","in3")])])
524534
mapping.connect([(inverse_AparcAseg, niftiVolumes,[("out_file","in1")])])
525535

nipype/interfaces/cmtk/cmtk.py

Lines changed: 55 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ def cmat(track_file, roi_file, resolution_network_file, matrix_name, matrix_mat_
175175
G.add_node(int(u), d)
176176
# compute a position for the node based on the mean position of the
177177
# ROI in voxel coordinates (segmentation volume )
178-
G.node[int(u)]['dn_position'] = str(tuple(np.mean( np.where(roiData== int(d["dn_correspondence_id"]) ) , axis = 1)))
178+
G.node[int(u)]['dn_position'] = tuple(np.mean( np.where(roiData== int(d["dn_correspondence_id"]) ) , axis = 1))
179179

180180
dis = 0
181181
for i in range(endpoints.shape[0]):
@@ -275,6 +275,10 @@ def cmat(track_file, roi_file, resolution_network_file, matrix_name, matrix_mat_
275275
fibdev_dict['cmatrix'] = fibdev_mlab
276276

277277
path, name, ext = split_filename(matrix_mat_name)
278+
if not ext == '.mat':
279+
ext = '.mat'
280+
matrix_mat_name = matrix_mat_name + ext
281+
278282
print 'Writing matlab matrix as {mat}'.format(mat=matrix_mat_name)
279283
sio.savemat(matrix_mat_name, numfib_dict)
280284

@@ -306,16 +310,12 @@ def save_fibers(oldhdr, oldfib, fname, indices):
306310
""" Stores a new trackvis file fname using only given indices """
307311
import nibabel.trackvis as tv
308312
import cPickle
309-
310313
hdrnew = oldhdr.copy()
311-
312314
outstreams = []
313315
for i in indices:
314316
outstreams.append( oldfib[i] )
315-
316317
n_fib_out = len(outstreams)
317318
hdrnew['n_count'] = n_fib_out
318-
319319
print "Writing final no orphan fibers as %s" % fname
320320
tv.write(fname,outstreams,hdrnew)
321321

@@ -325,10 +325,10 @@ class CreateMatrixInputSpec(TraitedSpec):
325325
tract_file = File(exists=True, mandatory=True, desc='Trackvis tract file')
326326
resolution_network_file = File(exists=True, mandatory=True, desc='Parcellation files from Connectome Mapping Toolkit')
327327
out_matrix_file = File(genfile = True, desc='NetworkX graph describing the connectivity')
328-
out_matrix_mat_file = File(genfile = True, desc='Matlab matrix describing the connectivity')
329-
out_mean_fiber_length_matrix_mat_file = File(genfile = True, desc='Matlab matrix describing the mean fiber lengths between each node.')
330-
out_fiber_length_std_matrix_mat_file = File(genfile = True, desc='Matlab matrix describing the deviation in fiber lengths connecting each node.')
331-
out_endpoint_array_name = File(genfile = True, desc='Name for the generated endpoint arrays')
328+
out_matrix_mat_file = File('cmatrix.mat', usedefault=True, desc='Matlab matrix describing the connectivity')
329+
out_mean_fiber_length_matrix_mat_file = File(genfile=True, desc='Matlab matrix describing the mean fiber lengths between each node.')
330+
out_fiber_length_std_matrix_mat_file = File(genfile=True, desc='Matlab matrix describing the deviation in fiber lengths connecting each node.')
331+
out_endpoint_array_name = File(genfile=True, desc='Name for the generated endpoint arrays')
332332

333333
class CreateMatrixOutputSpec(TraitedSpec):
334334
matrix_file = File(desc='NetworkX graph describing the connectivity')
@@ -349,8 +349,8 @@ class CreateMatrix(BaseInterface):
349349
Example
350350
-------
351351
352-
>>> import nipype.interfaces.cmtk.cmtk as ck
353-
>>> conmap = ck.CreateMatrix()
352+
>>> import nipype.interfaces.cmtk as cmtk
353+
>>> conmap = cmtk.CreateMatrix()
354354
>>> conmap.roi_file = 'fsLUT_aparc+aseg.nii'
355355
>>> conmap.dict_file = 'fsLUT_aparc+aseg.pck'
356356
>>> conmap.tract_file = 'fibers.trk'
@@ -365,17 +365,29 @@ def _run_interface(self, runtime):
365365
path, name, _ = split_filename(self.inputs.out_matrix_file)
366366
matrix_file = op.abspath(name + '.pck')
367367
else:
368-
matrix_file = self._gen_outfilename('pck')
369-
if isdefined(self.inputs.out_matrix_mat_file):
370-
path, name, _ = split_filename(self.inputs.out_matrix_mat_file)
371-
matrix_mat_file = op.abspath(name + '.mat')
368+
matrix_file = self._gen_outfilename('.pck')
369+
370+
matrix_mat_file = op.abspath(self.inputs.out_matrix_mat_file)
371+
path, name, ext = split_filename(matrix_mat_file)
372+
if not ext == '.mat':
373+
ext = '.mat'
374+
matrix_mat_file = matrix_mat_file + ext
375+
376+
if isdefined(self.inputs.out_mean_fiber_length_matrix_mat_file):
377+
mean_fiber_length_matrix_mat_file = op.abspath(self.inputs.out_mean_fiber_length_matrix_mat_file)
372378
else:
373-
matrix_mat_file = self._gen_outfilename('mat')
374-
379+
mean_fiber_length_matrix_name = op.abspath(self._gen_outfilename('_mean_fiber_length'))
380+
381+
if isdefined(self.inputs.out_fiber_length_std_matrix_mat_file):
382+
fiber_length_std_matrix_mat_file = op.abspath(self.inputs.out_fiber_length_std_matrix_mat_file)
383+
else:
384+
fiber_length_std_matrix_name = op.abspath(self._gen_outfilename('_fiber_length_std.mat'))
385+
375386
if not isdefined(self.inputs.out_endpoint_array_name):
376387
_, endpoint_name , _ = split_filename(self.inputs.tract_file)
388+
endpoint_name = op.abspath(endpoint_name)
377389
else:
378-
endpoint_name = self.inputs.out_endpoint_array_name
390+
endpoint_name = op.abspath(self.inputs.out_endpoint_array_name)
379391

380392
if isdefined(self.inputs.dict_file):
381393
cmat(self.inputs.tract_file, self.inputs.roi_file, self.inputs.resolution_network_file,
@@ -390,26 +402,27 @@ def _list_outputs(self):
390402
outputs = self.output_spec().get()
391403
if isdefined(self.inputs.out_matrix_file):
392404
path, name, _ = split_filename(self.inputs.out_matrix_file)
393-
outputs['matrix_file']= op.abspath(name + '.pck')
405+
outputs['matrix_file'] = op.abspath(name + '.pck')
394406
else:
395-
outputs['matrix_file']=op.abspath(self._gen_outfilename('pck'))
396-
if isdefined(self.inputs.out_matrix_mat_file):
397-
path, name, _ = split_filename(self.inputs.out_matrix_mat_file)
398-
outputs['matrix_mat_file']= op.abspath(name + '.mat')
399-
outputs['mean_fiber_length_matrix_mat_file']= op.abspath(name + '_mean_fiber_length.mat')
400-
outputs['fiber_length_std_matrix_mat_file']= op.abspath(name + '_fiber_length_std.mat')
407+
outputs['matrix_file'] = op.abspath(self._gen_outfilename('.pck'))
408+
409+
matrix_mat_file = op.abspath(self.inputs.out_matrix_mat_file)
410+
path, name, ext = split_filename(matrix_mat_file)
411+
if not ext == '.mat':
412+
ext = '.mat'
413+
matrix_mat_file = matrix_mat_file + ext
414+
415+
outputs['matrix_mat_file'] = matrix_mat_file
416+
if isdefined(self.inputs.out_mean_fiber_length_matrix_mat_file):
417+
outputs['mean_fiber_length_matrix_mat_file']= op.abspath(self.inputs.out_mean_fiber_length_matrix_mat_file)
401418
else:
402-
name = op.abspath(self._gen_outfilename('mat'))
403-
outputs['matrix_mat_file'] = name
404-
outputs['mean_fiber_length_matrix_mat_file'] = op.abspath(name + '_mean_fiber_length.mat')
405-
outputs['fiber_length_std_matrix_mat_file'] = op.abspath(name + '_fiber_length_std.mat')
406-
407-
if isdefined(self.inputs.out_matrix_mat_file):
408-
path, name, _ = split_filename(self.inputs.out_matrix_mat_file)
409-
outputs['matrix_mat_file']= op.abspath(name + '.mat')
419+
outputs['mean_fiber_length_matrix_mat_file']=op.abspath(self._gen_outfilename('_mean_fiber_length.mat'))
420+
421+
if isdefined(self.inputs.out_fiber_length_std_matrix_mat_file):
422+
outputs['fiber_length_std_matrix_mat_file']= op.abspath(self.inputs.out_fiber_length_std_matrix_mat_file)
410423
else:
411-
outputs['matrix_mat_file']=op.abspath(self._gen_outfilename('mat'))
412-
424+
outputs['fiber_length_std_matrix_mat_file']= op.abspath(self._gen_outfilename('_fiber_length_std.mat'))
425+
413426
if isdefined(self.inputs.out_endpoint_array_name):
414427
outputs['endpoint_file'] = op.abspath(self.inputs.out_endpoint_array_name + '_endpoints.npy')
415428
outputs['endpoint_file_mm'] = op.abspath(self.inputs.out_endpoint_array_name + '_endpointsmm.npy')
@@ -429,8 +442,11 @@ def _list_outputs(self):
429442
return outputs
430443

431444
def _gen_outfilename(self, ext):
432-
_, name , _ = split_filename(self.inputs.tract_file)
433-
return name + '.' + ext
445+
if isdefined(self.inputs.out_matrix_file):
446+
_, name , _ = split_filename(self.inputs.out_matrix_file)
447+
else:
448+
_, name , _ = split_filename(self.inputs.tract_file)
449+
return name + ext
434450

435451
class ROIGenInputSpec(BaseInterfaceInputSpec):
436452
aparc_aseg_file = File(exists=True, mandatory=True, desc='Freesurfer aparc+aseg file')
@@ -451,8 +467,8 @@ class ROIGen(BaseInterface):
451467
Example
452468
-------
453469
454-
>>> import nipype.interfaces.cmtk.cmtk as ck
455-
>>> rg = ck.ROIGen()
470+
>>> import nipype.interfaces.cmtk as cmtk
471+
>>> rg = cmtk.ROIGen()
456472
>>> rg.inputs.aparc_aseg_file = 'aparc+aseg.nii'
457473
>>> rg.inputs.use_freesurfer_LUT = True
458474
>>> rg.inputs.freesurfer_dir = '/usr/local/freesurfer'

0 commit comments

Comments
 (0)