Skip to content

Commit 3013a06

Browse files
authored
Merge pull request #1331 from FCP-INDI/develop
Merge 1.7.0-development branch into Master
2 parents ce26ba9 + 5d712c6 commit 3013a06

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+11534
-2227
lines changed

.circleci/config.yml

Lines changed: 84 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,93 @@
11
version: 2
22
jobs:
3-
pytest:
4-
docker:
5-
- image: fcpindi/c-pac:python3
3+
pytest-docker:
4+
machine: true
65
steps:
7-
- checkout
6+
- attach_workspace:
7+
# Must be absolute path or relative path from working_directory
8+
at: /home/circleci/
9+
- run:
10+
name: "Set Python Version"
11+
command: |
12+
pyenv install 3.6.3
13+
pyenv global 3.6.3
814
- run:
915
name: Get Sample BIDS Data
1016
command: git clone https://github.com/bids-standard/bids-examples.git
1117
- run:
1218
name: pytest
1319
command: |
14-
pip install -r dev/circleci_data/requirements.txt
15-
coverage run -m pytest --junitxml=test-results/junit.xml --doctest-ignore-import-errors --continue-on-collection-errors --doctest-modules --ignore=CPAC/cwas/tests/test_mdmr_cython.py dev/circleci_data/
16-
coverage report --include="./*" --omit="/home/circleci/.local/*"
17-
coverage html
20+
docker load < cpac-docker-image.tar.gz
21+
docker run -dit -P -v /home/circleci/project/test-results:/code/test-results -v /home/circleci/project/htmlcov:/code/htmlcov --entrypoint=/bin/bash --name docker_test fcpindi/c-pac:${CIRCLE_BRANCH//\//_}
22+
docker exec docker_test /bin/bash ./code/dev/circleci_data/test_in_image.sh
1823
- store_test_results:
1924
path: test-results
2025
- store_artifacts:
2126
path: test-results
2227
- store_artifacts:
2328
path: htmlcov
29+
no_output_timeout: 5h
30+
pytest-singularity:
31+
machine: true
32+
steps:
33+
- attach_workspace:
34+
# Must be absolute path or relative path from working_directory
35+
at: /home/circleci/
36+
- run:
37+
name: "Set Python Version"
38+
command: |
39+
pyenv install 3.6.3
40+
pyenv global 3.6.3
41+
- run:
42+
name: test_install
43+
command: |
44+
sudo apt-get update && sudo apt-get install flawfinder squashfs-tools uuid-dev libuuid1 libffi-dev libssl-dev libssl1.0.0 libarchive-dev libgpgme11-dev libseccomp-dev -y
45+
cd singularity
46+
./autogen.sh
47+
./configure --prefix=/usr/local --sysconfdir=/etc
48+
make
49+
sudo make install
50+
cd ..
51+
pip install -r dev/circleci_data/requirements.txt
52+
coverage run -m pytest --junitxml=test-results/junit.xml --continue-on-collection-errors dev/circleci_data/test_install.py
2453
build:
2554
machine: true
2655
steps:
2756
- checkout
2857
- run:
29-
name: build
58+
name: "Set Python Version"
59+
command: |
60+
pyenv install 3.6.3
61+
pyenv global 3.6.3
62+
- run:
63+
name: build-docker
3064
command: |
31-
docker build -t cpac:${CIRCLE_BRANCH//\//_} .
32-
docker save cpac:${CIRCLE_BRANCH//\//_} | gzip > cpac-docker-image.tar.gz
65+
docker build -t fcpindi/c-pac:${CIRCLE_BRANCH//\//_} .
66+
docker save fcpindi/c-pac:${CIRCLE_BRANCH//\//_} | gzip > cpac-docker-image.tar.gz
3367
# Persist the specified paths (workspace/echo-output) into the workspace for use in downstream job.
68+
- run:
69+
name: local-registry
70+
command: docker run -d -p 5000:5000 --restart=always --name registry registry:2
71+
- run:
72+
name: build-singularity
73+
command: |
74+
sudo apt-get update && sudo apt-get install flawfinder squashfs-tools uuid-dev libuuid1 libffi-dev libssl-dev libssl1.0.0 libarchive-dev libgpgme11-dev libseccomp-dev -y
75+
git clone -b 2.5.2 https://github.com/sylabs/singularity
76+
cd singularity
77+
./autogen.sh
78+
./configure --prefix=/usr/local --sysconfdir=/etc
79+
make
80+
sudo make install
81+
cd ..
82+
docker load < cpac-docker-image.tar.gz
83+
docker tag fcpindi/c-pac:${CIRCLE_BRANCH//\//_} localhost:5000/fcpindi/c-pac:${CIRCLE_BRANCH//\//_}
84+
docker push localhost:5000/fcpindi/c-pac:${CIRCLE_BRANCH//\//_}
85+
SINGULARITY_NOHTTPS=1 singularity build C-PAC-CI.simg docker://localhost:5000/fcpindi/c-pac:${CIRCLE_BRANCH//\//_}
86+
- store_artifacts:
87+
path: cpac-docker-image.tar.gz
88+
- store_artifacts:
89+
path: C-PAC-CI.simg
90+
destination: cpac-singularity-image.simg
3491
- persist_to_workspace:
3592
# Must be an absolute path, or relative path from working_directory. This is a directory on the container which is
3693
# taken to be the root directory of the workspace.
@@ -43,6 +100,11 @@ jobs:
43100
- attach_workspace:
44101
# Must be absolute path or relative path from working_directory
45102
at: /home/circleci/
103+
- run:
104+
name: "Set Python Version"
105+
command: |
106+
pyenv install 3.6.3
107+
pyenv global 3.6.3
46108
- run:
47109
name:
48110
command: python dev/circleci_data/scripts/compare.py
@@ -52,6 +114,11 @@ jobs:
52114
- attach_workspace:
53115
# Must be absolute path or relative path from working_directory
54116
at: /home/circleci/
117+
- run:
118+
name: "Set Python Version"
119+
command: |
120+
pyenv install 3.6.3
121+
pyenv global 3.6.3
55122
- run:
56123
name: Run C-PAC
57124
command: |
@@ -84,6 +151,9 @@ workflows:
84151
filters:
85152
branches:
86153
only: feature/auto-heatmaps
87-
unit_tests:
88-
jobs:
89-
- pytest
154+
- pytest-docker:
155+
requires:
156+
- build
157+
- pytest-singularity:
158+
requires:
159+
- build

CPAC/anat_preproc/anat_preproc.py

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# -*- coding: utf-8 -*-
2+
import os
23
from nipype.interfaces import afni
34
from nipype.interfaces import ants
45
from nipype.interfaces import fsl
@@ -9,6 +10,23 @@
910
from CPAC.utils.datasource import create_check_for_s3_node
1011
from CPAC.unet.function import predict_volumes
1112

13+
def patch_cmass_output(lst, index=0):
14+
"""
15+
Parameters
16+
----------
17+
lst : list of tuples
18+
output of afni.CenterMass()
19+
index : int
20+
index in the list of tuples
21+
22+
Returns
23+
-------
24+
tuple
25+
one set of center of mass coordinates
26+
"""
27+
if len(lst) <= index:
28+
raise IndexError("lst index out of range")
29+
return lst[index]
1230

1331
def create_anat_preproc(method='afni', already_skullstripped=False, config=None, wf_name='anat_preproc'):
1432
"""The main purpose of this workflow is to process T1 scans. Raw mprage file is deobliqued, reoriented
@@ -82,15 +100,20 @@ def create_anat_preproc(method='afni', already_skullstripped=False, config=None,
82100

83101
preproc = pe.Workflow(name=wf_name)
84102

85-
inputnode = pe.Node(util.IdentityInterface(
86-
fields=['anat', 'brain_mask']), name='inputspec')
103+
inputnode = pe.Node(util.IdentityInterface(fields=['anat',
104+
'brain_mask',
105+
'template_brain_only_for_anat',
106+
'template_skull_for_anat',
107+
'template_cmass']),
108+
name='inputspec')
87109

88110
outputnode = pe.Node(util.IdentityInterface(fields=['refit',
89111
'reorient',
90112
'skullstrip',
91113
'brain',
92-
'brain_mask']),
93-
name='outputspec')
114+
'brain_mask',
115+
'center_of_mass']),
116+
name='outputspec')
94117

95118
anat_deoblique = pe.Node(interface=afni.Refit(),
96119
name='anat_deoblique')
@@ -241,6 +264,7 @@ def create_anat_preproc(method='afni', already_skullstripped=False, config=None,
241264

242265
preproc.connect(anat_reorient, 'out_file',
243266
anat_skullstrip, 'in_file')
267+
244268
preproc.connect(skullstrip_args, 'expr',
245269
anat_skullstrip, 'args')
246270

@@ -295,7 +319,7 @@ def create_anat_preproc(method='afni', already_skullstripped=False, config=None,
295319
anat_skullstrip = pe.Node(
296320
interface=fsl.BET(), name='anat_skullstrip')
297321
anat_skullstrip.inputs.output_type = 'NIFTI_GZ'
298-
322+
299323
preproc.connect(anat_reorient, 'out_file',
300324
anat_skullstrip, 'in_file')
301325

@@ -422,29 +446,28 @@ def create_anat_preproc(method='afni', already_skullstripped=False, config=None,
422446
# flirt -v -dof 6 -in brain.nii.gz -ref NMT_SS_0.5mm.nii.gz -o brain_rot2atl -omat brain_rot2atl.mat -interp sinc
423447
# TODO: antsRegistration -z 0 -d 3 -r [NMT_SS_0.5mm.nii.gz,brain.nii.gz,0] -o [transform,brain_rot2atl.nii.gz,brain_inv_rot2atl.nii.gz] -t Rigid[0.1] -m MI[NMT_SS_0.5mm.nii.gz,brain.nii.gz,1,32,Regular,0.25] -c [1000x500x250x100,1e-08,10] -s 3.0x2.0x1.0x0.0 -f 8x4x2x1 -u 1 -t Affine[0.1] -m MI[NMT_SS_0.5mm.nii.gz,brain.nii.gz,1,32,Regular,0.25] -c [1000x500x250x100,1e-08,10] -s 3.0x2.0x1.0x0.0 -f 8x4x2x1 -u 1
424448
native_brain_to_template_brain = pe.Node(interface=fsl.FLIRT(), name='native_brain_to_template_brain')
425-
native_brain_to_template_brain.inputs.reference = config.template_brain_only_for_anat
426449
native_brain_to_template_brain.inputs.dof = 6
427450
native_brain_to_template_brain.inputs.interp = 'sinc'
428451
preproc.connect(unet_masked_brain, 'out_file', native_brain_to_template_brain, 'in_file')
452+
preproc.connect(inputnode, 'template_brain_only_for_anat', native_brain_to_template_brain, 'reference')
429453

430454
# flirt -in head.nii.gz -ref NMT_0.5mm.nii.gz -o head_rot2atl -applyxfm -init brain_rot2atl.mat
431455
# TODO: antsApplyTransforms -d 3 -i head.nii.gz -r NMT_0.5mm.nii.gz -n Linear -o head_rot2atl.nii.gz -v -t transform1Rigid.mat -t transform2Affine.mat -t transform0DerivedInitialMovingTranslation.mat
432456
native_head_to_template_head = pe.Node(interface=fsl.FLIRT(), name='native_head_to_template_head')
433-
native_head_to_template_head.inputs.reference = config.template_skull_for_anat
434457
native_head_to_template_head.inputs.apply_xfm = True
435458
preproc.connect(anat_reorient, 'out_file', native_head_to_template_head, 'in_file')
436459
preproc.connect(native_brain_to_template_brain, 'out_matrix_file', native_head_to_template_head, 'in_matrix_file')
437-
460+
preproc.connect(inputnode, 'template_skull_for_anat', native_head_to_template_head, 'reference')
461+
438462
# fslmaths NMT_SS_0.5mm.nii.gz -bin templateMask.nii.gz
439463
template_brain_mask = pe.Node(interface=fsl.maths.MathsCommand(), name='template_brain_mask')
440-
template_brain_mask.inputs.in_file = config.template_brain_only_for_anat
441464
template_brain_mask.inputs.args = '-bin'
465+
preproc.connect(inputnode, 'template_brain_only_for_anat', template_brain_mask, 'in_file')
442466

443467
# ANTS 3 -m CC[head_rot2atl.nii.gz,NMT_0.5mm.nii.gz,1,5] -t SyN[0.25] -r Gauss[3,0] -o atl2T1rot -i 60x50x20 --use-Histogram-Matching --number-of-affine-iterations 10000x10000x10000x10000x10000 --MI-option 32x16000
444468
ants_template_head_to_template = pe.Node(interface=ants.Registration(), name='template_head_to_template')
445469
ants_template_head_to_template.inputs.metric = ['CC']
446470
ants_template_head_to_template.inputs.metric_weight = [1,5]
447-
ants_template_head_to_template.inputs.moving_image = config.template_skull_for_anat
448471
ants_template_head_to_template.inputs.transforms = ['SyN']
449472
ants_template_head_to_template.inputs.transform_parameters = [(0.25,)]
450473
ants_template_head_to_template.inputs.interpolation = 'NearestNeighbor'
@@ -453,7 +476,7 @@ def create_anat_preproc(method='afni', already_skullstripped=False, config=None,
453476
ants_template_head_to_template.inputs.shrink_factors = [[4,2,1]]
454477
ants_template_head_to_template.inputs.convergence_threshold = [1.e-8]
455478
preproc.connect(native_head_to_template_head, 'out_file', ants_template_head_to_template, 'fixed_image')
456-
479+
preproc.connect(inputnode, 'template_skull_for_anat', ants_template_head_to_template, 'moving_image')
457480
# antsApplyTransforms -d 3 -i templateMask.nii.gz -t atl2T1rotWarp.nii.gz atl2T1rotAffine.txt -r brain_rot2atl.nii.gz -o brain_rot2atl_mask.nii.gz
458481
template_head_transform_to_template = pe.Node(interface=ants.ApplyTransforms(), name='template_head_transform_to_template')
459482
template_head_transform_to_template.inputs.dimension = 3
@@ -491,3 +514,4 @@ def create_anat_preproc(method='afni', already_skullstripped=False, config=None,
491514
preproc.connect(refined_brain, 'out_file', outputnode, 'brain')
492515

493516
return preproc
517+

0 commit comments

Comments
 (0)