Skip to content

Commit

Permalink
Fix spm native (#231)
Browse files Browse the repository at this point in the history
* real segment in native space , mesh IsoSurface + prerelease is like release except for pip install

* flake8
  • Loading branch information
davidmeunier79 authored Nov 17, 2023
1 parent 0da0d99 commit c623dc5
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 98 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build_on_prerelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,15 @@ jobs:
- name: Running test pipeline macaque_prime-de
run: |
docker run -i -v /home/ubuntu/actions-runner/_work/macapype/macapype/${{ matrix.soft }}/macapype_CI:/data macatools/macapype:latest segment_pnh -data /data/macaque_prime-de/ -out /data/macaque_prime-de/results -soft ${{ matrix.soft }}_prep -species macaque -sub 032140 -ses 001 -deriv -pad
docker run -i -v /home/ubuntu/actions-runner/_work/macapype/macapype/${{ matrix.soft }}/macapype_CI:/data macatools/macapype:latest segment_pnh -data /data/macaque_prime-de/ -out /data/macaque_prime-de/results -soft ${{ matrix.soft }} -species macaque -sub 032140 -ses 001 -deriv -pad
- name: Running test pipeline marmo-marmobrain
run: |
docker run -i -v /home/ubuntu/actions-runner/_work/macapype/macapype/${{ matrix.soft }}/macapype_CI:/data macatools/macapype:latest segment_pnh -data /data/marmo-marmobrain -out /data/marmo-marmobrain/results -soft ${{ matrix.soft }}_prep -species marmo -sub Percy -ses 01 -deriv -pad
docker run -i -v /home/ubuntu/actions-runner/_work/macapype/macapype/${{ matrix.soft }}/macapype_CI:/data macatools/macapype:latest segment_pnh -data /data/marmo-marmobrain -out /data/marmo-marmobrain/results -soft ${{ matrix.soft }} -species marmo -sub Percy -ses 01 -deriv -pad
- name: Running test pipeline baboon-cerimed-adrien
run: |
docker run -i -v /home/ubuntu/actions-runner/_work/macapype/macapype/${{ matrix.soft }}/macapype_CI:/data macatools/macapype:latest segment_pnh -data /data/baboon-cerimed-adrien -out /data/baboon-cerimed-adrien/results -soft ${{ matrix.soft }}_prep -species baboon -sub Fidji -ses 01 -deriv -pad
docker run -i -v /home/ubuntu/actions-runner/_work/macapype/macapype/${{ matrix.soft }}/macapype_CI:/data macatools/macapype:latest segment_pnh -data /data/baboon-cerimed-adrien -out /data/baboon-cerimed-adrien/results -soft ${{ matrix.soft }} -species baboon -sub Fidji -ses 01 -deriv -pad
- name: Cleaning dataset
run:
Expand Down
20 changes: 0 additions & 20 deletions macapype/nodes/surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,26 +119,6 @@ def wrap_nii2mesh(nii_file):
assert ret == 0, "Error, cmd {} did not work".format(cmd)
return stl_file

def wrap_afni_IsoSurface (nii_file):

import os
from nipype.utils.filemanip import split_filename as split_f

path, fname, ext = split_f(nii_file)

stl_file = os.path.abspath(fname + ".stl")

isoval=1
cmd = "IsoSurface -isoval {} -input {} -Tsmooth 0.1 100 -remesh 0.5 -overwrite -autocrop -o {}".format(
isoval, nii_file, stl_file)

ret = os.system(cmd)

print(ret)

assert ret == 0, "Error, cmd {} did not work".format(cmd)
return stl_file


# ### wrapping afni IsoSurface
def wrap_afni_IsoSurface(nii_file):
Expand Down
67 changes: 66 additions & 1 deletion macapype/pipelines/full_pipelines.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
create_extract_T1_pipe)

from .surface import (create_nii_to_mesh_pipe, create_nii_to_mesh_fs_pipe,
create_nii2mesh_brain_pipe)
create_nii2mesh_brain_pipe, create_IsoSurface_brain_pipe)

from macapype.utils.misc import parse_key, list_input_files, show_files

Expand Down Expand Up @@ -2628,6 +2628,38 @@ def create_full_ants_subpipes(

seg_pipe.connect(nii2mesh_brain_pipe, "outputnode.wmgm_nii",
outputnode, 'wmgm_mask')
elif "IsoSurface_brain_pipe" in params.keys():

IsoSurface_brain_pipe = create_IsoSurface_brain_pipe(
params=parse_key(params["brain_segment_pipe"],
"IsoSurface_brain_pipe"))

if pad:
if "native_to_stereo_pipe" in params.keys():

seg_pipe.connect(apply_stereo_seg_mask, "out_file",
IsoSurface_brain_pipe,
'inputnode.segmented_file')

seg_pipe.connect(IsoSurface_brain_pipe, "outputnode.wmgm_stl",
outputnode, 'stereo_wmgm_stl')

seg_pipe.connect(IsoSurface_brain_pipe, "outputnode.wmgm_nii",
outputnode, 'stereo_wmgm_mask')

elif space == "native":
seg_pipe.connect(pad_seg_mask, "out_file",
IsoSurface_brain_pipe,
'inputnode.segmented_file')
else:
seg_pipe.connect(brain_segment_pipe, "outputnode.segmented_file",
IsoSurface_brain_pipe, 'inputnode.segmented_file')

seg_pipe.connect(IsoSurface_brain_pipe, "outputnode.wmgm_stl",
outputnode, 'wmgm_stl')

seg_pipe.connect(IsoSurface_brain_pipe, "outputnode.wmgm_nii",
outputnode, 'wmgm_mask')

elif 'nii_to_mesh_pipe' in params.keys():
# kept for compatibility but nii2mesh is prefered...
Expand Down Expand Up @@ -3811,4 +3843,37 @@ def create_full_T1_ants_subpipes(params_template, params_template_aladin,
seg_pipe.connect(nii2mesh_brain_pipe, "outputnode.wmgm_nii",
outputnode, 'wmgm_mask')

elif "IsoSurface_brain_pipe" in params["brain_segment_pipe"]:

IsoSurface_brain_pipe = create_IsoSurface_brain_pipe(
params=parse_key(params["brain_segment_pipe"],
"IsoSurface_brain_pipe"))

if pad:
if "native_to_stereo_pipe" in params.keys():

seg_pipe.connect(apply_stereo_seg_mask, "out_file",
IsoSurface_brain_pipe,
'inputnode.segmented_file')

seg_pipe.connect(IsoSurface_brain_pipe, "outputnode.wmgm_stl",
outputnode, 'stereo_wmgm_stl')

seg_pipe.connect(IsoSurface_brain_pipe, "outputnode.wmgm_nii",
outputnode, 'stereo_wmgm_mask')

elif space == "native":
seg_pipe.connect(pad_seg_mask, "out_file",
IsoSurface_brain_pipe,
'inputnode.segmented_file')
else:
seg_pipe.connect(brain_segment_pipe, "outputnode.segmented_file",
IsoSurface_brain_pipe, 'inputnode.segmented_file')

seg_pipe.connect(IsoSurface_brain_pipe, "outputnode.wmgm_stl",
outputnode, 'wmgm_stl')

seg_pipe.connect(IsoSurface_brain_pipe, "outputnode.wmgm_nii",
outputnode, 'wmgm_mask')

return seg_pipe
115 changes: 44 additions & 71 deletions macapype/pipelines/segment.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import nipype.interfaces.spm as spm

from ..nodes.segment import (AtroposN4, BinaryFillHoles, merge_masks,
from ..nodes.segment import (AtroposN4, merge_masks,
merge_imgs, split_indexed_mask, copy_header,
compute_5tt, fill_list_vol)

Expand Down Expand Up @@ -724,31 +724,12 @@ def create_native_old_segment_pipe(params_template, params={},
assert set_spm(), \
"Error, SPM was not found, cannot run SPM old segment pipeline"

unzip = pe.Node(
interface=niu.Function(input_names=['zipped_file'],
output_names=["unzipped_file"],
function=gunzip),
name="unzip")

seg_pipe.connect(inputnode, 'T1', unzip, 'zipped_file')

# Segment in to 6 tissues
segment = NodeParams(spm.Segment(),
params=parse_key(params, "segment"),
name="old_segment")

segment.inputs.tissue_prob_maps = [params_template["template_gm"],
params_template["template_wm"],
params_template["template_csf"]]

seg_pipe.connect(unzip, 'unzipped_file', segment, 'data')

# gm
register_gm_to_nat = pe.Node(fsl.ApplyXFM(), name="register_gm_to_nat")
register_gm_to_nat.inputs.output_type = "NIFTI_GZ" # for SPM segment
register_gm_to_nat.inputs.output_type = "NIFTI" # for SPM segment
register_gm_to_nat.inputs.interp = "nearestneighbour"

seg_pipe.connect(segment, 'native_gm_image',
register_gm_to_nat, 'in_file')
register_gm_to_nat.inputs.in_file = params_template["template_gm"]

seg_pipe.connect(inputnode, 'native_T1',
register_gm_to_nat, 'reference')
Expand All @@ -758,10 +739,10 @@ def create_native_old_segment_pipe(params_template, params={},

# wm
register_wm_to_nat = pe.Node(fsl.ApplyXFM(), name="register_wm_to_nat")
register_wm_to_nat.inputs.output_type = "NIFTI_GZ" # for SPM segment
register_wm_to_nat.inputs.output_type = "NIFTI" # for SPM segment
register_wm_to_nat.inputs.interp = "nearestneighbour"

seg_pipe.connect(segment, 'native_wm_image',
register_wm_to_nat, 'in_file')
register_wm_to_nat.inputs.in_file = params_template["template_wm"]

seg_pipe.connect(inputnode, 'native_T1',
register_wm_to_nat, 'reference')
Expand All @@ -771,23 +752,51 @@ def create_native_old_segment_pipe(params_template, params={},

# csf
register_csf_to_nat = pe.Node(fsl.ApplyXFM(), name="register_csf_to_nat")
register_csf_to_nat.inputs.output_type = "NIFTI_GZ" # for SPM segment
register_csf_to_nat.inputs.output_type = "NIFTI" # for SPM segment
register_csf_to_nat.inputs.interp = "nearestneighbour"

seg_pipe.connect(segment, 'native_csf_image',
register_csf_to_nat, 'in_file')
register_csf_to_nat.inputs.in_file = params_template["template_csf"]

seg_pipe.connect(inputnode, 'native_T1',
register_csf_to_nat, 'reference')

seg_pipe.connect(inputnode, 'inv_transfo_file',
register_csf_to_nat, "in_matrix_file")
# unzip T1
unzip = pe.Node(
interface=niu.Function(input_names=['zipped_file'],
output_names=["unzipped_file"],
function=gunzip),
name="unzip")

seg_pipe.connect(inputnode, 'T1', unzip, 'zipped_file')

# merge_tissue_files
merge_tissue_files = pe.Node(
interface=niu.Merge(3),
name="merge_tissue_files")

seg_pipe.connect(register_gm_to_nat, "out_file", merge_tissue_files, 'in1')
seg_pipe.connect(register_wm_to_nat, "out_file", merge_tissue_files, 'in2')
seg_pipe.connect(register_csf_to_nat, "out_file",
merge_tissue_files, 'in3')

# Segment in to 6 tissues
segment = NodeParams(spm.Segment(),
params=parse_key(params, "segment"),
name="old_segment")

seg_pipe.connect(merge_tissue_files, "out",
segment, "tissue_prob_maps")

seg_pipe.connect(unzip, 'unzipped_file', segment, 'data')

# threshold_gm
threshold_gm = NodeParams(fsl.Threshold(),
params=parse_key(params, "threshold_gm"),
name="threshold_gm")

seg_pipe.connect(register_gm_to_nat, 'out_file', threshold_gm, 'in_file')
seg_pipe.connect(segment, 'native_gm_image', threshold_gm, 'in_file')

seg_pipe.connect(
inputnode, ('indiv_params', parse_key, "threshold_gm"),
Expand All @@ -798,7 +807,7 @@ def create_native_old_segment_pipe(params_template, params={},
params=parse_key(params, "threshold_wm"),
name="threshold_wm")

seg_pipe.connect(register_wm_to_nat, 'out_file', threshold_wm, 'in_file')
seg_pipe.connect(segment, 'native_wm_image', threshold_wm, 'in_file')

seg_pipe.connect(
inputnode, ('indiv_params', parse_key, "threshold_wm"),
Expand All @@ -809,7 +818,7 @@ def create_native_old_segment_pipe(params_template, params={},
params=parse_key(params, "threshold_csf"),
name="threshold_csf")

seg_pipe.connect(register_csf_to_nat, 'out_file', threshold_csf, 'in_file')
seg_pipe.connect(segment, 'native_csf_image', threshold_csf, 'in_file')

seg_pipe.connect(
inputnode, ('indiv_params', parse_key, "threshold_csf"),
Expand All @@ -826,9 +835,9 @@ def create_native_old_segment_pipe(params_template, params={},
seg_pipe.connect(threshold_wm, 'out_file', outputnode, 'threshold_wm')
seg_pipe.connect(threshold_csf, 'out_file', outputnode, 'threshold_csf')

seg_pipe.connect(register_gm_to_nat, 'out_file', outputnode, 'prob_gm')
seg_pipe.connect(register_wm_to_nat, 'out_file', outputnode, 'prob_wm')
seg_pipe.connect(register_csf_to_nat, 'out_file', outputnode, 'prob_csf')
seg_pipe.connect(segment, 'native_gm_image', outputnode, 'prob_gm')
seg_pipe.connect(segment, 'native_wm_image', outputnode, 'prob_wm')
seg_pipe.connect(segment, 'native_csf_image', outputnode, 'prob_csf')

return seg_pipe

Expand Down Expand Up @@ -892,42 +901,6 @@ def create_mask_from_seg_pipe(params={}, name="mask_from_seg_pipe"):
seg_pipe.connect(inputnode, 'mask_wm',
bin_wm, 'in_file')

# Compute union of the 3 tissues
# Done with 2 fslmaths as it seems to hard to do it
wmgm_union = pe.Node(fsl.BinaryMaths(), name="wmgm_union")
wmgm_union.inputs.operation = "add"
seg_pipe.connect(bin_gm, 'out_file', wmgm_union, 'in_file')
seg_pipe.connect(bin_wm, 'out_file', wmgm_union, 'operand_file')

tissues_union = pe.Node(fsl.BinaryMaths(), name="tissues_union")
tissues_union.inputs.operation = "add"
seg_pipe.connect(wmgm_union, 'out_file', tissues_union, 'in_file')
seg_pipe.connect(bin_csf, 'out_file',
tissues_union, 'operand_file')

# Opening (dilating) mask
dilate_mask = NodeParams(fsl.DilateImage(),
params=parse_key(params, "dilate_mask"),
name="dilate_mask")

dilate_mask.inputs.operation = "mean" # Arbitrary operation
seg_pipe.connect(tissues_union, 'out_file', dilate_mask, 'in_file')

# fill holes of dilate_mask
fill_holes_dil = pe.Node(BinaryFillHoles(), name="fill_holes_dil")
seg_pipe.connect(dilate_mask, 'out_file', fill_holes_dil, 'in_file')

# Eroding mask
erode_mask = NodeParams(fsl.ErodeImage(),
params=parse_key(params, "erode_mask"),
name="erode_mask")

seg_pipe.connect(tissues_union, 'out_file', erode_mask, 'in_file')

# fill holes of erode_mask
fill_holes = pe.Node(BinaryFillHoles(), name="fill_holes")
seg_pipe.connect(erode_mask, 'out_file', fill_holes, 'in_file')

# merge to index
merge_indexed_mask = NodeParams(
interface=niu.Function(input_names=["mask_csf_file", "mask_wm_file",
Expand Down
55 changes: 54 additions & 1 deletion macapype/pipelines/surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
import macapype.nodes.register as reg

from macapype.nodes.surface import (Meshify, split_LR_mask,
wrap_nii2mesh, merge_tissues)
wrap_nii2mesh,
wrap_afni_IsoSurface, merge_tissues)

from macapype.utils.utils_nodes import parse_key, NodeParams

Expand Down Expand Up @@ -683,3 +684,55 @@ def create_nii2mesh_brain_pipe(params={},
nii2mesh_brain_pipe.connect(wmgm2mesh, 'stl_file', outputnode, "wmgm_stl")

return nii2mesh_brain_pipe


def create_IsoSurface_brain_pipe(params={},
name="IsoSurface_brain_pipe"):

# creating pipeline
IsoSurface_brain_pipe = pe.Workflow(name=name)

# creating inputnode
inputnode = pe.Node(
niu.IdentityInterface(
fields=["segmented_file"]),
name='inputnode')

# merge_brain_tissues
merge_brain_tissues = NodeParams(
interface=niu.Function(input_names=["dseg_file", "keep_indexes"],
output_names=["mask_file"],
function=merge_tissues),
params=parse_key(params, "merge_brain_tissues"),
name="keep_GCC_brain")

IsoSurface_brain_pipe.connect(inputnode, 'segmented_file',
merge_brain_tissues, 'dseg_file')

# bin mask
bin_mask = pe.Node(interface=fsl.UnaryMaths(), name="bin_mask")
bin_mask.inputs.operation = "bin"

IsoSurface_brain_pipe.connect(merge_brain_tissues,
'mask_file', bin_mask, 'in_file')

# wmgm2mesh
wmgm2mesh = pe.Node(
interface=niu.Function(input_names=["nii_file"],
output_names=["stl_file"],
function=wrap_afni_IsoSurface),
name="wmgm2mesh")

IsoSurface_brain_pipe.connect(bin_mask, 'out_file', wmgm2mesh, "nii_file")

# outputnode
outputnode = pe.Node(
niu.IdentityInterface(
fields=["wmgm_stl", "wmgm_nii"]),
name='outputnode')

IsoSurface_brain_pipe.connect(bin_mask, 'out_file', outputnode, "wmgm_nii")
IsoSurface_brain_pipe.connect(wmgm2mesh, 'stl_file',
outputnode, "wmgm_stl")

return IsoSurface_brain_pipe
2 changes: 1 addition & 1 deletion workflows/params_segment_macaque_ants.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
"export_5tt_pipe":
{
},
"nii2mesh_brain_pipe":
"IsoSurface_brain_pipe":
{
"merge_brain_tissues":
{
Expand Down
Loading

0 comments on commit c623dc5

Please sign in to comment.