Skip to content

Commit a221f1b

Browse files
committed
Merge branch 'master' of https://github.com/nipy/nipype into enh/workbench
2 parents ada6e30 + 9eaa2a3 commit a221f1b

File tree

9 files changed

+244
-27
lines changed

9 files changed

+244
-27
lines changed

.circleci/config.yml

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ _build_main_image_py36: &build_main_image_py36
5454
--tag nipype/nipype:py36 \
5555
--build-arg BUILD_DATE="$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
5656
--build-arg VCS_REF="$(git rev-parse --short HEAD)" \
57-
--build-arg VERSION="${CIRCLE_TAG}" /home/circleci/nipype \
57+
--build-arg VERSION="${CIRCLE_TAG}" /home/circleci/nipype
5858
5959
_build_main_image_py27: &build_main_image_py27
6060
name: Build main image (py27)
@@ -68,7 +68,7 @@ _build_main_image_py27: &build_main_image_py27
6868
--build-arg PYTHON_VERSION_MINOR=7 \
6969
--build-arg BUILD_DATE="$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
7070
--build-arg VCS_REF="$(git rev-parse --short HEAD)" \
71-
--build-arg VERSION="${CIRCLE_TAG}-py27" /home/circleci/nipype \
71+
--build-arg VERSION="${CIRCLE_TAG}-py27" /home/circleci/nipype
7272
7373
_download_test_data: &_download_test_data
7474
name: Download test data
@@ -299,7 +299,7 @@ jobs:
299299
- run: *_run_codecov_smoke
300300
- store_artifacts: *store_artifacts_kwds
301301

302-
deploy:
302+
deploy_dockerhub:
303303
docker:
304304
- image: docker:17.10.0-ce-git
305305
steps:
@@ -330,6 +330,18 @@ jobs:
330330
- /tmp/docker/cache/Dockerfile.base-pruned
331331
key: dockerfile-cache-v1-{{ .Branch }}-{{ checksum "/tmp/docker/cache/Dockerfile.base-pruned" }}
332332

333+
deploy_pypi:
334+
machine: *machine_kwds
335+
working_directory: /home/circleci/nipype
336+
steps:
337+
- checkout:
338+
path: /home/circleci/nipype
339+
- run:
340+
name: Deploy to PyPI
341+
command: |
342+
pip install twine future wheel
343+
python setup.py sdist bdist_wheel
344+
twine upload dist/*
333345
334346
workflows:
335347
version: 2
@@ -348,7 +360,7 @@ workflows:
348360
- test_fmri_spm_nested_fsl_feeds:
349361
requires:
350362
- compare_base_dockerfiles
351-
- deploy:
363+
- deploy_dockerhub:
352364
filters:
353365
branches:
354366
only: master
@@ -357,3 +369,14 @@ workflows:
357369
- test_fmri_spm_nested_fsl_feeds
358370
- test_py3_fmri_fsl_spm
359371
- test_py3_fmri_spm_dartel_multiproc
372+
- deploy_pypi:
373+
filters:
374+
branches:
375+
ignore: /.*/
376+
tags:
377+
only: /.*/
378+
requires:
379+
- test_pytest
380+
- test_fmri_spm_nested_fsl_feeds
381+
- test_py3_fmri_fsl_spm
382+
- test_py3_fmri_spm_dartel_multiproc

.travis.yml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,5 @@ install:
6060
script:
6161
- py.test -v --cov nipype --cov-config .coveragerc --cov-report xml:cov.xml -c nipype/pytest.ini --doctest-modules nipype
6262

63-
deploy:
64-
provider: pypi
65-
user: satra
66-
password:
67-
secure: OCO0FXb4f+pH4Uw7zWCIRp3qOJ1t7rhky4K8MjNU8tyVCJgd6O/Bv8GJgceS0LktPodlAAjB8SxAhTORPAQZ1D/44PJYy3NQIisvej1zjLpaA9TEGfl6W7MqhDpRyMHW+cnSi/n84SAmdr+Z4vOxScDHdwr13EPmGyOIlHMAGnE=
68-
on:
69-
tags: true
70-
repo: nipy/nipype
71-
branch: master
72-
distributions: "sdist bdist_wheel"
73-
7463
after_script:
7564
- codecov --file cov.xml --flags unittests -e TRAVIS_JOB_NUMBER

nipype/interfaces/afni/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from .utils import (
1919
ABoverlap, AFNItoNIFTI, Autobox, Axialize, BrickStat, Bucket, Calc, Cat,
2020
CatMatvec, CenterMass, ConvertDset, Copy, Dot, Edge3, Eval, FWHMx,
21-
MaskTool, Merge, Notes, NwarpApply, NwarpAdjust, NwarpCat, OneDToolPy,
22-
Refit, Resample, TCat, TCatSubBrick, TStat, To3D, Unifize, Undump, ZCutUp,
23-
GCOR, Zcat, Zeropad)
21+
LocalBistat, MaskTool, Merge, Notes, NwarpApply, NwarpAdjust, NwarpCat,
22+
OneDToolPy, Refit, Resample, TCat, TCatSubBrick, TStat, To3D, Unifize,
23+
Undump, ZCutUp, GCOR, Zcat, Zeropad)
2424
from .model import (Deconvolve, Remlfit, Synthesize)
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from __future__ import unicode_literals
3+
from ..utils import LocalBistat
4+
5+
6+
def test_LocalBistat_inputs():
7+
input_map = dict(
8+
args=dict(argstr='%s', ),
9+
automask=dict(
10+
argstr='-automask',
11+
xor=['weight_file'],
12+
),
13+
environ=dict(
14+
nohash=True,
15+
usedefault=True,
16+
),
17+
ignore_exception=dict(
18+
deprecated='1.0.0',
19+
nohash=True,
20+
usedefault=True,
21+
),
22+
in_file1=dict(
23+
argstr='%s',
24+
mandatory=True,
25+
position=-2,
26+
),
27+
in_file2=dict(
28+
argstr='%s',
29+
mandatory=True,
30+
position=-1,
31+
),
32+
mask_file=dict(argstr='-mask %s', ),
33+
neighborhood=dict(
34+
argstr="-nbhd '%s(%s)'",
35+
mandatory=True,
36+
),
37+
num_threads=dict(
38+
nohash=True,
39+
usedefault=True,
40+
),
41+
out_file=dict(
42+
argstr='-prefix %s',
43+
keep_extension=True,
44+
name_source='in_file1',
45+
name_template='%s_bistat',
46+
position=0,
47+
),
48+
outputtype=dict(),
49+
stat=dict(
50+
argstr='-stat %s...',
51+
mandatory=True,
52+
),
53+
terminal_output=dict(
54+
deprecated='1.0.0',
55+
nohash=True,
56+
),
57+
weight_file=dict(
58+
argstr='-weight %s',
59+
xor=['automask'],
60+
),
61+
)
62+
inputs = LocalBistat.input_spec()
63+
64+
for key, metadata in list(input_map.items()):
65+
for metakey, value in list(metadata.items()):
66+
assert getattr(inputs.traits()[key], metakey) == value
67+
def test_LocalBistat_outputs():
68+
output_map = dict(out_file=dict(), )
69+
outputs = LocalBistat.output_spec()
70+
71+
for key, metadata in list(output_map.items()):
72+
for metakey, value in list(metadata.items()):
73+
assert getattr(outputs.traits()[key], metakey) == value

nipype/interfaces/afni/utils.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,6 +1338,121 @@ def _list_outputs(self):
13381338
return outputs
13391339

13401340

1341+
class LocalBistatInputSpec(AFNICommandInputSpec):
1342+
in_file1 = File(
1343+
exists=True,
1344+
mandatory=True,
1345+
argstr='%s',
1346+
position=-2,
1347+
desc='Filename of the first image')
1348+
in_file2 = File(
1349+
exists=True,
1350+
mandatory=True,
1351+
argstr='%s',
1352+
position=-1,
1353+
desc='Filename of the second image')
1354+
neighborhood = traits.Either(
1355+
traits.Tuple(traits.Enum('SPHERE', 'RHDD', 'TOHD'), traits.Float()),
1356+
traits.Tuple(traits.Enum('RECT'), traits.Tuple(traits.Float(),
1357+
traits.Float(),
1358+
traits.Float())),
1359+
mandatory=True,
1360+
desc='The region around each voxel that will be extracted for '
1361+
'the statistics calculation. Possible regions are: '
1362+
'\'SPHERE\', \'RHDD\' (rhombic dodecahedron), \'TOHD\' '
1363+
'(truncated octahedron) with a given radius in mm or '
1364+
'\'RECT\' (rectangular block) with dimensions to specify in mm.',
1365+
argstr="-nbhd '%s(%s)'")
1366+
_stat_names = ['pearson', 'spearman', 'quadrant', 'mutinfo', 'normuti',
1367+
'jointent', 'hellinger', 'crU', 'crM', 'crA', 'L2slope',
1368+
'L1slope', 'num', 'ALL']
1369+
stat = InputMultiPath(
1370+
traits.Enum(_stat_names),
1371+
mandatory=True,
1372+
desc='statistics to compute. Possible names are :'
1373+
' * pearson = Pearson correlation coefficient'
1374+
' * spearman = Spearman correlation coefficient'
1375+
' * quadrant = Quadrant correlation coefficient'
1376+
' * mutinfo = Mutual Information'
1377+
' * normuti = Normalized Mutual Information'
1378+
' * jointent = Joint entropy'
1379+
' * hellinger= Hellinger metric'
1380+
' * crU = Correlation ratio (Unsymmetric)'
1381+
' * crM = Correlation ratio (symmetrized by Multiplication)'
1382+
' * crA = Correlation ratio (symmetrized by Addition)'
1383+
' * L2slope = slope of least-squares (L2) linear regression of '
1384+
' the data from dataset1 vs. the dataset2 '
1385+
' (i.e., d2 = a + b*d1 ==> this is \'b\')'
1386+
' * L1slope = slope of least-absolute-sum (L1) linear '
1387+
' regression of the data from dataset1 vs. '
1388+
' the dataset2'
1389+
' * num = number of the values in the region: '
1390+
' with the use of -mask or -automask, '
1391+
' the size of the region around any given '
1392+
' voxel will vary; this option lets you '
1393+
' map that size.'
1394+
' * ALL = all of the above, in that order'
1395+
'More than one option can be used.',
1396+
argstr='-stat %s...')
1397+
mask_file = traits.File(
1398+
exists=True,
1399+
desc='mask image file name. Voxels NOT in the mask will not be used '
1400+
'in the neighborhood of any voxel. Also, a voxel NOT in the mask '
1401+
'will have its statistic(s) computed as zero (0).',
1402+
argstr='-mask %s')
1403+
automask = traits.Bool(
1404+
desc='Compute the mask as in program 3dAutomask.',
1405+
argstr='-automask',
1406+
xor=['weight_file'])
1407+
weight_file = traits.File(
1408+
exists=True,
1409+
desc='File name of an image to use as a weight. Only applies to '
1410+
'\'pearson\' statistics.',
1411+
argstr='-weight %s',
1412+
xor=['automask'])
1413+
out_file = traits.File(
1414+
desc='Output dataset.',
1415+
argstr='-prefix %s',
1416+
name_source='in_file1',
1417+
name_template='%s_bistat',
1418+
keep_extension=True,
1419+
position=0)
1420+
1421+
1422+
class LocalBistat(AFNICommand):
1423+
"""3dLocalBistat - computes statistics between 2 datasets, at each voxel,
1424+
based on a local neighborhood of that voxel.
1425+
1426+
For complete details, see the `3dLocalBistat Documentation.
1427+
<https://afni.nimh.nih.gov/pub../pub/dist/doc/program_help/3dLocalBistat.html>`_
1428+
1429+
Examples
1430+
========
1431+
1432+
>>> from nipype.interfaces import afni
1433+
>>> bistat = afni.LocalBistat()
1434+
>>> bistat.inputs.in_file1 = 'functional.nii'
1435+
>>> bistat.inputs.in_file2 = 'structural.nii'
1436+
>>> bistat.inputs.neighborhood = ('SPHERE', 1.2)
1437+
>>> bistat.inputs.stat = 'pearson'
1438+
>>> bistat.inputs.outputtype = 'NIFTI'
1439+
>>> bistat.cmdline
1440+
"3dLocalBistat -prefix functional_bistat.nii -nbhd 'SPHERE(1.2)' -stat pearson functional.nii structural.nii"
1441+
>>> res = automask.run() # doctest: +SKIP
1442+
1443+
"""
1444+
1445+
_cmd = '3dLocalBistat'
1446+
input_spec = LocalBistatInputSpec
1447+
output_spec = AFNICommandOutputSpec
1448+
1449+
def _format_arg(self, name, spec, value):
1450+
if name == 'neighborhood' and value[0] == 'RECT':
1451+
value = ('RECT', '%s,%s,%s' % value[1])
1452+
1453+
return super(LocalBistat, self)._format_arg(name, spec, value)
1454+
1455+
13411456
class MaskToolInputSpec(AFNICommandInputSpec):
13421457
in_file = File(
13431458
desc='input file or files to 3dmask_tool',

nipype/interfaces/dcm2nii.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ class Dcm2niixInputSpec(CommandLineInputSpec):
264264
position=-1,
265265
copyfile=False,
266266
mandatory=True,
267-
desc=('A set of filenames to be converted. Note that the current '
267+
desc=('A set of filenames to be converted. Note that the current '
268268
'version (1.0.20180328) of dcm2niix converts any files in the '
269269
'directory. To only convert specific files they should be in an '
270270
'isolated directory'),

nipype/tests/test_nipype.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def test_nipype_info():
1212
assert exception_not_raised
1313

1414

15-
@pytest.mark.skipif(not get_nipype_gitversion(),
15+
@pytest.mark.skipif(not get_nipype_gitversion(),
1616
reason="not able to get version from get_nipype_gitversion")
1717
def test_git_hash():
1818
# removing the first "g" from gitversion

nipype/workflows/dmri/dtitk/tensor_registration.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,11 @@ def diffeomorphic_tensor_pipeline(name='DiffeoTen',
5252
params={'array_size': (128, 128, 64)}):
5353
"""
5454
Workflow that performs a diffeomorphic registration
55-
(Rigid and Affine follwed by Diffeomorphic)
55+
(Rigid and Affine followed by Diffeomorphic)
5656
Note: the requirements for a diffeomorphic registration specify that
5757
the dimension 0 is a power of 2 so images are resliced prior to
58-
registration
58+
registration. Remember to move origin and reslice prior to applying xfm to
59+
another file!
5960
6061
Example
6162
-------
@@ -75,7 +76,9 @@ def diffeomorphic_tensor_pipeline(name='DiffeoTen',
7576
fields=['out_file', 'out_file_xfm',
7677
'fixed_resliced', 'moving_resliced']),
7778
name='outputnode')
78-
79+
origin_node_fixed = pe.Node(dtitk.TVAdjustVoxSp(origin=(0, 0, 0)),
80+
name='origin_node_fixed')
81+
origin_node_moving = origin_node_fixed.clone(name='origin_node_moving')
7982
reslice_node_pow2 = pe.Node(dtitk.TVResample(
8083
origin=(0, 0, 0),
8184
array_size=params['array_size']),
@@ -92,14 +95,23 @@ def diffeomorphic_tensor_pipeline(name='DiffeoTen',
9295
compose_xfm_node = pe.Node(dtitk.ComposeXfm(), name='compose_xfm_node')
9396
apply_xfm_node = pe.Node(dtitk.DiffeoSymTensor3DVol(),
9497
name='apply_xfm_node')
98+
adjust_vs_node_to_input = pe.Node(dtitk.TVAdjustVoxSp(),
99+
name='adjust_vs_node_to_input')
100+
reslice_node_to_input = pe.Node(dtitk.TVResample(),
101+
name='reslice_node_to_input')
102+
input_fa = pe.Node(dtitk.TVtool(in_flag='fa'), name='input_fa')
95103

96104
wf = pe.Workflow(name=name)
97105

106+
# calculate input FA image for origin reference
107+
wf.connect(inputnode, 'fixed_file', input_fa, 'in_file')
98108
# Reslice input images
99-
wf.connect(inputnode, 'fixed_file', reslice_node_pow2, 'in_file')
109+
wf.connect(inputnode, 'fixed_file', origin_node_fixed, 'in_file')
110+
wf.connect(origin_node_fixed, 'out_file', reslice_node_pow2, 'in_file')
100111
wf.connect(reslice_node_pow2, 'out_file',
101112
reslice_node_moving, 'target_file')
102-
wf.connect(inputnode, 'moving_file', reslice_node_moving, 'in_file')
113+
wf.connect(inputnode, 'moving_file', origin_node_moving, 'in_file')
114+
wf.connect(origin_node_moving, 'out_file', reslice_node_moving, 'in_file')
103115
# Rigid registration
104116
wf.connect(reslice_node_pow2, 'out_file', rigid_node, 'fixed_file')
105117
wf.connect(reslice_node_moving, 'out_file', rigid_node, 'moving_file')
@@ -118,8 +130,13 @@ def diffeomorphic_tensor_pipeline(name='DiffeoTen',
118130
# Apply transform
119131
wf.connect(reslice_node_moving, 'out_file', apply_xfm_node, 'in_file')
120132
wf.connect(compose_xfm_node, 'out_file', apply_xfm_node, 'transform')
133+
# Move origin and reslice to match original fixed input image
134+
wf.connect(apply_xfm_node, 'out_file', adjust_vs_node_to_input, 'in_file')
135+
wf.connect(input_fa, 'out_file', adjust_vs_node_to_input, 'target_file')
136+
wf.connect(adjust_vs_node_to_input, 'out_file', reslice_node_to_input, 'in_file')
137+
wf.connect(input_fa, 'out_file', reslice_node_to_input, 'target_file')
121138
# Send to output
122-
wf.connect(apply_xfm_node, 'out_file', outputnode, 'out_file')
139+
wf.connect(reslice_node_to_input, 'out_file', outputnode, 'out_file')
123140
wf.connect(compose_xfm_node, 'out_file', outputnode, 'out_file_xfm')
124141
wf.connect(reslice_node_pow2, 'out_file', outputnode, 'fixed_resliced')
125142
wf.connect(reslice_node_moving, 'out_file', outputnode, 'moving_resliced')

tools/checkspecs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ def test_specs(self, uri):
287287
and "requires" not in trait.__dict__\
288288
and "xor" not in trait.__dict__:
289289
if trait.trait_type.__class__.__name__ is "Range"\
290-
and trait.default == trait.trait_type._low:
290+
and trait.default == trait.trait_type._low:
291291
continue
292292
bad_specs.append(
293293
[uri, c, 'Inputs', traitname, 'default value is set, no value for usedefault'])

0 commit comments

Comments
 (0)