From 4d55a7470f7ce2384cf8aeac1d5adbc439f76e76 Mon Sep 17 00:00:00 2001 From: Chris Filo Gorgolewski Date: Fri, 9 May 2014 11:34:36 +0200 Subject: [PATCH 1/2] Fixed c3d --- bips/workflows/gablab/wips/scripts/smri_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bips/workflows/gablab/wips/scripts/smri_base.py b/bips/workflows/gablab/wips/scripts/smri_base.py index 012a394..c0b6cd7 100644 --- a/bips/workflows/gablab/wips/scripts/smri_base.py +++ b/bips/workflows/gablab/wips/scripts/smri_base.py @@ -135,7 +135,7 @@ def get_post_struct_norm_workflow(name='normalize_post_struct'): #makes fsl-style coregistration ANTS compatible fsl_reg_2_itk = pe.Node( - c3.C3dAffineTool(fsl2ras=True), + c3.C3dAffineTool(fsl2ras=True, itk_transform=True), name='fsl_reg_2_itk') #collects series of transformations to be applied to the moving images @@ -215,7 +215,7 @@ def get_post_struct_norm_WIMT_workflow(name='normalize_post_struct'): #makes fsl-style coregistration ANTS compatible fsl_reg_2_itk = pe.Node( - c3.C3dAffineTool(fsl2ras=True), + c3.C3dAffineTool(fsl2ras=True, itk_transform=True), name='fsl_reg_2_itk') #collects series of transformations to be applied to the moving images From f1b030933a9538ce44a56826a28289f9e19ed6ba Mon Sep 17 00:00:00 2001 From: Chris Filo Gorgolewski Date: Fri, 9 May 2014 14:07:18 +0200 Subject: [PATCH 2/2] new option for applying normalization - keep original resolution, refactoring, fixes --- .../gablab/wips/scripts/smri_base.py | 116 +++++------------- .../gablab/wips/smri/normalize_functionals.py | 13 +- 2 files changed, 41 insertions(+), 88 deletions(-) diff --git a/bips/workflows/gablab/wips/scripts/smri_base.py b/bips/workflows/gablab/wips/scripts/smri_base.py index c0b6cd7..cb06ed3 100644 --- a/bips/workflows/gablab/wips/scripts/smri_base.py +++ b/bips/workflows/gablab/wips/scripts/smri_base.py @@ -1,5 +1,5 @@ from smri_utils import (convert_affine, get_image_dimensions) -from nipype.interfaces import c3 +from nipype.interfaces import c3, fsl def get_struct_norm_workflow(name='normalize_struct'): @@ -94,88 +94,24 @@ def get_struct_norm_workflow(name='normalize_struct'): return normalize_struct - -def get_post_struct_norm_workflow(name='normalize_post_struct'): - """ Base post-structural workflow for normalization +def get_highest_resolution(images): + """Return dimensions of list of images Parameters ---------- - name : name of workflow. Default = 'normalize_post_struct' - - Inputs - ------ - inputspec.template_file : - inputspec.unwarped_brain : - inputspec.warp_field : - inputspec.affine_transformation : - inputspec.out_fsl_file : - inputspec.moving_image : - inputspec.mean_func : - inputspec.use_nearest: - - Outputs - ------- - outputspec.warped_image : + images : list of filenames Returns ------- - workflow : post-structural normalization workflow + list : returns dimensions of input image list """ - #inputs to workflow - import nipype.interfaces.freesurfer as fs - import nipype.interfaces.ants as ants - import nipype.pipeline.engine as pe - import nipype.interfaces.utility as util - inputspec = pe.Node( - util.IdentityInterface( - fields=['template_file', 'unwarped_brain', 'warp_field', - 'affine_transformation', 'out_fsl_file', 'moving_image', - 'mean_func',"use_nearest"]), - name='inputspec') + import nibabel as nb - #makes fsl-style coregistration ANTS compatible - fsl_reg_2_itk = pe.Node( - c3.C3dAffineTool(fsl2ras=True, itk_transform=True), - name='fsl_reg_2_itk') - - #collects series of transformations to be applied to the moving images - collect_transforms = pe.Node( - util.Merge(3), - name='collect_transforms') - - #performs series of transformations on moving images - warp_images = pe.MapNode( - ants.WarpTimeSeriesImageMultiTransform(), - name='warp_images', - iterfield=['input_image', 'dimension']) + res = min(nb.load(images).get_header().get_zooms()) + return res - #collects workflow outputs - outputspec = pe.Node( - util.IdentityInterface( - fields=['warped_image']), - name='outputspec') - #initializes and connects workflow nodes - normalize_post_struct = pe.Workflow(name=name) - normalize_post_struct.connect([ - (inputspec, fsl_reg_2_itk, [('unwarped_brain', 'reference_file')]), - (inputspec, fsl_reg_2_itk, [('out_fsl_file', 'transform_file')]), - (inputspec, fsl_reg_2_itk, [('mean_func', 'source_file')]), - (fsl_reg_2_itk, collect_transforms, [('itk_transform', 'in3')]), - (inputspec, collect_transforms, [('warp_field', 'in1'), - ('affine_transformation', 'in2')]), - (inputspec, warp_images, [('moving_image', 'input_image')]), - (inputspec, warp_images, [(('moving_image', get_image_dimensions), - 'dimension')]), - (inputspec, warp_images, [('template_file', 'reference_image'),('use_nearest','use_nearest')]), - (collect_transforms, warp_images, [('out', - 'transformation_series')]), - (warp_images, outputspec, [('output_image', 'warped_image')])]) - - return normalize_post_struct - - -def get_post_struct_norm_WIMT_workflow(name='normalize_post_struct'): +def get_post_struct_norm_workflow(name='normalize_post_struct', timeseries=True, original_res=True): """ Base post-structural workflow for normalization Parameters @@ -202,7 +138,6 @@ def get_post_struct_norm_WIMT_workflow(name='normalize_post_struct'): workflow : post-structural normalization workflow """ #inputs to workflow - import nipype.interfaces.freesurfer as fs import nipype.interfaces.ants as ants import nipype.pipeline.engine as pe import nipype.interfaces.utility as util @@ -224,10 +159,14 @@ def get_post_struct_norm_WIMT_workflow(name='normalize_post_struct'): name='collect_transforms') #performs series of transformations on moving images - warp_images = pe.MapNode( - ants.WarpImageMultiTransform(), - name='warp_images', - iterfield=['input_image', 'dimension']) + if timeseries: + warp_images = pe.MapNode(ants.WarpTimeSeriesImageMultiTransform(), + name='warp_images', + iterfield=['input_image', 'dimension']) + else: + warp_images = pe.MapNode(ants.WarpImageMultiTransform(), + name='warp_images', + iterfield=['input_image', 'dimension']) #collects workflow outputs outputspec = pe.Node( @@ -243,14 +182,27 @@ def get_post_struct_norm_WIMT_workflow(name='normalize_post_struct'): (inputspec, fsl_reg_2_itk, [('mean_func', 'source_file')]), (fsl_reg_2_itk, collect_transforms, [('itk_transform', 'in3')]), (inputspec, collect_transforms, [('warp_field', 'in1'), - ('affine_transformation', 'in2')]), + ('affine_transformation', 'in2')]), (inputspec, warp_images, [('moving_image', 'input_image')]), (inputspec, warp_images, [(('moving_image', get_image_dimensions), - 'dimension')]), - (inputspec, warp_images, [('template_file', 'reference_image'),('use_nearest','use_nearest')]), + 'dimension')]), + (inputspec, warp_images, [('use_nearest','use_nearest')]), (collect_transforms, warp_images, [('out', - 'transformation_series')]), + 'transformation_series')]), (warp_images, outputspec, [('output_image', 'warped_image')])]) + + if original_res: + reslice_atlas = pe.Node(fsl.FLIRT(), name="reslice_atlas") + + normalize_post_struct.connect([ + (inputspec, reslice_atlas, [('template_file', 'reference'), + ('template_file', 'in_file'), + (('mean_func', get_highest_resolution), + 'apply_isoxfm')]), + (reslice_atlas, warp_images, [('out_file', 'reference_image')])]) + else: + normalize_post_struct.connect([ + (inputspec, warp_images, [('template_file', 'reference_image')])]) return normalize_post_struct diff --git a/bips/workflows/gablab/wips/smri/normalize_functionals.py b/bips/workflows/gablab/wips/smri/normalize_functionals.py index fda91ed..33a22a0 100644 --- a/bips/workflows/gablab/wips/smri/normalize_functionals.py +++ b/bips/workflows/gablab/wips/smri/normalize_functionals.py @@ -1,5 +1,5 @@ import os -from ..scripts.smri_base import get_post_struct_norm_workflow, get_post_struct_norm_WIMT_workflow +from ..scripts.smri_base import get_post_struct_norm_workflow from ..scripts.smri_utils import warp_segments from ....base import MetaWorkflow, load_config, register_workflow from traits.api import HasTraits, Directory, Bool, Button @@ -42,7 +42,9 @@ class config(BaseWorkflowConfig): do_segment = traits.Bool(True) surf_dir = traits.Directory() moving_images_4D = traits.Bool(True, usedefault=True, desc="True if your moving image inputs \ - are time series images, False if they are 3-dimensional") +are time series images, False if they are 3-dimensional") + original_res = traits.Bool(True, usedefault=True, desc="Keep the original resolution of the normalized files. \ +Helps to save space. Note that isotropic resolution will be used (for example 3x3x4 will be resliced to 3x3x3).") # Advanced Options use_advanced_options = traits.Bool() advanced_script = traits.Code() @@ -132,6 +134,7 @@ def create_view(): Item(name="do_segment"),Item("use_nearest"), Item(name="surf_dir", enabled_when="do_segment"), Item(name="moving_images_4D"), + Item(name="original_res"), label='Normalization', show_border=True), Group(Item(name='use_advanced_options'), Item(name='advanced_script',enabled_when='use_advanced_options'), @@ -194,10 +197,8 @@ def normalize_workflow(c): import nipype.pipeline.engine as pe import nipype.interfaces.io as nio - if c.moving_images_4D: - norm = get_post_struct_norm_workflow() - else: - norm = get_post_struct_norm_WIMT_workflow() + norm = get_post_struct_norm_workflow(timeseries = c.moving_images_4D, + original_res = c.original_res) datagrab = c.datagrabber.create_dataflow() #func_datagrabber(c) #fssource = pe.Node(interface=FreeSurferSource(), name='fssource')