Skip to content
This repository was archived by the owner on Nov 10, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 35 additions & 83 deletions bips/workflows/gablab/wips/scripts/smri_base.py
Original file line number Diff line number Diff line change
@@ -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'):
Expand Down Expand Up @@ -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')

#makes fsl-style coregistration ANTS compatible
fsl_reg_2_itk = pe.Node(
c3.C3dAffineTool(fsl2ras=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')
import nibabel as nb

#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
Expand All @@ -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
Expand All @@ -215,7 +150,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
Expand All @@ -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(
Expand All @@ -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

Expand Down
13 changes: 7 additions & 6 deletions bips/workflows/gablab/wips/smri/normalize_functionals.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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'),
Expand Down Expand Up @@ -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')
Expand Down