From 9788a54b27844b244ed74f44c392bb9068c077ad Mon Sep 17 00:00:00 2001 From: danginsburg Date: Thu, 26 Aug 2010 15:42:46 -0400 Subject: [PATCH 01/16] Check in initial work at implementing ODFRecon and HARDIMat --- .../interfaces/diffusion_toolkit/__init__.py | 2 +- .../interfaces/diffusion_toolkit/preproc.py | 128 +++++++++++++++++- 2 files changed, 127 insertions(+), 3 deletions(-) diff --git a/nipype/interfaces/diffusion_toolkit/__init__.py b/nipype/interfaces/diffusion_toolkit/__init__.py index b7af039552..26f33576ec 100644 --- a/nipype/interfaces/diffusion_toolkit/__init__.py +++ b/nipype/interfaces/diffusion_toolkit/__init__.py @@ -1 +1 @@ -from nipype.interfaces.diffusion_toolkit.preproc import DTIRecon \ No newline at end of file +from nipype.interfaces.diffusion_toolkit.preproc import (DTIRecon, HARDIMat, ODFRecon) \ No newline at end of file diff --git a/nipype/interfaces/diffusion_toolkit/preproc.py b/nipype/interfaces/diffusion_toolkit/preproc.py index 4d9eb080f5..bcb8a52240 100644 --- a/nipype/interfaces/diffusion_toolkit/preproc.py +++ b/nipype/interfaces/diffusion_toolkit/preproc.py @@ -10,12 +10,13 @@ """ import re +import os from nipype.utils.filemanip import fname_presuffix __docformat__ = 'restructuredtext' from nipype.interfaces.base import (TraitedSpec, File, traits, CommandLine, CommandLineInputSpec) - +from nipype.utils.misc import isdefined class DTIReconInputSpec(CommandLineInputSpec): dwi = File(desc='Input diffusion volume', argstr='%s',exists=True, mandatory=True,position=1) @@ -102,4 +103,127 @@ def _list_outputs(self): outputs['V2'] = fname_presuffix("", prefix=out_prefix, suffix='_v2.'+ output_type) outputs['V3'] = fname_presuffix("", prefix=out_prefix, suffix='_v3.'+ output_type) - return outputs \ No newline at end of file + return outputs + +class HARDIMatInputSpec(CommandLineInputSpec): + bvecs = File(exists=True, desc = 'b vectors file', argstr='%s', mandatory=True, position=1) + out_file = File(desc = 'output matrix file', argstr='%s', genfile=True, position=2) + order = traits.Int(argsstr='-order %s', desc="""maximum order of spherical harmonics. must be even number. default +is 4""") + odf_file = File(exists=True, argstr='-odf %s', desc="""filename that contains the reconstruction points on a HEMI-sphere. +use the pre-set 181 points by default""") + reference_file = File(exists=True, argstr='-ref %s', desc="""provide a dicom or nifti image as the reference for the program to +figure out the image orientation information. if no such info was +found in the given image header, the next 5 options -info, etc., +will be used if provided. if image orientation info can be found +in the given reference, all other 5 image orientation options will +be IGNORED""") + image_info = File(exists=True, argstr='-info %s', desc="""specify image information file. the image info file is generated +from original dicom image by diff_unpack program and contains image +orientation and other information needed for reconstruction and +tracking. by default will look into the image folder for .info file""") + image_orientation_vectors = traits.List(traits.Float(), minlen=6, maxlen=6, desc="""specify image orientation vectors. if just one argument given, +will treat it as filename and read the orientation vectors from +the file. if 6 arguments are given, will treat them as 6 float +numbers and construct the 1st and 2nd vector and calculate the 3rd +one automatically. +this information will be used to determine image orientation, +as well as to adjust gradient vectors with oblique angle when""", argstr="-iop %f") + oblique_correction = traits.Bool(desc="""when oblique angle(s) applied, some SIEMENS dti protocols do not +adjust gradient accordingly, thus it requires adjustment for correct +diffusion tensor calculation""", argstr="-oc") + +class HARDIMatOutputSpec(TraitedSpec): + out_file = File(exists=True, desc='output matrix file') + + +class HARDIMat(CommandLine): + """Use hardi_mat to calculate a reconstruction matrix from a gradient table + """ + input_spec=HARDIMatInputSpec + output_spec=HARDIMatOutputSpec + + _cmd = 'hardi_mat' + + def _get_outfilename(self): + outfile = self.inputs.out_file + if not isdefined(outfile): + outfile = fname_presuffix(self.inputs.bvecs, + newpath=os.getcwd(), + suffix='_out', + use_ext=False) + return outfile + + def _list_outputs(self): + outputs = self.output_spec().get() + outfile = self._get_outfilename() + outputs['out_file'] = outfile + return outputs + + def _gen_filename(self, name): + if name == 'out_file': + return self._get_outfilename() + return None + + +class ODFReconInputSpec(CommandLineInputSpec): + raw_data = File(desc='Input raw data', argstr='%s',exists=True, mandatory=True,position=1) + n_directions = traits.Int(desc='Number of directions', argstr='%s', mandatory=True, position=2) + n_output_directions = traits.Int(desc='Number of output directions', argstr='%s', mandatory=True, position=3) + out_prefix = traits.Str("odf", desc='Output file prefix', argstr='%s', usedefault=True, position=4) + matrix = File(argstr='-mat %s', exists=True, desc="""use given file as reconstruction matrix. by default the program +will pick matrix file automatically by the given number of +diffusion and output directions""") + n_b0 = traits.Int(argstr='-b0 %s', desc="""number of b0 scans. by default the program gets this information +from the number of directions and number of volume files in +the raw data directory. useful when dealing with incomplete raw +data set or only using part of raw data set to reconstruct""") + output_type = traits.Enum('nii', 'analyze', 'ni1', 'nii.gz', argstr='-ot %s', desc='output file type', usedefault=True) + sharpness = traits.Float(desc="""smooth or sharpen the raw data. factor > 0 is smoothing. +factor < 0 is sharpening. default value is 0 +NOTE: this option applies to DSI study only""", argstr='-s %f') + filter = traits.Bool(desc="""apply a filter (e.g. high pass) to the raw image""", argstr='-f') + subtract_background = traits.Bool(desc="""subtract the background value before reconstruction""", argstr='-bg') + dsi = traits.Bool(desc="""indicates that the data is dsi""", argstr='-dsi') + output_entropy = traits.Bool(desc="""output entropy map""", argstr='-oe') + image_orientation_vectors = traits.List(traits.Float(), minlen=6, maxlen=6, desc="""specify image orientation vectors. if just one argument given, +will treat it as filename and read the orientation vectors from +the file. if 6 arguments are given, will treat them as 6 float +numbers and construct the 1st and 2nd vector and calculate the 3rd +one automatically. +this information will be used to determine image orientation, +as well as to adjust gradient vectors with oblique angle when""", argstr="-iop %f") + oblique_correction = traits.Bool(desc="""when oblique angle(s) applied, some SIEMENS dti protocols do not +adjust gradient accordingly, thus it requires adjustment for correct +diffusion tensor calculation""", argstr="-oc") + + +class ODFReconOutputSpec(TraitedSpec): + B0 = File(exists=True) + DWI = File(exists=True) + MAX = File(exists=True) + ODF = File(exists=True) + OE = File(desc='Output entropy map') + +class ODFRecon(CommandLine): + """Use dti_recon to generate tensors and other maps + """ + + input_spec=ODFReconInputSpec + output_spec=ODFReconOutputSpec + + _cmd = 'odf_recon' + + def _list_outputs(self): + out_prefix = self.inputs.out_prefix + output_type = self.inputs.output_type + + outputs = self.output_spec().get() + outputs['B0'] = fname_presuffix("", prefix=out_prefix, suffix='_b0.'+ output_type) + outputs['DWI'] = fname_presuffix("", prefix=out_prefix, suffix='_dwi.'+ output_type) + outputs['MAX'] = fname_presuffix("", prefix=out_prefix, suffix='_max.'+ output_type) + outputs['ODF'] = fname_presuffix("", prefix=out_prefix, suffix='_odf.'+ output_type) + if isdefined(self.inputs.output_entropy): + outputs['OE'] = fname_presuffix("", prefix=out_prefix, suffix='_oe.'+ output_type) + + return outputs From 0ec50355673e733a3d316dd997172660f7e838e0 Mon Sep 17 00:00:00 2001 From: danginsburg Date: Fri, 27 Aug 2010 16:18:54 -0400 Subject: [PATCH 02/16] Implement ODFTracker() and ODFSplineFilter() - can now run full HARDI path through --- .../interfaces/diffusion_toolkit/__init__.py | 2 +- .../interfaces/diffusion_toolkit/preproc.py | 122 +++++++++++++++++- 2 files changed, 120 insertions(+), 4 deletions(-) diff --git a/nipype/interfaces/diffusion_toolkit/__init__.py b/nipype/interfaces/diffusion_toolkit/__init__.py index 26f33576ec..e8273d5d7e 100644 --- a/nipype/interfaces/diffusion_toolkit/__init__.py +++ b/nipype/interfaces/diffusion_toolkit/__init__.py @@ -1 +1 @@ -from nipype.interfaces.diffusion_toolkit.preproc import (DTIRecon, HARDIMat, ODFRecon) \ No newline at end of file +from nipype.interfaces.diffusion_toolkit.preproc import (DTIRecon, HARDIMat, ODFRecon, ODFTracker, SplineFilter) \ No newline at end of file diff --git a/nipype/interfaces/diffusion_toolkit/preproc.py b/nipype/interfaces/diffusion_toolkit/preproc.py index bcb8a52240..8016d23c21 100644 --- a/nipype/interfaces/diffusion_toolkit/preproc.py +++ b/nipype/interfaces/diffusion_toolkit/preproc.py @@ -203,10 +203,10 @@ class ODFReconOutputSpec(TraitedSpec): DWI = File(exists=True) MAX = File(exists=True) ODF = File(exists=True) - OE = File(desc='Output entropy map') + ENTROPY = File(desc='Output entropy map') class ODFRecon(CommandLine): - """Use dti_recon to generate tensors and other maps + """Use odf_recon to generate tensors and other maps """ input_spec=ODFReconInputSpec @@ -224,6 +224,122 @@ def _list_outputs(self): outputs['MAX'] = fname_presuffix("", prefix=out_prefix, suffix='_max.'+ output_type) outputs['ODF'] = fname_presuffix("", prefix=out_prefix, suffix='_odf.'+ output_type) if isdefined(self.inputs.output_entropy): - outputs['OE'] = fname_presuffix("", prefix=out_prefix, suffix='_oe.'+ output_type) + outputs['ENTROPY'] = fname_presuffix("", prefix=out_prefix, suffix='_entropy.'+ output_type) + + return outputs + +class ODFTrackerInputSpec(CommandLineInputSpec): + recon_data_prefix = traits.Str(desc='recon data prefix', argstr='%s', mandatory=True, position=1) + out_file = File(desc = 'output track file', argstr='%s', genfile=True, position=2) + input_output_type = traits.Enum('nii', 'analyze', 'ni1', 'nii.gz', argstr='-it %s', desc='input and output file type', usedefault=True) + runge_kutta2 = traits.Bool(argstr='-rk2', desc="""use 2nd order runge-kutta method for tracking. +default tracking method is non-interpolate streamline""") + step_length = traits.Float(argstr='-l %f', desc="""set step length, in the unit of minimum voxel size. +default value is 0.1.""") + angle_threshold = traits.Float(argstr='-at %f',desc="""set angle threshold. default value is 35 degree for +default tracking method and 25 for rk2""") + random_seed = traits.Int(argstr='-rseed %s', desc="""use random location in a voxel instead of the center of the voxel +to seed. can also define number of seed per voxel. default is 1""") + invert_x = traits.Bool(argstr='-ix', desc='invert x component of the vector') + invert_y = traits.Bool(argstr='-iy', desc='invert y component of the vector') + invert_z = traits.Bool(argstr='-iz', desc='invert z component of the vector') + swap_xy = traits.Bool(argstr='-sxy', desc='swap x and y vectors while tracking') + swap_yz = traits.Bool(argstr='-syz', desc='swap y and z vectors while tracking') + swap_zx = traits.Bool(argstr='-szx', desc='swap x and z vectors while tracking') + disc = traits.Bool(argstr='-disc', desc='use disc tracking') + mask = traits.List(traits.Str(), minlen=1, maxlen=2, desc=""" [] threshold for mask image. The +first argument is the mask image and the second is the threshold. If the threshold is not provided, then the program will +automatically try to find the threshold""", argstr='-m %s') + mask2 = traits.List(traits.Str(), minlen=1, maxlen=2, desc=""" [] threshold for second mask image. The +first argument is the mask image and the second is the threshold. If the threshold is not provided, then the program will +automatically try to find the threshold""", argstr='-m %s') + limit = traits.Int(argstr='-limit %d', desc="""in some special case, such as heart data, some track may go into +infinite circle and take long time to stop. this option allows +setting a limit for the longest tracking steps (voxels)""") + dsi = traits.Bool(argstr='-dsi', desc=""" specify the input odf data is dsi. because dsi recon uses fixed +pre-calculated matrix, some special orientation patch needs to +be applied to keep dti/dsi/q-ball consistent.""") + image_orientation_vectors = traits.List(traits.Float(), minlen=6, maxlen=6, desc="""specify image orientation vectors. if just one argument given, +will treat it as filename and read the orientation vectors from +the file. if 6 arguments are given, will treat them as 6 float +numbers and construct the 1st and 2nd vector and calculate the 3rd +one automatically. +this information will be used to determine image orientation, +as well as to adjust gradient vectors with oblique angle when""", argstr="-iop %f") + slice_order = traits.Int(argstr='-sorder %d', desc='set the slice order. 1 means normal, -1 means reversed. default value is 1') + voxel_order = traits.Enum('RAS', 'RPS', 'RAI', 'RPI', 'LAI', 'LAS', 'LPS', 'LPI', argstr='-vorder %s', desc="""specify the voxel order in RL/AP/IS (human brain) reference. must be +3 letters with no space in between. +for example, RAS means the voxel row is from L->R, the column +is from P->A and the slice order is from I->S. +by default voxel order is determined by the image orientation +(but NOT guaranteed to be correct because of various standards). +for example, siemens axial image is LPS, coronal image is LIP and +sagittal image is PIL. +this information also is NOT needed for tracking but will be saved +in the track file and is essential for track display to map onto +the right coordinates""") + +class ODFTrackerOutputSpec(TraitedSpec): + out_file = File(exists=True, desc='output track file') + +class ODFTracker(CommandLine): + """Use odf_tracker to generate track file + """ + + input_spec=ODFTrackerInputSpec + output_spec=ODFTrackerOutputSpec + + _cmd = 'odf_tracker' + + def _get_outfilename(self): + outfile = self.inputs.out_file + if not isdefined(outfile): + outfile = fname_presuffix("", prefix=self.inputs.recon_data_prefix, suffix='.trk') + return outfile + + def _list_outputs(self): + outputs = self.output_spec().get() + outfile = self._get_outfilename() + outputs['out_file'] = outfile + return outputs + + def _gen_filename(self, name): + if name == 'out_file': + return self._get_outfilename() + return None + +class SplineFilterInputSpec(CommandLineInputSpec): + in_file = File(exists=True, argstr='%s', mandatory=True, desc='Input track file',position=1) + step_length = traits.Float(argstr='%f', mandatory=True, desc='Step length', position=2) + out_file = File(argstr='%s', genfile=True, desc = 'output track file', position=3) + +class SplineFilterOutputSpec(CommandLineInputSpec): + out_file = File(exists=True, desc='output track file') + +class SplineFilter(CommandLine): + """Use spline_filter to clean up original track file + """ + + input_spec=SplineFilterInputSpec + output_spec=SplineFilterOutputSpec + + _cmd = 'spline_filter' + + def _get_outfilename(self): + outfile = self.inputs.out_file + if not isdefined(outfile): + outfile = fname_presuffix("", prefix=self.inputs.in_file, suffix='_filtered.trk') + return outfile + def _list_outputs(self): + outputs = self.output_spec().get() + outfile = self._get_outfilename() + outputs['out_file'] = outfile return outputs + + def _gen_filename(self, name): + if name == 'out_file': + return self._get_outfilename() + return None + + \ No newline at end of file From cdbf67ab90fabb2b1e0d325917d6a9f9dd42d34a Mon Sep 17 00:00:00 2001 From: Chris Filo Gorgolewski Date: Sat, 28 Aug 2010 17:48:51 -0400 Subject: [PATCH 03/16] Added DTI tracker and spline filter --- .../interfaces/diffusion_toolkit/preproc.py | 113 +++++++++++++++--- 1 file changed, 98 insertions(+), 15 deletions(-) diff --git a/nipype/interfaces/diffusion_toolkit/preproc.py b/nipype/interfaces/diffusion_toolkit/preproc.py index 4d9eb080f5..3c36760e72 100644 --- a/nipype/interfaces/diffusion_toolkit/preproc.py +++ b/nipype/interfaces/diffusion_toolkit/preproc.py @@ -10,7 +10,9 @@ """ import re -from nipype.utils.filemanip import fname_presuffix +from nipype.utils.filemanip import fname_presuffix, split_filename, copyfile +import os +from nipype.utils.misc import isdefined __docformat__ = 'restructuredtext' from nipype.interfaces.base import (TraitedSpec, File, traits, CommandLine, @@ -78,7 +80,6 @@ def _create_gradient_matrix(self, bvecs_file, bvals_file): bvecs_z = [val for val in re.split('\s+', bvecs_f.readline().strip())] bvecs_f.close() gradient_matrix_f = open(self._gradient_matrix_file, 'w') - print len(bvals), len(bvecs_x), len(bvecs_y), len(bvecs_z) for i in range(len(bvals)): gradient_matrix_f.write("%s, %s, %s, %s\n"%(bvecs_x[i], bvecs_y[i], bvecs_z[i], bvals[i])) gradient_matrix_f.close() @@ -89,17 +90,99 @@ def _list_outputs(self): output_type = self.inputs.output_type outputs = self.output_spec().get() - outputs['ADC'] = fname_presuffix("", prefix=out_prefix, suffix='_adc.'+ output_type) - outputs['B0'] = fname_presuffix("", prefix=out_prefix, suffix='_b0.'+ output_type) - outputs['L1'] = fname_presuffix("", prefix=out_prefix, suffix='_e1.'+ output_type) - outputs['L2'] = fname_presuffix("", prefix=out_prefix, suffix='_e2.'+ output_type) - outputs['L3'] = fname_presuffix("", prefix=out_prefix, suffix='_e3.'+ output_type) - outputs['exp'] = fname_presuffix("", prefix=out_prefix, suffix='_exp.'+ output_type) - outputs['FA'] = fname_presuffix("", prefix=out_prefix, suffix='_fa.'+ output_type) - outputs['FA_color'] = fname_presuffix("", prefix=out_prefix, suffix='_fa_color.'+ output_type) - outputs['tensor'] = fname_presuffix("", prefix=out_prefix, suffix='_tensor.'+ output_type) - outputs['V1'] = fname_presuffix("", prefix=out_prefix, suffix='_v1.'+ output_type) - outputs['V2'] = fname_presuffix("", prefix=out_prefix, suffix='_v2.'+ output_type) - outputs['V3'] = fname_presuffix("", prefix=out_prefix, suffix='_v3.'+ output_type) + outputs['ADC'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_adc.'+ output_type)) + outputs['B0'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_b0.'+ output_type)) + outputs['L1'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_e1.'+ output_type)) + outputs['L2'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_e2.'+ output_type)) + outputs['L3'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_e3.'+ output_type)) + outputs['exp'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_exp.'+ output_type)) + outputs['FA'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_fa.'+ output_type)) + outputs['FA_color'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_fa_color.'+ output_type)) + outputs['tensor'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_tensor.'+ output_type)) + outputs['V1'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_v1.'+ output_type)) + outputs['V2'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_v2.'+ output_type)) + outputs['V3'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_v3.'+ output_type)) - return outputs \ No newline at end of file + return outputs + +class DTITrackerInputSpec(CommandLineInputSpec): + tensor_file = File(exists=True, desc="reconstructed tensor file" ) + input_type = traits.Enum('nii', 'analyze', 'ni1', 'nii.gz', desc="""input and output file type. accepted values are: +analyze -> analyze format 7.5 +ni1 -> nifti format saved in seperate .hdr and .img file +nii -> nifti format with one .nii file +nii.gz -> nifti format with compression +default type is 'nii'""", argstr = "-it %s") + tracking_method = traits.Enum('fact', 'rk2', 'tl', 'sl', desc="""fact -> use FACT method for tracking. this is the default method. +rk2 -> use 2nd order runge-kutta method for tracking. +tl -> use tensorline method for tracking. +sl -> use interpolated streamline method with fixed step-length""", argstr="-%s") + step_length = traits.Float(desc="""set step length, in the unit of minimum voxel size. +default value is 0.5 for interpolated streamline method +and 0.1 for other methods""", argstr="-l %f") + angle_threshold = traits.Float(desc="set angle threshold. default value is 35 degree", argstr="-at %f") + angle_threshold_weight = traits.Float(desc="set angle threshold weighting factor. weighting will be be applied \ +on top of the angle_threshold", argstr = "-atw %f") + random_seed = traits.Int(desc = "use random location in a voxel instead of the center of the voxel \ + to seed. can also define number of seed per voxel. default is 1", argstr="-rseed") + invert_x = traits.Bool(desc="invert x component of the vector", argstr = "-ix") + invert_y = traits.Bool(desc="invert y component of the vector", argstr = "-iy") + invert_z = traits.Bool(desc="invert z component of the vector", argstr = "-iz") + swap_xy = traits.Bool(desc="swap x & y vectors while tracking", argstr = "-sxy") + swap_yz = traits.Bool(desc="swap y & z vectors while tracking", argstr = "-syz") + swap_xz = traits.Bool(desc="swap x & z vectors while tracking", argstr = "-sxz") + mask1_file = File(desc="first mask image", mandatory=True, argstr="-m %s", position=2) + mask1_threshold = traits.Float(desc="threshold value for the first mask image, if not given, the program will \ +try automatically find the threshold", position=3) + mask2_file = File(desc="second mask image", argstr="-m2 %s", position=4) + mask2_threshold = traits.Float(desc="threshold value for the second mask image, if not given, the program will \ +try automatically find the threshold", position=5) + input_data_prefix = traits.Str("dti", desc="for internal naming use only", position=0, argstr="%s", usedefault=True) + output_file = File("tracks.trk", "file containing tracks", argstr="%s", position=1, usedefault=True) + output_mask = File(desc="output a binary mask file in analyze format", argstr="-om %s") + primary_vector = traits.Enum('v2', 'v3', desc = "which vector to use for fibre tracking: v2 or v3. If not set use v1", argstr="-%s") + +class DTITrackerOutputSpec(TraitedSpec): + track_file = File(exists=True) + mask_file = File(exists=True) + +class DTITracker(CommandLine): + input_spec=DTITrackerInputSpec + output_spec=DTITrackerOutputSpec + + _cmd = 'dti_tracker' + + def _run_interface(self, runtime): + _, _, ext = split_filename(self.inputs.tensor_file) + copyfile(self.inputs.tensor_file, os.path.abspath(self.inputs.input_data_prefix + "_tensor" + ext), copy=False) + + return super(DTITracker, self)._run_interface(runtime) + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['track_file'] = os.path.abspath(self.inputs.output_file) + if isdefined(self.inputs.output_mask) and self.inputs.output_mask: + outputs['mask_file'] = os.path.abspath(self.inputs.output_mask) + + return outputs + +class SplineFilterInputSpec(CommandLineInputSpec): + track_file = File(exists=True, desc="file containing tracks to be filtered", position=0, argstr="%s", mandatory=True) + step_length = traits.Float(desc="in the unit of minimum voxel size", position=1, argstr="%f", mandatory=True) + output_file = File("spline_tracks.trk", desc="target file for smoothed tracks", position=2, argstr="%s", usedefault=True) + +class SplineFilterOutputSpec(TraitedSpec): + smoothed_track_file = File(exists=True) + +class SplineFilter(CommandLine): + input_spec=SplineFilterInputSpec + output_spec=SplineFilterOutputSpec + + _cmd = "spline_filter" + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['smoothed_track_file'] = os.path.abspath(self.inputs.output_file) + return outputs + + \ No newline at end of file From 1f9e9beee32eb2fe175c799210672414d324c1fd Mon Sep 17 00:00:00 2001 From: Chris Filo Gorgolewski Date: Sat, 28 Aug 2010 17:49:17 -0400 Subject: [PATCH 04/16] updated import to expose new classes --- nipype/interfaces/diffusion_toolkit/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nipype/interfaces/diffusion_toolkit/__init__.py b/nipype/interfaces/diffusion_toolkit/__init__.py index b7af039552..54ff10b04a 100644 --- a/nipype/interfaces/diffusion_toolkit/__init__.py +++ b/nipype/interfaces/diffusion_toolkit/__init__.py @@ -1 +1 @@ -from nipype.interfaces.diffusion_toolkit.preproc import DTIRecon \ No newline at end of file +from nipype.interfaces.diffusion_toolkit.preproc import DTIRecon, DTITracker, SplineFilter \ No newline at end of file From 9f637d6eba20bcd084d4ad4604236a3204018c79 Mon Sep 17 00:00:00 2001 From: Chris Filo Gorgolewski Date: Sat, 28 Aug 2010 17:49:41 -0400 Subject: [PATCH 05/16] updated tutorial to use DTK tracker and spline filter --- examples/diffusion_toolkit_tutorial.py | 79 ++++---------------------- 1 file changed, 12 insertions(+), 67 deletions(-) diff --git a/examples/diffusion_toolkit_tutorial.py b/examples/diffusion_toolkit_tutorial.py index fa3adfa935..4eef186ba7 100644 --- a/examples/diffusion_toolkit_tutorial.py +++ b/examples/diffusion_toolkit_tutorial.py @@ -69,15 +69,7 @@ info = dict(dwi=[['subject_id', 'data']], bvecs=[['subject_id','bvecs']], - bvals=[['subject_id','bvals']], - seed_file = [['subject_id','MASK_average_thal_right']], - target_masks = [['subject_id',['MASK_average_M1_right', - 'MASK_average_S1_right', - 'MASK_average_occipital_right', - 'MASK_average_pfc_right', - 'MASK_average_pmc_right', - 'MASK_average_ppc_right', - 'MASK_average_temporal_right']]]) + bvals=[['subject_id','bvals']]) infosource = pe.Node(interface=util.IdentityInterface(fields=['subject_id']), name="infosource") @@ -111,9 +103,7 @@ # http://www.fmrib.ox.ac.uk/fslcourse/fsl_course_data2.tar.gz datasource.inputs.base_directory = os.path.abspath('fsl_course_data/fdt/') -datasource.inputs.field_template = dict(dwi='%s/%s.nii.gz', - seed_file="%s.bedpostX/%s.nii.gz", - target_masks="%s.bedpostX/%s.nii.gz") +datasource.inputs.field_template = dict(dwi='%s/%s.nii.gz') datasource.inputs.template_args = info @@ -173,56 +163,19 @@ """ tractography = pe.Workflow(name='tractography') -tractography.base_dir = os.path.abspath('diffusion_toolkit_tutorial') - -""" -estimate the diffusion parameters: phi, theta, and so on -""" - -bedpostx = pe.Node(interface=fsl.BEDPOSTX(),name='bedpostx') -bedpostx.inputs.fibres = 1 - -bedpostx_2f = pe.Node(interface=fsl.BEDPOSTX(),name='bedpostx_2f') -bedpostx_2f.inputs.fibres = 2 - - -flirt = pe.Node(interface=fsl.FLIRT(), name='flirt') -flirt.inputs.reference = fsl.Info.standard_image('MNI152_T1_2mm_brain.nii.gz') -flirt.inputs.dof = 12 - -""" -perform probabilistic tracktography -""" - -probtrackx = pe.Node(interface=fsl.ProbTrackX(),name='probtrackx') -probtrackx.inputs.mode='seedmask' -probtrackx.inputs.loop_check=True -probtrackx.inputs.c_thresh = 0.2 -probtrackx.inputs.n_steps=2000 -probtrackx.inputs.step_length=0.5 -probtrackx.inputs.n_samples=5000 -probtrackx.inputs.force_dir=True -probtrackx.inputs.opd=True -probtrackx.inputs.os2t=True - - -""" -perform hard segmentation on the output of probtrackx -""" - -findthebiggest = pe.Node(interface=fsl.FindTheBiggest(),name='findthebiggest') +tractography.base_dir = os.path.abspath('dtk_tutorial') +dtk_trackt = pe.Node(interface=dtk.DTITracker(), name="dtk_trackt") +smooth_trk = pe.Node(interface=dtk.SplineFilter(), name="smooth_trk") +smooth_trk.inputs.step_length = 0.5 """ connect all the nodes for this workflow """ tractography.connect([ - (bedpostx,probtrackx,[('bpx_out_directory','bpx_directory')]), - (bedpostx,probtrackx,[('bpx_out_directory','out_dir')]), - (probtrackx,findthebiggest,[('targets','in_files')]), - (flirt, probtrackx, [('out_matrix_file','xfm')]) - ]) + (dtk_trackt, smooth_trk, [('track_file', 'track_file')]) + ]) """ @@ -242,24 +195,16 @@ def getstripdir(subject_id): """ dwiproc = pe.Workflow(name="dwiproc") -dwiproc.base_dir = os.path.abspath('dti_tutorial') +dwiproc.base_dir = os.path.abspath('dtk_tutorial') dwiproc.connect([ (infosource,datasource,[('subject_id', 'subject_id')]), (datasource,computeTensor,[('dwi','fslroi.in_file'), ('bvals','dtifit.bvals'), ('bvecs','dtifit.bvecs'), ('dwi','eddycorrect.in_file')]), - (datasource,tractography,[('bvals','bedpostx.bvals'), - ('bvecs','bedpostx.bvecs'), - ('seed_file','probtrackx.seed_file'), - ('target_masks','probtrackx.target_masks')]), - (computeTensor,tractography,[('eddycorrect.eddy_corrected','bedpostx.dwi'), - ('bet.mask_file','bedpostx.mask'), - ('bet.mask_file','probtrackx.mask'), - ('fslroi.roi_file','flirt.in_file')]), - (infosource, datasink,[('subject_id','container'), - (('subject_id', getstripdir),'strip_dir')]), - (tractography,datasink,[('findthebiggest.out_file','fbiggest.@biggestsegmentation')]) + (computeTensor,tractography,[('bet.mask_file','dtk_trackt.mask1_file'), + ('dtifit.tensor','dtk_trackt.tensor_file') + ]) ]) dwiproc.run() From c31937fa09a1eef406dc0786d79e8d5c0798e85e Mon Sep 17 00:00:00 2001 From: Chris Filo Gorgolewski Date: Wed, 1 Sep 2010 13:56:43 -0400 Subject: [PATCH 06/16] refactored ODF interfaces --- .../interfaces/diffusion_toolkit/preproc.py | 124 ++++++++---------- 1 file changed, 56 insertions(+), 68 deletions(-) diff --git a/nipype/interfaces/diffusion_toolkit/preproc.py b/nipype/interfaces/diffusion_toolkit/preproc.py index c35ffc5f2a..4f67baa96a 100644 --- a/nipype/interfaces/diffusion_toolkit/preproc.py +++ b/nipype/interfaces/diffusion_toolkit/preproc.py @@ -17,7 +17,20 @@ from nipype.interfaces.base import (TraitedSpec, File, traits, CommandLine, CommandLineInputSpec) -from nipype.utils.misc import isdefined + +def _create_gradient_matrix(bvecs_file, bvals_file): + _gradient_matrix_file = 'gradient_matrix.txt' + bvals = [val for val in re.split('\s+', open(bvals_file).readline().strip())] + bvecs_f = open(bvecs_file) + bvecs_x = [val for val in re.split('\s+', bvecs_f.readline().strip())] + bvecs_y = [val for val in re.split('\s+', bvecs_f.readline().strip())] + bvecs_z = [val for val in re.split('\s+', bvecs_f.readline().strip())] + bvecs_f.close() + gradient_matrix_f = open(_gradient_matrix_file, 'w') + for i in range(len(bvals)): + gradient_matrix_f.write("%s, %s, %s, %s\n"%(bvecs_x[i], bvecs_y[i], bvecs_z[i], bvals[i])) + gradient_matrix_f.close() + return _gradient_matrix_file class DTIReconInputSpec(CommandLineInputSpec): dwi = File(desc='Input diffusion volume', argstr='%s',exists=True, mandatory=True,position=1) @@ -63,27 +76,13 @@ class DTIRecon(CommandLine): input_spec=DTIReconInputSpec output_spec=DTIReconOutputSpec - _gradient_matrix_file = 'gradient_matrix.txt' _cmd = 'dti_recon' def _format_arg(self, name, spec, value): if name == "bvecs": - new_val = self._create_gradient_matrix(self.inputs.bvecs, self.inputs.bvals) + new_val = _create_gradient_matrix(self.inputs.bvecs, self.inputs.bvals) return super(DTIRecon, self)._format_arg("bvecs", spec, new_val) return super(DTIRecon, self)._format_arg(name, spec, value) - - def _create_gradient_matrix(self, bvecs_file, bvals_file): - bvals = [val for val in re.split('\s+', open(bvals_file).readline().strip())] - bvecs_f = open(bvecs_file) - bvecs_x = [val for val in re.split('\s+', bvecs_f.readline().strip())] - bvecs_y = [val for val in re.split('\s+', bvecs_f.readline().strip())] - bvecs_z = [val for val in re.split('\s+', bvecs_f.readline().strip())] - bvecs_f.close() - gradient_matrix_f = open(self._gradient_matrix_file, 'w') - for i in range(len(bvals)): - gradient_matrix_f.write("%s, %s, %s, %s\n"%(bvecs_x[i], bvecs_y[i], bvecs_z[i], bvals[i])) - gradient_matrix_f.close() - return self._gradient_matrix_file def _list_outputs(self): out_prefix = self.inputs.out_prefix @@ -186,8 +185,10 @@ def _list_outputs(self): return outputs class HARDIMatInputSpec(CommandLineInputSpec): - bvecs = File(exists=True, desc = 'b vectors file', argstr='%s', mandatory=True, position=1) - out_file = File(desc = 'output matrix file', argstr='%s', genfile=True, position=2) + bvecs = File(exists=True, desc = 'b vectors file', + argstr='%s', position=1, mandatory=True) + bvals = File(exists=True,desc = 'b values file', mandatory=True) + out_file = File("recon_mat.dat", desc = 'output matrix file', argstr='%s', usedefault=True, position=2) order = traits.Int(argsstr='-order %s', desc="""maximum order of spherical harmonics. must be even number. default is 4""") odf_file = File(exists=True, argstr='-odf %s', desc="""filename that contains the reconstruction points on a HEMI-sphere. @@ -225,39 +226,27 @@ class HARDIMat(CommandLine): _cmd = 'hardi_mat' - def _get_outfilename(self): - outfile = self.inputs.out_file - if not isdefined(outfile): - outfile = fname_presuffix(self.inputs.bvecs, - newpath=os.getcwd(), - suffix='_out', - use_ext=False) - return outfile - + def _format_arg(self, name, spec, value): + if name == "bvecs": + new_val = _create_gradient_matrix(self.inputs.bvecs, self.inputs.bvals) + return super(HARDIMat, self)._format_arg("bvecs", spec, new_val) + return super(HARDIMat, self)._format_arg(name, spec, value) + def _list_outputs(self): outputs = self.output_spec().get() - outfile = self._get_outfilename() - outputs['out_file'] = outfile + outputs['out_file'] = os.path.abspath(self.inputs.out_file) return outputs - def _gen_filename(self, name): - if name == 'out_file': - return self._get_outfilename() - return None - - class ODFReconInputSpec(CommandLineInputSpec): - raw_data = File(desc='Input raw data', argstr='%s',exists=True, mandatory=True,position=1) + dwi = File(desc='Input raw data', argstr='%s',exists=True, mandatory=True,position=1) n_directions = traits.Int(desc='Number of directions', argstr='%s', mandatory=True, position=2) n_output_directions = traits.Int(desc='Number of output directions', argstr='%s', mandatory=True, position=3) out_prefix = traits.Str("odf", desc='Output file prefix', argstr='%s', usedefault=True, position=4) - matrix = File(argstr='-mat %s', exists=True, desc="""use given file as reconstruction matrix. by default the program -will pick matrix file automatically by the given number of -diffusion and output directions""") + matrix = File(argstr='-mat %s', exists=True, desc="""use given file as reconstruction matrix.""", mandatory=True) n_b0 = traits.Int(argstr='-b0 %s', desc="""number of b0 scans. by default the program gets this information -from the number of directions and number of volume files in -the raw data directory. useful when dealing with incomplete raw -data set or only using part of raw data set to reconstruct""") +from the number of directions and number of volumes in +the raw data. useful when dealing with incomplete raw +data set or only using part of raw data set to reconstruct""", mandatory=True) output_type = traits.Enum('nii', 'analyze', 'ni1', 'nii.gz', argstr='-ot %s', desc='output file type', usedefault=True) sharpness = traits.Float(desc="""smooth or sharpen the raw data. factor > 0 is smoothing. factor < 0 is sharpening. default value is 0 @@ -299,18 +288,20 @@ def _list_outputs(self): output_type = self.inputs.output_type outputs = self.output_spec().get() - outputs['B0'] = fname_presuffix("", prefix=out_prefix, suffix='_b0.'+ output_type) - outputs['DWI'] = fname_presuffix("", prefix=out_prefix, suffix='_dwi.'+ output_type) - outputs['MAX'] = fname_presuffix("", prefix=out_prefix, suffix='_max.'+ output_type) - outputs['ODF'] = fname_presuffix("", prefix=out_prefix, suffix='_odf.'+ output_type) + outputs['B0'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_b0.'+ output_type)) + outputs['DWI'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_dwi.'+ output_type)) + outputs['MAX'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_max.'+ output_type)) + outputs['ODF'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_odf.'+ output_type)) if isdefined(self.inputs.output_entropy): - outputs['ENTROPY'] = fname_presuffix("", prefix=out_prefix, suffix='_entropy.'+ output_type) + outputs['ENTROPY'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_entropy.'+ output_type)) return outputs class ODFTrackerInputSpec(CommandLineInputSpec): - recon_data_prefix = traits.Str(desc='recon data prefix', argstr='%s', mandatory=True, position=1) - out_file = File(desc = 'output track file', argstr='%s', genfile=True, position=2) + MAX = File(exists=True, mandatory=True) + ODF = File(exists=True, mandatory=True) + input_data_prefix = traits.Str("odf", desc='recon data prefix', argstr='%s', usedefault=True, position=0) + out_file = File("tracks.trk", desc = 'output track file', argstr='%s', usedefault=True, position=1) input_output_type = traits.Enum('nii', 'analyze', 'ni1', 'nii.gz', argstr='-it %s', desc='input and output file type', usedefault=True) runge_kutta2 = traits.Bool(argstr='-rk2', desc="""use 2nd order runge-kutta method for tracking. default tracking method is non-interpolate streamline""") @@ -327,12 +318,12 @@ class ODFTrackerInputSpec(CommandLineInputSpec): swap_yz = traits.Bool(argstr='-syz', desc='swap y and z vectors while tracking') swap_zx = traits.Bool(argstr='-szx', desc='swap x and z vectors while tracking') disc = traits.Bool(argstr='-disc', desc='use disc tracking') - mask = traits.List(traits.Str(), minlen=1, maxlen=2, desc=""" [] threshold for mask image. The -first argument is the mask image and the second is the threshold. If the threshold is not provided, then the program will -automatically try to find the threshold""", argstr='-m %s') - mask2 = traits.List(traits.Str(), minlen=1, maxlen=2, desc=""" [] threshold for second mask image. The -first argument is the mask image and the second is the threshold. If the threshold is not provided, then the program will -automatically try to find the threshold""", argstr='-m %s') + mask1_file = File(desc="first mask image", mandatory=True, argstr="-m %s", position=2) + mask1_threshold = traits.Float(desc="threshold value for the first mask image, if not given, the program will \ +try automatically find the threshold", position=3) + mask2_file = File(desc="second mask image", argstr="-m2 %s", position=4) + mask2_threshold = traits.Float(desc="threshold value for the second mask image, if not given, the program will \ +try automatically find the threshold", position=5) limit = traits.Int(argstr='-limit %d', desc="""in some special case, such as heart data, some track may go into infinite circle and take long time to stop. this option allows setting a limit for the longest tracking steps (voxels)""") @@ -360,7 +351,7 @@ class ODFTrackerInputSpec(CommandLineInputSpec): the right coordinates""") class ODFTrackerOutputSpec(TraitedSpec): - out_file = File(exists=True, desc='output track file') + track_file = File(exists=True, desc='output track file') class ODFTracker(CommandLine): """Use odf_tracker to generate track file @@ -371,21 +362,18 @@ class ODFTracker(CommandLine): _cmd = 'odf_tracker' - def _get_outfilename(self): - outfile = self.inputs.out_file - if not isdefined(outfile): - outfile = fname_presuffix("", prefix=self.inputs.recon_data_prefix, suffix='.trk') - return outfile + def _run_interface(self, runtime): + _, _, ext = split_filename(self.inputs.MAX) + copyfile(self.inputs.MAX, os.path.abspath(self.inputs.input_data_prefix + "_max" + ext), copy=False) + + _, _, ext = split_filename(self.inputs.ODF) + copyfile(self.inputs.ODF, os.path.abspath(self.inputs.input_data_prefix + "_odf" + ext), copy=False) + + return super(ODFTracker, self)._run_interface(runtime) def _list_outputs(self): outputs = self.output_spec().get() - outfile = self._get_outfilename() - outputs['out_file'] = outfile + outputs['track_file'] = os.path.abspath(self.inputs.out_file) return outputs - - def _gen_filename(self, name): - if name == 'out_file': - return self._get_outfilename() - return None \ No newline at end of file From 5761c239ca7dc9a4837a00ffa03911577a33a35d Mon Sep 17 00:00:00 2001 From: Chris Filo Gorgolewski Date: Wed, 1 Sep 2010 13:57:42 -0400 Subject: [PATCH 07/16] ODF tutorial --- examples/odf_tutorial.py | 223 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 examples/odf_tutorial.py diff --git a/examples/odf_tutorial.py b/examples/odf_tutorial.py new file mode 100644 index 0000000000..ed3f0349e2 --- /dev/null +++ b/examples/odf_tutorial.py @@ -0,0 +1,223 @@ + +""" +A pipeline example that uses several interfaces to +perform analysis on diffusion weighted images using +FSL FDT tools. + +This tutorial is based on the 2010 FSL course and uses +data freely available at the FSL website at: +http://www.fmrib.ox.ac.uk/fslcourse/fsl_course_data2.tar.gz + +More details can be found at http://www.fmrib.ox.ac.uk/fslcourse/lectures/practicals/fdt/index.htm +""" + + +""" +Tell python where to find the appropriate functions. +""" + +import nipype.interfaces.io as nio # Data i/o +import nipype.interfaces.fsl as fsl # fsl +import nipype.interfaces.diffusion_toolkit as dtk +import nipype.interfaces.utility as util # utility +import nipype.pipeline.engine as pe # pypeline engine +import os # system functions + +""" +Confirm package dependencies are installed. (This is only for the +tutorial, rarely would you put this in your own code.) +""" + +from nipype.utils.misc import package_check + +package_check('numpy', '1.3', 'tutorial1') +package_check('scipy', '0.7', 'tutorial1') +package_check('networkx', '1.0', 'tutorial1') +package_check('IPython', '0.10', 'tutorial1') + + +""" +Setting up workflows +-------------------- +This is a generic workflow for DTI data analysis using the FSL +""" + +""" +Data specific components +------------------------ + +The nipype tutorial contains data for two subjects. Subject data +is in two subdirectories, ``dwis1`` and ``dwis2``. Each subject directory +contains each of the following files: bvec, bval, diffusion weighted data, a set of target masks, +a seed file, and a transformation matrix. + +Below we set some variables to inform the ``datasource`` about the +layout of our data. We specify the location of the data, the subject +sub-directories and a dictionary that maps each run to a mnemonic (or +field) for the run type (``dwi`` or ``bvals``). These fields become +the output fields of the ``datasource`` node in the pipeline. + +Specify the subject directories +""" + +subject_list = ['subj1'] + + +""" +Map field names to individual subject runs +""" + +info = dict(dwi=[['subject_id', 'data']], + bvecs=[['subject_id','bvecs']], + bvals=[['subject_id','bvals']]) + +infosource = pe.Node(interface=util.IdentityInterface(fields=['subject_id']), + name="infosource") + +"""Here we set up iteration over all the subjects. The following line +is a particular example of the flexibility of the system. The +``datasource`` attribute ``iterables`` tells the pipeline engine that +it should repeat the analysis on each of the items in the +``subject_list``. In the current example, the entire first level +preprocessing and estimation will be repeated for each subject +contained in subject_list. +""" + +infosource.iterables = ('subject_id', subject_list) + +""" +Now we create a :class:`nipype.interfaces.io.DataGrabber` object and +fill in the information from above about the layout of our data. The +:class:`nipype.pipeline.engine.Node` module wraps the interface object +and provides additional housekeeping and pipeline specific +functionality. +""" + +datasource = pe.Node(interface=nio.DataGrabber(infields=['subject_id'], + outfields=info.keys()), + name = 'datasource') + +datasource.inputs.template = "%s/%s" + +# This needs to point to the fdt folder you can find after extracting +# http://www.fmrib.ox.ac.uk/fslcourse/fsl_course_data2.tar.gz +datasource.inputs.base_directory = os.path.abspath('fsl_course_data/fdt/') + +datasource.inputs.field_template = dict(dwi='%s/%s.nii.gz') +datasource.inputs.template_args = info + + +""" +Setup for Diffusion Tensor Computation +-------------------------------------- +Here we will create a generic workflow for DTI computation +""" + +computeTensor = pe.Workflow(name='computeTensor') + +""" +extract the volume with b=0 (nodif_brain) +""" + +fslroi = pe.Node(interface=fsl.ExtractROI(),name='fslroi') +fslroi.inputs.t_min=0 +fslroi.inputs.t_size=1 + +""" +create a brain mask from the nodif_brain +""" + +bet = pe.Node(interface=fsl.BET(),name='bet') +bet.inputs.mask=True +bet.inputs.frac=0.34 + +""" +correct the diffusion weighted images for eddy_currents +""" + +eddycorrect = pe.Node(interface=fsl.EddyCorrect(),name='eddycorrect') +eddycorrect.inputs.ref_num=0 + +""" +compute the diffusion tensor in each voxel +""" + +hardi_mat = pe.Node(interface=dtk.HARDIMat(),name='hardi_mat') + +odf_recon = pe.Node(interface=dtk.ODFRecon(),name='odf_recon') + +""" +connect all the nodes for this workflow +""" + +computeTensor.connect([ + (fslroi,bet,[('roi_file','in_file')]), + (eddycorrect, odf_recon,[('eddy_corrected','dwi')]), + (eddycorrect, hardi_mat,[('eddy_corrected','reference_file')]), + (hardi_mat, odf_recon, [('out_file', 'matrix')]) + ]) + + + +""" +Setup for Tracktography +----------------------- +Here we will create a workflow to enable probabilistic tracktography +and hard segmentation of the seed region +""" + +tractography = pe.Workflow(name='tractography') +tractography.base_dir = os.path.abspath('odf_tutorial') + +odf_trackt = pe.Node(interface=dtk.ODFTracker(), name="odf_trackt") + +smooth_trk = pe.Node(interface=dtk.SplineFilter(), name="smooth_trk") +smooth_trk.inputs.step_length = 1 +""" +connect all the nodes for this workflow +""" + +tractography.connect([ + (odf_trackt, smooth_trk, [('track_file', 'track_file')]) + ]) + + +""" +Setup data storage area +""" + +datasink = pe.Node(interface=nio.DataSink(),name='datasink') +datasink.inputs.base_directory = os.path.abspath('dtiresults') + +def getstripdir(subject_id): + return os.path.join(os.path.abspath('data/workingdir/dwiproc'),'_subject_id_%s' % subject_id) + + +""" +Setup the pipeline that combines the two workflows: tractography and computeTensor +---------------------------------------------------------------------------------- +""" + +dwiproc = pe.Workflow(name="dwiproc") +dwiproc.base_dir = os.path.abspath('odf_tutorial') +dwiproc.connect([ + (infosource,datasource,[('subject_id', 'subject_id')]), + (datasource,computeTensor,[('dwi','fslroi.in_file'), + ('bvals','hardi_mat.bvals'), + ('bvecs','hardi_mat.bvecs'), + ('dwi','eddycorrect.in_file')]), + (computeTensor,tractography,[('bet.mask_file','odf_trackt.mask1_file'), + ('odf_recon.ODF','odf_trackt.ODF'), + ('odf_recon.MAX','odf_trackt.MAX') + ]) + ]) + +dwiproc.inputs.computeTensor.hardi_mat.oblique_correction = True +dwiproc.inputs.computeTensor.odf_recon.n_directions = 60 +dwiproc.inputs.computeTensor.odf_recon.n_b0 = 5 +dwiproc.inputs.computeTensor.odf_recon.n_output_directions = 181 + +dwiproc.run() +dwiproc.write_graph() + + From c25a13a341c9b6f3acb5ab8f8eb1343dd7de9311 Mon Sep 17 00:00:00 2001 From: Chris Filo Gorgolewski Date: Wed, 1 Sep 2010 16:17:43 -0400 Subject: [PATCH 08/16] corrected gradient matrix generation --- .../interfaces/diffusion_toolkit/preproc.py | 48 ++++++++++++------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/nipype/interfaces/diffusion_toolkit/preproc.py b/nipype/interfaces/diffusion_toolkit/preproc.py index 4f67baa96a..72211dd497 100644 --- a/nipype/interfaces/diffusion_toolkit/preproc.py +++ b/nipype/interfaces/diffusion_toolkit/preproc.py @@ -18,20 +18,6 @@ from nipype.interfaces.base import (TraitedSpec, File, traits, CommandLine, CommandLineInputSpec) -def _create_gradient_matrix(bvecs_file, bvals_file): - _gradient_matrix_file = 'gradient_matrix.txt' - bvals = [val for val in re.split('\s+', open(bvals_file).readline().strip())] - bvecs_f = open(bvecs_file) - bvecs_x = [val for val in re.split('\s+', bvecs_f.readline().strip())] - bvecs_y = [val for val in re.split('\s+', bvecs_f.readline().strip())] - bvecs_z = [val for val in re.split('\s+', bvecs_f.readline().strip())] - bvecs_f.close() - gradient_matrix_f = open(_gradient_matrix_file, 'w') - for i in range(len(bvals)): - gradient_matrix_f.write("%s, %s, %s, %s\n"%(bvecs_x[i], bvecs_y[i], bvecs_z[i], bvals[i])) - gradient_matrix_f.close() - return _gradient_matrix_file - class DTIReconInputSpec(CommandLineInputSpec): dwi = File(desc='Input diffusion volume', argstr='%s',exists=True, mandatory=True,position=1) out_prefix = traits.Str("dti", desc='Output file prefix', argstr='%s', usedefault=True,position=2) @@ -78,9 +64,23 @@ class DTIRecon(CommandLine): _cmd = 'dti_recon' + def _create_gradient_matrix(self, bvecs_file, bvals_file): + _gradient_matrix_file = 'gradient_matrix.txt' + bvals = [val for val in re.split('\s+', open(bvals_file).readline().strip())] + bvecs_f = open(bvecs_file) + bvecs_x = [val for val in re.split('\s+', bvecs_f.readline().strip())] + bvecs_y = [val for val in re.split('\s+', bvecs_f.readline().strip())] + bvecs_z = [val for val in re.split('\s+', bvecs_f.readline().strip())] + bvecs_f.close() + gradient_matrix_f = open(_gradient_matrix_file, 'w') + for i in range(len(bvals)): + gradient_matrix_f.write("%s, %s, %s, %s\n"%(bvecs_x[i], bvecs_y[i], bvecs_z[i], bvals[i])) + gradient_matrix_f.close() + return _gradient_matrix_file + def _format_arg(self, name, spec, value): if name == "bvecs": - new_val = _create_gradient_matrix(self.inputs.bvecs, self.inputs.bvals) + new_val = self._create_gradient_matrix(self.inputs.bvecs, self.inputs.bvals) return super(DTIRecon, self)._format_arg("bvecs", spec, new_val) return super(DTIRecon, self)._format_arg(name, spec, value) @@ -226,9 +226,25 @@ class HARDIMat(CommandLine): _cmd = 'hardi_mat' + def _create_gradient_matrix(self, bvecs_file, bvals_file): + _gradient_matrix_file = 'gradient_matrix.txt' + bvals = [val for val in re.split('\s+', open(bvals_file).readline().strip())] + bvecs_f = open(bvecs_file) + bvecs_x = [val for val in re.split('\s+', bvecs_f.readline().strip())] + bvecs_y = [val for val in re.split('\s+', bvecs_f.readline().strip())] + bvecs_z = [val for val in re.split('\s+', bvecs_f.readline().strip())] + bvecs_f.close() + gradient_matrix_f = open(_gradient_matrix_file, 'w') + for i in range(len(bvals)): + if int(bvals[i]) == 0: + continue + gradient_matrix_f.write("%s %s %s\n"%(bvecs_x[i], bvecs_y[i], bvecs_z[i])) + gradient_matrix_f.close() + return _gradient_matrix_file + def _format_arg(self, name, spec, value): if name == "bvecs": - new_val = _create_gradient_matrix(self.inputs.bvecs, self.inputs.bvals) + new_val = self._create_gradient_matrix(self.inputs.bvecs, self.inputs.bvals) return super(HARDIMat, self)._format_arg("bvecs", spec, new_val) return super(HARDIMat, self)._format_arg(name, spec, value) From 3316cf20779be5d3166dd8eae01dda425e67a15f Mon Sep 17 00:00:00 2001 From: Chris Filo Gorgolewski Date: Wed, 1 Sep 2010 16:18:08 -0400 Subject: [PATCH 09/16] tutorial finally works --- examples/odf_tutorial.py | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/examples/odf_tutorial.py b/examples/odf_tutorial.py index ed3f0349e2..e420b82280 100644 --- a/examples/odf_tutorial.py +++ b/examples/odf_tutorial.py @@ -60,16 +60,16 @@ Specify the subject directories """ -subject_list = ['subj1'] +subject_list = ['siemens_hardi_test'] """ Map field names to individual subject runs """ -info = dict(dwi=[['subject_id', 'data']], - bvecs=[['subject_id','bvecs']], - bvals=[['subject_id','bvals']]) +info = dict(dwi=[['subject_id', 'siemens_hardi_test_data']], + bvecs=[['subject_id','siemens_hardi_test_data.bvec']], + bvals=[['subject_id','siemens_hardi_test_data.bval']]) infosource = pe.Node(interface=util.IdentityInterface(fields=['subject_id']), name="infosource") @@ -101,9 +101,9 @@ # This needs to point to the fdt folder you can find after extracting # http://www.fmrib.ox.ac.uk/fslcourse/fsl_course_data2.tar.gz -datasource.inputs.base_directory = os.path.abspath('fsl_course_data/fdt/') +datasource.inputs.base_directory = os.path.abspath('data') -datasource.inputs.field_template = dict(dwi='%s/%s.nii.gz') +datasource.inputs.field_template = dict(dwi='%s/%s.nii') datasource.inputs.template_args = info @@ -182,17 +182,6 @@ ]) -""" -Setup data storage area -""" - -datasink = pe.Node(interface=nio.DataSink(),name='datasink') -datasink.inputs.base_directory = os.path.abspath('dtiresults') - -def getstripdir(subject_id): - return os.path.join(os.path.abspath('data/workingdir/dwiproc'),'_subject_id_%s' % subject_id) - - """ Setup the pipeline that combines the two workflows: tractography and computeTensor ---------------------------------------------------------------------------------- @@ -213,7 +202,7 @@ def getstripdir(subject_id): ]) dwiproc.inputs.computeTensor.hardi_mat.oblique_correction = True -dwiproc.inputs.computeTensor.odf_recon.n_directions = 60 +dwiproc.inputs.computeTensor.odf_recon.n_directions = 31 dwiproc.inputs.computeTensor.odf_recon.n_b0 = 5 dwiproc.inputs.computeTensor.odf_recon.n_output_directions = 181 From c74cefacb7a0a780e15396b6a2d22ffe5bbde698 Mon Sep 17 00:00:00 2001 From: Chris Filo Gorgolewski Date: Thu, 2 Sep 2010 12:43:31 -0400 Subject: [PATCH 10/16] DTK cleanup --- .../interfaces/diffusion_toolkit/__init__.py | 4 +- nipype/interfaces/diffusion_toolkit/dti.py | 166 ++++++++++++++++ .../diffusion_toolkit/{preproc.py => odf.py} | 179 +----------------- .../interfaces/diffusion_toolkit/postproc.py | 35 ++++ 4 files changed, 210 insertions(+), 174 deletions(-) create mode 100644 nipype/interfaces/diffusion_toolkit/dti.py rename nipype/interfaces/diffusion_toolkit/{preproc.py => odf.py} (56%) create mode 100644 nipype/interfaces/diffusion_toolkit/postproc.py diff --git a/nipype/interfaces/diffusion_toolkit/__init__.py b/nipype/interfaces/diffusion_toolkit/__init__.py index fbc59d9659..2a086ecb29 100644 --- a/nipype/interfaces/diffusion_toolkit/__init__.py +++ b/nipype/interfaces/diffusion_toolkit/__init__.py @@ -1 +1,3 @@ -from nipype.interfaces.diffusion_toolkit.preproc import (DTIRecon, DTITracker, HARDIMat, ODFRecon, ODFTracker, SplineFilter) +from nipype.interfaces.diffusion_toolkit.postproc import SplineFilter +from nipype.interfaces.diffusion_toolkit.dti import (DTIRecon, DTITracker) +from nipype.interfaces.diffusion_toolkit.odf import (HARDIMat, ODFRecon, ODFTracker) diff --git a/nipype/interfaces/diffusion_toolkit/dti.py b/nipype/interfaces/diffusion_toolkit/dti.py new file mode 100644 index 0000000000..cc3eb2267c --- /dev/null +++ b/nipype/interfaces/diffusion_toolkit/dti.py @@ -0,0 +1,166 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: +"""Provides interfaces to various commands provided by diffusion toolkit + + Change directory to provide relative paths for doctests + >>> import os + >>> filepath = os.path.dirname( os.path.realpath( __file__ ) ) + >>> datadir = os.path.realpath(os.path.join(filepath, '../../testing/data')) + >>> os.chdir(datadir) + +""" +import re +from nipype.utils.filemanip import fname_presuffix, split_filename, copyfile +import os +from nipype.utils.misc import isdefined +__docformat__ = 'restructuredtext' + +from nipype.interfaces.base import (TraitedSpec, File, traits, CommandLine, + CommandLineInputSpec) + +class DTIReconInputSpec(CommandLineInputSpec): + DWI = File(desc='Input diffusion volume', argstr='%s',exists=True, mandatory=True,position=1) + out_prefix = traits.Str("dti", desc='Output file prefix', argstr='%s', usedefault=True,position=2) + output_type = traits.Enum('nii', 'analyze', 'ni1', 'nii.gz', argstr='-ot %s', desc='output file type', usedefault=True) + bvecs = File(exists=True, desc = 'b vectors file', + argstr='-gm %s', mandatory=True) + bvals = File(exists=True,desc = 'b values file', mandatory=True) + n_averages = traits.Int(desc='Number of averages', argstr='-nex %s') + image_orientation_vectors = traits.List(traits.Float(), minlen=6, maxlen=6, desc="""specify image orientation vectors. if just one argument given, +will treat it as filename and read the orientation vectors from +the file. if 6 arguments are given, will treat them as 6 float +numbers and construct the 1st and 2nd vector and calculate the 3rd +one automatically. +this information will be used to determine image orientation, +as well as to adjust gradient vectors with oblique angle when""", argstr="-iop %f") + oblique_correction = traits.Bool(desc="""when oblique angle(s) applied, some SIEMENS dti protocols do not +adjust gradient accordingly, thus it requires adjustment for correct +diffusion tensor calculation""", argstr="-oc") + b0_threshold = traits.Float(desc="""program will use b0 image with the given threshold to mask out high +background of fa/adc maps. by default it will calculate threshold +automatically. but if it failed, you need to set it manually.""", argstr="-b0_th") + + +class DTIReconOutputSpec(TraitedSpec): + ADC = File(exists=True) + B0 = File(exists=True) + L1 = File(exists=True) + L2 = File(exists=True) + L3 = File(exists=True) + exp = File(exists=True) + FA = File(exists=True) + FA_color = File(exists=True) + tensor = File(exists=True) + V1 = File(exists=True) + V2 = File(exists=True) + V3 = File(exists=True) + +class DTIRecon(CommandLine): + """Use dti_recon to generate tensors and other maps + """ + + input_spec=DTIReconInputSpec + output_spec=DTIReconOutputSpec + + _cmd = 'dti_recon' + + def _create_gradient_matrix(self, bvecs_file, bvals_file): + _gradient_matrix_file = 'gradient_matrix.txt' + bvals = [val for val in re.split('\s+', open(bvals_file).readline().strip())] + bvecs_f = open(bvecs_file) + bvecs_x = [val for val in re.split('\s+', bvecs_f.readline().strip())] + bvecs_y = [val for val in re.split('\s+', bvecs_f.readline().strip())] + bvecs_z = [val for val in re.split('\s+', bvecs_f.readline().strip())] + bvecs_f.close() + gradient_matrix_f = open(_gradient_matrix_file, 'w') + for i in range(len(bvals)): + gradient_matrix_f.write("%s, %s, %s, %s\n"%(bvecs_x[i], bvecs_y[i], bvecs_z[i], bvals[i])) + gradient_matrix_f.close() + return _gradient_matrix_file + + def _format_arg(self, name, spec, value): + if name == "bvecs": + new_val = self._create_gradient_matrix(self.inputs.bvecs, self.inputs.bvals) + return super(DTIRecon, self)._format_arg("bvecs", spec, new_val) + return super(DTIRecon, self)._format_arg(name, spec, value) + + def _list_outputs(self): + out_prefix = self.inputs.out_prefix + output_type = self.inputs.output_type + + outputs = self.output_spec().get() + outputs['ADC'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_adc.'+ output_type)) + outputs['B0'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_b0.'+ output_type)) + outputs['L1'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_e1.'+ output_type)) + outputs['L2'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_e2.'+ output_type)) + outputs['L3'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_e3.'+ output_type)) + outputs['exp'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_exp.'+ output_type)) + outputs['FA'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_fa.'+ output_type)) + outputs['FA_color'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_fa_color.'+ output_type)) + outputs['tensor'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_tensor.'+ output_type)) + outputs['V1'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_v1.'+ output_type)) + outputs['V2'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_v2.'+ output_type)) + outputs['V3'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_v3.'+ output_type)) + + return outputs + +class DTITrackerInputSpec(CommandLineInputSpec): + tensor_file = File(exists=True, desc="reconstructed tensor file") + input_type = traits.Enum('nii', 'analyze', 'ni1', 'nii.gz', desc="""input and output file type. accepted values are: +analyze -> analyze format 7.5 +ni1 -> nifti format saved in seperate .hdr and .img file +nii -> nifti format with one .nii file +nii.gz -> nifti format with compression +default type is 'nii'""", argstr = "-it %s") + tracking_method = traits.Enum('fact', 'rk2', 'tl', 'sl', desc="""fact -> use FACT method for tracking. this is the default method. +rk2 -> use 2nd order runge-kutta method for tracking. +tl -> use tensorline method for tracking. +sl -> use interpolated streamline method with fixed step-length""", argstr="-%s") + step_length = traits.Float(desc="""set step length, in the unit of minimum voxel size. +default value is 0.5 for interpolated streamline method +and 0.1 for other methods""", argstr="-l %f") + angle_threshold = traits.Float(desc="set angle threshold. default value is 35 degree", argstr="-at %f") + angle_threshold_weight = traits.Float(desc="set angle threshold weighting factor. weighting will be be applied \ +on top of the angle_threshold", argstr = "-atw %f") + random_seed = traits.Int(desc = "use random location in a voxel instead of the center of the voxel \ + to seed. can also define number of seed per voxel. default is 1", argstr="-rseed") + invert_x = traits.Bool(desc="invert x component of the vector", argstr = "-ix") + invert_y = traits.Bool(desc="invert y component of the vector", argstr = "-iy") + invert_z = traits.Bool(desc="invert z component of the vector", argstr = "-iz") + swap_xy = traits.Bool(desc="swap x & y vectors while tracking", argstr = "-sxy") + swap_yz = traits.Bool(desc="swap y & z vectors while tracking", argstr = "-syz") + swap_xz = traits.Bool(desc="swap x & z vectors while tracking", argstr = "-sxz") + mask1_file = File(desc="first mask image", mandatory=True, argstr="-m %s", position=2) + mask1_threshold = traits.Float(desc="threshold value for the first mask image, if not given, the program will \ +try automatically find the threshold", position=3) + mask2_file = File(desc="second mask image", argstr="-m2 %s", position=4) + mask2_threshold = traits.Float(desc="threshold value for the second mask image, if not given, the program will \ +try automatically find the threshold", position=5) + input_data_prefix = traits.Str("dti", desc="for internal naming use only", position=0, argstr="%s", usedefault=True) + output_file = File("tracks.trk", "file containing tracks", argstr="%s", position=1, usedefault=True) + output_mask = File(desc="output a binary mask file in analyze format", argstr="-om %s") + primary_vector = traits.Enum('v2', 'v3', desc = "which vector to use for fibre tracking: v2 or v3. If not set use v1", argstr="-%s") + +class DTITrackerOutputSpec(TraitedSpec): + track_file = File(exists=True) + mask_file = File(exists=True) + +class DTITracker(CommandLine): + input_spec=DTITrackerInputSpec + output_spec=DTITrackerOutputSpec + + _cmd = 'dti_tracker' + + def _run_interface(self, runtime): + _, _, ext = split_filename(self.inputs.tensor_file) + copyfile(self.inputs.tensor_file, os.path.abspath(self.inputs.input_data_prefix + "_tensor" + ext), copy=False) + + return super(DTITracker, self)._run_interface(runtime) + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['track_file'] = os.path.abspath(self.inputs.output_file) + if isdefined(self.inputs.output_mask) and self.inputs.output_mask: + outputs['mask_file'] = os.path.abspath(self.inputs.output_mask) + + return outputs \ No newline at end of file diff --git a/nipype/interfaces/diffusion_toolkit/preproc.py b/nipype/interfaces/diffusion_toolkit/odf.py similarity index 56% rename from nipype/interfaces/diffusion_toolkit/preproc.py rename to nipype/interfaces/diffusion_toolkit/odf.py index 72211dd497..22c254ce86 100644 --- a/nipype/interfaces/diffusion_toolkit/preproc.py +++ b/nipype/interfaces/diffusion_toolkit/odf.py @@ -18,172 +18,6 @@ from nipype.interfaces.base import (TraitedSpec, File, traits, CommandLine, CommandLineInputSpec) -class DTIReconInputSpec(CommandLineInputSpec): - dwi = File(desc='Input diffusion volume', argstr='%s',exists=True, mandatory=True,position=1) - out_prefix = traits.Str("dti", desc='Output file prefix', argstr='%s', usedefault=True,position=2) - output_type = traits.Enum('nii', 'analyze', 'ni1', 'nii.gz', argstr='-ot %s', desc='output file type', usedefault=True) - bvecs = File(exists=True, desc = 'b vectors file', - argstr='-gm %s', mandatory=True) - bvals = File(exists=True,desc = 'b values file', mandatory=True) - n_averages = traits.Int(desc='Number of averages', argstr='-nex %s') - image_orientation_vectors = traits.List(traits.Float(), minlen=6, maxlen=6, desc="""specify image orientation vectors. if just one argument given, -will treat it as filename and read the orientation vectors from -the file. if 6 arguments are given, will treat them as 6 float -numbers and construct the 1st and 2nd vector and calculate the 3rd -one automatically. -this information will be used to determine image orientation, -as well as to adjust gradient vectors with oblique angle when""", argstr="-iop %f") - oblique_correction = traits.Bool(desc="""when oblique angle(s) applied, some SIEMENS dti protocols do not -adjust gradient accordingly, thus it requires adjustment for correct -diffusion tensor calculation""", argstr="-oc") - b0_threshold = traits.Float(desc="""program will use b0 image with the given threshold to mask out high -background of fa/adc maps. by default it will calculate threshold -automatically. but if it failed, you need to set it manually.""", argstr="-b0_th") - - -class DTIReconOutputSpec(TraitedSpec): - ADC = File(exists=True) - B0 = File(exists=True) - L1 = File(exists=True) - L2 = File(exists=True) - L3 = File(exists=True) - exp = File(exists=True) - FA = File(exists=True) - FA_color = File(exists=True) - tensor = File(exists=True) - V1 = File(exists=True) - V2 = File(exists=True) - V3 = File(exists=True) - -class DTIRecon(CommandLine): - """Use dti_recon to generate tensors and other maps - """ - - input_spec=DTIReconInputSpec - output_spec=DTIReconOutputSpec - - _cmd = 'dti_recon' - - def _create_gradient_matrix(self, bvecs_file, bvals_file): - _gradient_matrix_file = 'gradient_matrix.txt' - bvals = [val for val in re.split('\s+', open(bvals_file).readline().strip())] - bvecs_f = open(bvecs_file) - bvecs_x = [val for val in re.split('\s+', bvecs_f.readline().strip())] - bvecs_y = [val for val in re.split('\s+', bvecs_f.readline().strip())] - bvecs_z = [val for val in re.split('\s+', bvecs_f.readline().strip())] - bvecs_f.close() - gradient_matrix_f = open(_gradient_matrix_file, 'w') - for i in range(len(bvals)): - gradient_matrix_f.write("%s, %s, %s, %s\n"%(bvecs_x[i], bvecs_y[i], bvecs_z[i], bvals[i])) - gradient_matrix_f.close() - return _gradient_matrix_file - - def _format_arg(self, name, spec, value): - if name == "bvecs": - new_val = self._create_gradient_matrix(self.inputs.bvecs, self.inputs.bvals) - return super(DTIRecon, self)._format_arg("bvecs", spec, new_val) - return super(DTIRecon, self)._format_arg(name, spec, value) - - def _list_outputs(self): - out_prefix = self.inputs.out_prefix - output_type = self.inputs.output_type - - outputs = self.output_spec().get() - outputs['ADC'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_adc.'+ output_type)) - outputs['B0'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_b0.'+ output_type)) - outputs['L1'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_e1.'+ output_type)) - outputs['L2'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_e2.'+ output_type)) - outputs['L3'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_e3.'+ output_type)) - outputs['exp'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_exp.'+ output_type)) - outputs['FA'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_fa.'+ output_type)) - outputs['FA_color'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_fa_color.'+ output_type)) - outputs['tensor'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_tensor.'+ output_type)) - outputs['V1'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_v1.'+ output_type)) - outputs['V2'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_v2.'+ output_type)) - outputs['V3'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_v3.'+ output_type)) - - return outputs - -class DTITrackerInputSpec(CommandLineInputSpec): - tensor_file = File(exists=True, desc="reconstructed tensor file" ) - input_type = traits.Enum('nii', 'analyze', 'ni1', 'nii.gz', desc="""input and output file type. accepted values are: -analyze -> analyze format 7.5 -ni1 -> nifti format saved in seperate .hdr and .img file -nii -> nifti format with one .nii file -nii.gz -> nifti format with compression -default type is 'nii'""", argstr = "-it %s") - tracking_method = traits.Enum('fact', 'rk2', 'tl', 'sl', desc="""fact -> use FACT method for tracking. this is the default method. -rk2 -> use 2nd order runge-kutta method for tracking. -tl -> use tensorline method for tracking. -sl -> use interpolated streamline method with fixed step-length""", argstr="-%s") - step_length = traits.Float(desc="""set step length, in the unit of minimum voxel size. -default value is 0.5 for interpolated streamline method -and 0.1 for other methods""", argstr="-l %f") - angle_threshold = traits.Float(desc="set angle threshold. default value is 35 degree", argstr="-at %f") - angle_threshold_weight = traits.Float(desc="set angle threshold weighting factor. weighting will be be applied \ -on top of the angle_threshold", argstr = "-atw %f") - random_seed = traits.Int(desc = "use random location in a voxel instead of the center of the voxel \ - to seed. can also define number of seed per voxel. default is 1", argstr="-rseed") - invert_x = traits.Bool(desc="invert x component of the vector", argstr = "-ix") - invert_y = traits.Bool(desc="invert y component of the vector", argstr = "-iy") - invert_z = traits.Bool(desc="invert z component of the vector", argstr = "-iz") - swap_xy = traits.Bool(desc="swap x & y vectors while tracking", argstr = "-sxy") - swap_yz = traits.Bool(desc="swap y & z vectors while tracking", argstr = "-syz") - swap_xz = traits.Bool(desc="swap x & z vectors while tracking", argstr = "-sxz") - mask1_file = File(desc="first mask image", mandatory=True, argstr="-m %s", position=2) - mask1_threshold = traits.Float(desc="threshold value for the first mask image, if not given, the program will \ -try automatically find the threshold", position=3) - mask2_file = File(desc="second mask image", argstr="-m2 %s", position=4) - mask2_threshold = traits.Float(desc="threshold value for the second mask image, if not given, the program will \ -try automatically find the threshold", position=5) - input_data_prefix = traits.Str("dti", desc="for internal naming use only", position=0, argstr="%s", usedefault=True) - output_file = File("tracks.trk", "file containing tracks", argstr="%s", position=1, usedefault=True) - output_mask = File(desc="output a binary mask file in analyze format", argstr="-om %s") - primary_vector = traits.Enum('v2', 'v3', desc = "which vector to use for fibre tracking: v2 or v3. If not set use v1", argstr="-%s") - -class DTITrackerOutputSpec(TraitedSpec): - track_file = File(exists=True) - mask_file = File(exists=True) - -class DTITracker(CommandLine): - input_spec=DTITrackerInputSpec - output_spec=DTITrackerOutputSpec - - _cmd = 'dti_tracker' - - def _run_interface(self, runtime): - _, _, ext = split_filename(self.inputs.tensor_file) - copyfile(self.inputs.tensor_file, os.path.abspath(self.inputs.input_data_prefix + "_tensor" + ext), copy=False) - - return super(DTITracker, self)._run_interface(runtime) - - def _list_outputs(self): - outputs = self.output_spec().get() - outputs['track_file'] = os.path.abspath(self.inputs.output_file) - if isdefined(self.inputs.output_mask) and self.inputs.output_mask: - outputs['mask_file'] = os.path.abspath(self.inputs.output_mask) - - return outputs - -class SplineFilterInputSpec(CommandLineInputSpec): - track_file = File(exists=True, desc="file containing tracks to be filtered", position=0, argstr="%s", mandatory=True) - step_length = traits.Float(desc="in the unit of minimum voxel size", position=1, argstr="%f", mandatory=True) - output_file = File("spline_tracks.trk", desc="target file for smoothed tracks", position=2, argstr="%s", usedefault=True) - -class SplineFilterOutputSpec(TraitedSpec): - smoothed_track_file = File(exists=True) - -class SplineFilter(CommandLine): - input_spec=SplineFilterInputSpec - output_spec=SplineFilterOutputSpec - - _cmd = "spline_filter" - - def _list_outputs(self): - outputs = self.output_spec().get() - outputs['smoothed_track_file'] = os.path.abspath(self.inputs.output_file) - return outputs - class HARDIMatInputSpec(CommandLineInputSpec): bvecs = File(exists=True, desc = 'b vectors file', argstr='%s', position=1, mandatory=True) @@ -254,7 +88,7 @@ def _list_outputs(self): return outputs class ODFReconInputSpec(CommandLineInputSpec): - dwi = File(desc='Input raw data', argstr='%s',exists=True, mandatory=True,position=1) + DWI = File(desc='Input raw data', argstr='%s',exists=True, mandatory=True,position=1) n_directions = traits.Int(desc='Number of directions', argstr='%s', mandatory=True, position=2) n_output_directions = traits.Int(desc='Number of output directions', argstr='%s', mandatory=True, position=3) out_prefix = traits.Str("odf", desc='Output file prefix', argstr='%s', usedefault=True, position=4) @@ -286,9 +120,9 @@ class ODFReconInputSpec(CommandLineInputSpec): class ODFReconOutputSpec(TraitedSpec): B0 = File(exists=True) DWI = File(exists=True) - MAX = File(exists=True) + max = File(exists=True) ODF = File(exists=True) - ENTROPY = File(desc='Output entropy map') + entropy = File() class ODFRecon(CommandLine): """Use odf_recon to generate tensors and other maps @@ -306,15 +140,15 @@ def _list_outputs(self): outputs = self.output_spec().get() outputs['B0'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_b0.'+ output_type)) outputs['DWI'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_dwi.'+ output_type)) - outputs['MAX'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_max.'+ output_type)) + outputs['max'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_max.'+ output_type)) outputs['ODF'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_odf.'+ output_type)) if isdefined(self.inputs.output_entropy): - outputs['ENTROPY'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_entropy.'+ output_type)) + outputs['entropy'] = os.path.abspath(fname_presuffix("", prefix=out_prefix, suffix='_entropy.'+ output_type)) return outputs class ODFTrackerInputSpec(CommandLineInputSpec): - MAX = File(exists=True, mandatory=True) + max = File(exists=True, mandatory=True) ODF = File(exists=True, mandatory=True) input_data_prefix = traits.Str("odf", desc='recon data prefix', argstr='%s', usedefault=True, position=0) out_file = File("tracks.trk", desc = 'output track file', argstr='%s', usedefault=True, position=1) @@ -392,4 +226,3 @@ def _list_outputs(self): outputs['track_file'] = os.path.abspath(self.inputs.out_file) return outputs - \ No newline at end of file diff --git a/nipype/interfaces/diffusion_toolkit/postproc.py b/nipype/interfaces/diffusion_toolkit/postproc.py new file mode 100644 index 0000000000..20633ccf94 --- /dev/null +++ b/nipype/interfaces/diffusion_toolkit/postproc.py @@ -0,0 +1,35 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: +"""Provides interfaces to various commands provided by diffusion toolkit + + Change directory to provide relative paths for doctests + >>> import os + >>> filepath = os.path.dirname( os.path.realpath( __file__ ) ) + >>> datadir = os.path.realpath(os.path.join(filepath, '../../testing/data')) + >>> os.chdir(datadir) + +""" +import os +__docformat__ = 'restructuredtext' + +from nipype.interfaces.base import (TraitedSpec, File, traits, CommandLine, + CommandLineInputSpec) + +class SplineFilterInputSpec(CommandLineInputSpec): + track_file = File(exists=True, desc="file containing tracks to be filtered", position=0, argstr="%s", mandatory=True) + step_length = traits.Float(desc="in the unit of minimum voxel size", position=1, argstr="%f", mandatory=True) + output_file = File("spline_tracks.trk", desc="target file for smoothed tracks", position=2, argstr="%s", usedefault=True) + +class SplineFilterOutputSpec(TraitedSpec): + smoothed_track_file = File(exists=True) + +class SplineFilter(CommandLine): + input_spec=SplineFilterInputSpec + output_spec=SplineFilterOutputSpec + + _cmd = "spline_filter" + + def _list_outputs(self): + outputs = self.output_spec().get() + outputs['smoothed_track_file'] = os.path.abspath(self.inputs.output_file) + return outputs \ No newline at end of file From 21eb6705eed97621acc4a733f1bbf98a0c0e13af Mon Sep 17 00:00:00 2001 From: Chris Filo Gorgolewski Date: Thu, 2 Sep 2010 12:43:52 -0400 Subject: [PATCH 11/16] diffusion tutorials cleanup --- ...oolkit_tutorial.py => dtk_dti_tutorial.py} | 8 +++--- .../{odf_tutorial.py => dtk_odf_tutorial.py} | 25 ++++++++----------- .../{dti_tutorial.py => fsl_dti_tutorial.py} | 4 +-- 3 files changed, 17 insertions(+), 20 deletions(-) rename examples/{diffusion_toolkit_tutorial.py => dtk_dti_tutorial.py} (96%) rename examples/{odf_tutorial.py => dtk_odf_tutorial.py} (90%) rename examples/{dti_tutorial.py => fsl_dti_tutorial.py} (98%) diff --git a/examples/diffusion_toolkit_tutorial.py b/examples/dtk_dti_tutorial.py similarity index 96% rename from examples/diffusion_toolkit_tutorial.py rename to examples/dtk_dti_tutorial.py index 4eef186ba7..67c1e7c91c 100644 --- a/examples/diffusion_toolkit_tutorial.py +++ b/examples/dtk_dti_tutorial.py @@ -150,7 +150,7 @@ computeTensor.connect([ (fslroi,bet,[('roi_file','in_file')]), - (eddycorrect,dtifit,[('eddy_corrected','dwi')]) + (eddycorrect,dtifit,[('eddy_corrected','DWI')]) ]) @@ -163,9 +163,9 @@ """ tractography = pe.Workflow(name='tractography') -tractography.base_dir = os.path.abspath('dtk_tutorial') +tractography.base_dir = os.path.abspath('dtk_dti_tutorial') -dtk_trackt = pe.Node(interface=dtk.DTITracker(), name="dtk_trackt") +dtk_tracker = pe.Node(interface=dtk.DTITracker(), name="dtk_tracker") smooth_trk = pe.Node(interface=dtk.SplineFilter(), name="smooth_trk") smooth_trk.inputs.step_length = 0.5 @@ -174,7 +174,7 @@ """ tractography.connect([ - (dtk_trackt, smooth_trk, [('track_file', 'track_file')]) + (dtk_tracker, smooth_trk, [('track_file', 'track_file')]) ]) diff --git a/examples/odf_tutorial.py b/examples/dtk_odf_tutorial.py similarity index 90% rename from examples/odf_tutorial.py rename to examples/dtk_odf_tutorial.py index e420b82280..730112f42a 100644 --- a/examples/odf_tutorial.py +++ b/examples/dtk_odf_tutorial.py @@ -113,7 +113,7 @@ Here we will create a generic workflow for DTI computation """ -computeTensor = pe.Workflow(name='computeTensor') +compute_ODF = pe.Workflow(name='compute_ODF') """ extract the volume with b=0 (nodif_brain) @@ -138,9 +138,6 @@ eddycorrect = pe.Node(interface=fsl.EddyCorrect(),name='eddycorrect') eddycorrect.inputs.ref_num=0 -""" -compute the diffusion tensor in each voxel -""" hardi_mat = pe.Node(interface=dtk.HARDIMat(),name='hardi_mat') @@ -150,9 +147,9 @@ connect all the nodes for this workflow """ -computeTensor.connect([ +compute_ODF.connect([ (fslroi,bet,[('roi_file','in_file')]), - (eddycorrect, odf_recon,[('eddy_corrected','dwi')]), + (eddycorrect, odf_recon,[('eddy_corrected','DWI')]), (eddycorrect, hardi_mat,[('eddy_corrected','reference_file')]), (hardi_mat, odf_recon, [('out_file', 'matrix')]) ]) @@ -167,9 +164,9 @@ """ tractography = pe.Workflow(name='tractography') -tractography.base_dir = os.path.abspath('odf_tutorial') +tractography.base_dir = os.path.abspath('dtk_odf_tutorial') -odf_trackt = pe.Node(interface=dtk.ODFTracker(), name="odf_trackt") +odf_tracker = pe.Node(interface=dtk.ODFTracker(), name="odf_tracker") smooth_trk = pe.Node(interface=dtk.SplineFilter(), name="smooth_trk") smooth_trk.inputs.step_length = 1 @@ -178,12 +175,12 @@ """ tractography.connect([ - (odf_trackt, smooth_trk, [('track_file', 'track_file')]) + (odf_tracker, smooth_trk, [('track_file', 'track_file')]) ]) """ -Setup the pipeline that combines the two workflows: tractography and computeTensor +Setup the pipeline that combines the two workflows: tractography and compute_ODF ---------------------------------------------------------------------------------- """ @@ -191,13 +188,13 @@ dwiproc.base_dir = os.path.abspath('odf_tutorial') dwiproc.connect([ (infosource,datasource,[('subject_id', 'subject_id')]), - (datasource,computeTensor,[('dwi','fslroi.in_file'), + (datasource,compute_ODF,[('dwi','fslroi.in_file'), ('bvals','hardi_mat.bvals'), ('bvecs','hardi_mat.bvecs'), ('dwi','eddycorrect.in_file')]), - (computeTensor,tractography,[('bet.mask_file','odf_trackt.mask1_file'), - ('odf_recon.ODF','odf_trackt.ODF'), - ('odf_recon.MAX','odf_trackt.MAX') + (compute_ODF,tractography,[('bet.mask_file','odf_trackt.mask1_file'), + ('odf_recon.ODF','odf_tracker.ODF'), + ('odf_recon.max','odf_tracker.max') ]) ]) diff --git a/examples/dti_tutorial.py b/examples/fsl_dti_tutorial.py similarity index 98% rename from examples/dti_tutorial.py rename to examples/fsl_dti_tutorial.py index 79d59de471..bd8d797b13 100644 --- a/examples/dti_tutorial.py +++ b/examples/fsl_dti_tutorial.py @@ -174,7 +174,7 @@ """ tractography = pe.Workflow(name='tractography') -tractography.base_dir = os.path.abspath('dti_tutorial') +tractography.base_dir = os.path.abspath('fsl_dti_tutorial') """ estimate the diffusion parameters: phi, theta, and so on @@ -243,7 +243,7 @@ def getstripdir(subject_id): """ dwiproc = pe.Workflow(name="dwiproc") -dwiproc.base_dir = os.path.abspath('dti_tutorial') +dwiproc.base_dir = os.path.abspath('fsl_dti_tutorial') dwiproc.connect([ (infosource,datasource,[('subject_id', 'subject_id')]), (datasource,computeTensor,[('dwi','fslroi.in_file'), From 3810ee8e8483b7432caa9a322036be959e343a0f Mon Sep 17 00:00:00 2001 From: Chris Filo Gorgolewski Date: Thu, 2 Sep 2010 14:53:35 -0400 Subject: [PATCH 12/16] added crucial direction inversion --- examples/dtk_dti_tutorial.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/dtk_dti_tutorial.py b/examples/dtk_dti_tutorial.py index 67c1e7c91c..ba81f3ee6c 100644 --- a/examples/dtk_dti_tutorial.py +++ b/examples/dtk_dti_tutorial.py @@ -163,9 +163,9 @@ """ tractography = pe.Workflow(name='tractography') -tractography.base_dir = os.path.abspath('dtk_dti_tutorial') dtk_tracker = pe.Node(interface=dtk.DTITracker(), name="dtk_tracker") +dtk_tracker.inputs.invert_x = True smooth_trk = pe.Node(interface=dtk.SplineFilter(), name="smooth_trk") smooth_trk.inputs.step_length = 0.5 @@ -195,15 +195,15 @@ def getstripdir(subject_id): """ dwiproc = pe.Workflow(name="dwiproc") -dwiproc.base_dir = os.path.abspath('dtk_tutorial') +dwiproc.base_dir = os.path.abspath('dtk_dti_tutorial') dwiproc.connect([ (infosource,datasource,[('subject_id', 'subject_id')]), (datasource,computeTensor,[('dwi','fslroi.in_file'), ('bvals','dtifit.bvals'), ('bvecs','dtifit.bvecs'), ('dwi','eddycorrect.in_file')]), - (computeTensor,tractography,[('bet.mask_file','dtk_trackt.mask1_file'), - ('dtifit.tensor','dtk_trackt.tensor_file') + (computeTensor,tractography,[('bet.mask_file','dtk_tracker.mask1_file'), + ('dtifit.tensor','dtk_tracker.tensor_file') ]) ]) From 9367489913cceb88b257001cefdb02a6d932037e Mon Sep 17 00:00:00 2001 From: Chris Filo Gorgolewski Date: Thu, 2 Sep 2010 14:54:53 -0400 Subject: [PATCH 13/16] typos --- examples/dtk_odf_tutorial.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/examples/dtk_odf_tutorial.py b/examples/dtk_odf_tutorial.py index 730112f42a..e39f84d5a3 100644 --- a/examples/dtk_odf_tutorial.py +++ b/examples/dtk_odf_tutorial.py @@ -164,7 +164,6 @@ """ tractography = pe.Workflow(name='tractography') -tractography.base_dir = os.path.abspath('dtk_odf_tutorial') odf_tracker = pe.Node(interface=dtk.ODFTracker(), name="odf_tracker") @@ -185,23 +184,23 @@ """ dwiproc = pe.Workflow(name="dwiproc") -dwiproc.base_dir = os.path.abspath('odf_tutorial') +dwiproc.base_dir = os.path.abspath('dtk_odf_tutorial') dwiproc.connect([ (infosource,datasource,[('subject_id', 'subject_id')]), (datasource,compute_ODF,[('dwi','fslroi.in_file'), ('bvals','hardi_mat.bvals'), ('bvecs','hardi_mat.bvecs'), ('dwi','eddycorrect.in_file')]), - (compute_ODF,tractography,[('bet.mask_file','odf_trackt.mask1_file'), + (compute_ODF,tractography,[('bet.mask_file','odf_tracker.mask1_file'), ('odf_recon.ODF','odf_tracker.ODF'), ('odf_recon.max','odf_tracker.max') ]) ]) -dwiproc.inputs.computeTensor.hardi_mat.oblique_correction = True -dwiproc.inputs.computeTensor.odf_recon.n_directions = 31 -dwiproc.inputs.computeTensor.odf_recon.n_b0 = 5 -dwiproc.inputs.computeTensor.odf_recon.n_output_directions = 181 +dwiproc.inputs.compute_ODF.hardi_mat.oblique_correction = True +dwiproc.inputs.compute_ODF.odf_recon.n_directions = 31 +dwiproc.inputs.compute_ODF.odf_recon.n_b0 = 5 +dwiproc.inputs.compute_ODF.odf_recon.n_output_directions = 181 dwiproc.run() dwiproc.write_graph() From 6b92c0538bd787158429f10c0700ba515acf7b26 Mon Sep 17 00:00:00 2001 From: Chris Filo Gorgolewski Date: Thu, 2 Sep 2010 14:55:26 -0400 Subject: [PATCH 14/16] corrected swap parameter --- nipype/interfaces/diffusion_toolkit/dti.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nipype/interfaces/diffusion_toolkit/dti.py b/nipype/interfaces/diffusion_toolkit/dti.py index cc3eb2267c..b508828f1e 100644 --- a/nipype/interfaces/diffusion_toolkit/dti.py +++ b/nipype/interfaces/diffusion_toolkit/dti.py @@ -129,7 +129,7 @@ class DTITrackerInputSpec(CommandLineInputSpec): invert_z = traits.Bool(desc="invert z component of the vector", argstr = "-iz") swap_xy = traits.Bool(desc="swap x & y vectors while tracking", argstr = "-sxy") swap_yz = traits.Bool(desc="swap y & z vectors while tracking", argstr = "-syz") - swap_xz = traits.Bool(desc="swap x & z vectors while tracking", argstr = "-sxz") + swap_zx = traits.Bool(desc="swap x & z vectors while tracking", argstr = "-szx") mask1_file = File(desc="first mask image", mandatory=True, argstr="-m %s", position=2) mask1_threshold = traits.Float(desc="threshold value for the first mask image, if not given, the program will \ try automatically find the threshold", position=3) From 1711d66134feaad60eabb1973af2e1d00c81c53c Mon Sep 17 00:00:00 2001 From: Chris Filo Gorgolewski Date: Thu, 2 Sep 2010 14:55:51 -0400 Subject: [PATCH 15/16] corrected max name --- nipype/interfaces/diffusion_toolkit/odf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nipype/interfaces/diffusion_toolkit/odf.py b/nipype/interfaces/diffusion_toolkit/odf.py index 22c254ce86..ce1be469ba 100644 --- a/nipype/interfaces/diffusion_toolkit/odf.py +++ b/nipype/interfaces/diffusion_toolkit/odf.py @@ -213,8 +213,8 @@ class ODFTracker(CommandLine): _cmd = 'odf_tracker' def _run_interface(self, runtime): - _, _, ext = split_filename(self.inputs.MAX) - copyfile(self.inputs.MAX, os.path.abspath(self.inputs.input_data_prefix + "_max" + ext), copy=False) + _, _, ext = split_filename(self.inputs.max) + copyfile(self.inputs.max, os.path.abspath(self.inputs.input_data_prefix + "_max" + ext), copy=False) _, _, ext = split_filename(self.inputs.ODF) copyfile(self.inputs.ODF, os.path.abspath(self.inputs.input_data_prefix + "_odf" + ext), copy=False) From 0310d388b767ae5cc034e5fdbfa1175115cc4104 Mon Sep 17 00:00:00 2001 From: Chris Filo Gorgolewski Date: Fri, 3 Sep 2010 09:54:37 -0400 Subject: [PATCH 16/16] improved comments --- examples/dtk_dti_tutorial.py | 5 ++--- examples/dtk_odf_tutorial.py | 15 +++++---------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/examples/dtk_dti_tutorial.py b/examples/dtk_dti_tutorial.py index ba81f3ee6c..b553c53157 100644 --- a/examples/dtk_dti_tutorial.py +++ b/examples/dtk_dti_tutorial.py @@ -2,7 +2,7 @@ """ A pipeline example that uses several interfaces to perform analysis on diffusion weighted images using -FSL FDT tools. +Diffusion Toolkit and FSL. This tutorial is based on the 2010 FSL course and uses data freely available at the FSL website at: @@ -158,8 +158,7 @@ """ Setup for Tracktography ----------------------- -Here we will create a workflow to enable probabilistic tracktography -and hard segmentation of the seed region +Here we will create a workflow to enable deterministic tracktography """ tractography = pe.Workflow(name='tractography') diff --git a/examples/dtk_odf_tutorial.py b/examples/dtk_odf_tutorial.py index e39f84d5a3..47d47d2860 100644 --- a/examples/dtk_odf_tutorial.py +++ b/examples/dtk_odf_tutorial.py @@ -2,13 +2,9 @@ """ A pipeline example that uses several interfaces to perform analysis on diffusion weighted images using -FSL FDT tools. +Diffusion Toolkit and FSL. -This tutorial is based on the 2010 FSL course and uses -data freely available at the FSL website at: -http://www.fmrib.ox.ac.uk/fslcourse/fsl_course_data2.tar.gz - -More details can be found at http://www.fmrib.ox.ac.uk/fslcourse/lectures/practicals/fdt/index.htm +This tutorial uses data from out nipype-tutorial package. """ @@ -108,9 +104,9 @@ """ -Setup for Diffusion Tensor Computation +Setup for ODF Computation -------------------------------------- -Here we will create a generic workflow for DTI computation +Here we will create a generic workflow for ODF computation """ compute_ODF = pe.Workflow(name='compute_ODF') @@ -159,8 +155,7 @@ """ Setup for Tracktography ----------------------- -Here we will create a workflow to enable probabilistic tracktography -and hard segmentation of the seed region +Here we will create a workflow to enable deterministic tracktography """ tractography = pe.Workflow(name='tractography')