Skip to content

Commit 94c926b

Browse files
committed
Merge remote-tracking branch 'upstream/master' into fix/spminfo
2 parents 44a7b66 + 04d0159 commit 94c926b

File tree

11 files changed

+349
-39
lines changed

11 files changed

+349
-39
lines changed

.circleci/config.yml

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,28 @@ jobs:
183183
- run: *_run_codecov_coverage
184184
- store_artifacts: *store_artifacts_kwds
185185
- store_test_results: *store_artifacts_kwds
186+
- run:
187+
name: Build docs (py36)
188+
no_output_timeout: 30m
189+
environment: *test_environment
190+
command: bash -ux /home/circleci/nipype/.circleci/test_py3_docs.sh
191+
- store_artifacts:
192+
path: /home/circleci/work/docs
193+
- run:
194+
name: Save Docker images to workspace if on master
195+
no_output_timeout: 60m
196+
command: |
197+
if [ "$CIRCLE_BRANCH" = "master" -a -z "$CIRCLE_PULL_REQUEST" ]; then
198+
docker save nipype/nipype:base \
199+
nipype/nipype:latest \
200+
nipype/nipype:py27 \
201+
nipype/nipype:py36 | gzip -1 > /tmp/docker/nipype-base-latest-py36-py27.tar.gz \
202+
&& du -h /tmp/docker/nipype-base-latest-py36-py27.tar.gz
203+
fi
204+
- persist_to_workspace:
205+
root: /tmp
206+
paths:
207+
- docker
186208

187209
test_py3_fmri_fsl_spm:
188210
machine: *machine_kwds
@@ -200,11 +222,6 @@ jobs:
200222
- run: *_get_codecov
201223
- run: *_download_test_data
202224
- run: *prepare_working_directory
203-
- run:
204-
name: Run FSL FEEDS pipeline (py36)
205-
no_output_timeout: 40m
206-
environment: *test_environment
207-
command: bash -ux /home/circleci/nipype/.circleci/test_py3_fmri_fsl_feeds_linear_l1.sh
208225
- run:
209226
name: Run FSL reuse pipeline (py36)
210227
no_output_timeout: 40m
@@ -252,7 +269,7 @@ jobs:
252269
- run: *_run_codecov_smoke
253270
- store_artifacts: *store_artifacts_kwds
254271

255-
test_fmri_spm_nested_multiproc:
272+
test_fmri_spm_nested_fsl_feeds:
256273
machine: *machine_kwds
257274
working_directory: /home/circleci/nipype
258275
steps:
@@ -279,30 +296,13 @@ jobs:
279296
no_output_timeout: 30m
280297
environment: *test_environment
281298
command: bash -ux /home/circleci/nipype/.circleci/test_py2_fmri_spm_nested_multiproc_l2.sh
282-
- run: *_run_codecov_smoke
283-
- store_artifacts: *store_artifacts_kwds
284299
- run:
285-
name: Build docs (py36)
286-
no_output_timeout: 30m
300+
name: Run FSL FEEDS pipeline (py36)
301+
no_output_timeout: 40m
287302
environment: *test_environment
288-
command: bash -ux /home/circleci/nipype/.circleci/test_py3_docs.sh
289-
- store_artifacts:
290-
path: /home/circleci/work/docs
291-
- run:
292-
name: Save Docker images to workspace if on master
293-
no_output_timeout: 60m
294-
command: |
295-
if [ "$CIRCLE_BRANCH" = "master" -a -z "$CIRCLE_PULL_REQUEST" ]; then
296-
docker save nipype/nipype:base \
297-
nipype/nipype:latest \
298-
nipype/nipype:py27 \
299-
nipype/nipype:py36 | gzip -1 > /tmp/docker/nipype-base-latest-py36-py27.tar.gz \
300-
&& du -h /tmp/docker/nipype-base-latest-py36-py27.tar.gz
301-
fi
302-
- persist_to_workspace:
303-
root: /tmp
304-
paths:
305-
- docker
303+
command: bash -ux /home/circleci/nipype/.circleci/test_py3_fmri_fsl_feeds_linear_l1.sh
304+
- run: *_run_codecov_smoke
305+
- store_artifacts: *store_artifacts_kwds
306306

307307
deploy:
308308
docker:
@@ -350,7 +350,7 @@ workflows:
350350
- test_py3_fmri_spm_dartel_multiproc:
351351
requires:
352352
- compare_base_dockerfiles
353-
- test_fmri_spm_nested_multiproc:
353+
- test_fmri_spm_nested_fsl_feeds:
354354
requires:
355355
- compare_base_dockerfiles
356356
- deploy:
@@ -359,6 +359,6 @@ workflows:
359359
only: master
360360
requires:
361361
- test_pytest
362-
- test_fmri_spm_nested_multiproc
362+
- test_fmri_spm_nested_fsl_feeds
363363
- test_py3_fmri_fsl_spm
364364
- test_py3_fmri_spm_dartel_multiproc

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ before_install:
4040
fi;
4141

4242
# handle python operations separately to reduce timeouts
43-
- wget https://repo.continuum.io/miniconda/Miniconda${TRAVIS_PYTHON_VERSION:0:1}-latest-Linux-x86_64.sh
43+
- wget https://repo.continuum.io/miniconda/Miniconda${TRAVIS_PYTHON_VERSION:0:1}-4.3.31-Linux-x86_64.sh
4444
-O /home/travis/.cache/conda.sh
4545
- bash ${HOME}/.cache/conda.sh -b -p ${HOME}/conda
4646
- export PATH=${HOME}/conda/bin:$PATH

CHANGES

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
Upcoming release
2-
================
3-
41
1.0.0 (January 24, 2018)
52
========================
63

docker/generate_dockerfiles.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ function generate_main_dockerfile() {
8888
--user neuro \
8989
--miniconda env_name=neuro \
9090
activate=true \
91+
miniconda_version=4.3.31 \
9192
--copy docker/files/run_builddocs.sh docker/files/run_examples.sh \
9293
docker/files/run_pytests.sh nipype/external/fsl_imglob.py /usr/bin/ \
9394
--copy . /src/nipype \

nipype/interfaces/spm/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from .base import (Info, SPMCommand, logger, no_spm, scans_for_fname,
77
scans_for_fnames)
8-
from .preprocess import (SliceTiming, Realign, Coregister, Normalize,
8+
from .preprocess import (FieldMap, SliceTiming, Realign, Coregister, Normalize,
99
Normalize12, Segment, Smooth, NewSegment, DARTEL,
1010
DARTELNorm2MNI, CreateWarped, VBMSegment)
1111
from .model import (Level1Design, EstimateModel, EstimateContrast, Threshold,

nipype/interfaces/spm/base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,8 @@ def _format_arg(self, opt, spec, val):
387387
"""Convert input to appropriate format for SPM."""
388388
if spec.is_trait_type(traits.Bool):
389389
return int(val)
390+
elif spec.is_trait_type(traits.Tuple):
391+
return list(val)
390392
else:
391393
return val
392394

nipype/interfaces/spm/preprocess.py

Lines changed: 139 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,149 @@
2222
# Local imports
2323
from ...utils.filemanip import (fname_presuffix, filename_to_list,
2424
list_to_filename, split_filename)
25-
from ..base import (OutputMultiPath, TraitedSpec, isdefined, traits,
26-
InputMultiPath, File)
27-
from .base import (SPMCommand, scans_for_fname, func_is_3d, scans_for_fnames,
28-
SPMCommandInputSpec, ImageFileSPM)
25+
from ..base import (OutputMultiPath, TraitedSpec, isdefined,
26+
traits, InputMultiPath, File, Str)
27+
from .base import (SPMCommand, scans_for_fname, func_is_3d,
28+
scans_for_fnames, SPMCommandInputSpec, ImageFileSPM)
2929

3030
__docformat__ = 'restructuredtext'
3131

3232

33+
class FieldMapInputSpec(SPMCommandInputSpec):
34+
jobtype = traits.Enum('calculatevdm', 'applyvdm', usedefault=True,
35+
desc='one of: calculatevdm, applyvdm')
36+
phase_file = File(mandatory=True, exists=True, copyfile=False,
37+
field='subj.data.presubphasemag.phase',
38+
desc='presubstracted phase file')
39+
magnitude_file = File(mandatory=True, exists=True, copyfile=False,
40+
field='subj.data.presubphasemag.magnitude',
41+
desc='presubstracted magnitude file')
42+
echo_times = traits.Tuple(traits.Float, traits.Float, mandatory=True,
43+
field='subj.defaults.defaultsval.et',
44+
desc='short and long echo times')
45+
maskbrain = traits.Bool(True, usedefault=True,
46+
field='subj.defaults.defaultsval.maskbrain',
47+
desc='masking or no masking of the brain')
48+
blip_direction = traits.Enum(1, -1, mandatory=True,
49+
field='subj.defaults.defaultsval.blipdir',
50+
desc='polarity of the phase-encode blips')
51+
total_readout_time = traits.Float(mandatory=True,
52+
field='subj.defaults.defaultsval.tert',
53+
desc='total EPI readout time')
54+
epifm = traits.Bool(False, usedefault=True,
55+
field='subj.defaults.defaultsval.epifm',
56+
desc='epi-based field map');
57+
jacobian_modulation = traits.Bool(False, usedefault=True,
58+
field='subj.defaults.defaultsval.ajm',
59+
desc='jacobian modulation');
60+
# Unwarping defaults parameters
61+
method = traits.Enum('Mark3D', 'Mark2D', 'Huttonish', usedefault=True,
62+
desc='One of: Mark3D, Mark2D, Huttonish',
63+
field='subj.defaults.defaultsval.uflags.method');
64+
unwarp_fwhm = traits.Range(low=0, value=10, usedefault=True,
65+
field='subj.defaults.defaultsval.uflags.fwhm',
66+
desc='gaussian smoothing kernel width');
67+
pad = traits.Range(low=0, value=0, usedefault=True,
68+
field='subj.defaults.defaultsval.uflags.pad',
69+
desc='padding kernel width');
70+
ws = traits.Bool(True, usedefault=True,
71+
field='subj.defaults.defaultsval.uflags.ws',
72+
desc='weighted smoothing');
73+
# Brain mask defaults parameters
74+
template = File(copyfile=False, exists=True,
75+
field='subj.defaults.defaultsval.mflags.template',
76+
desc='template image for brain masking');
77+
mask_fwhm = traits.Range(low=0, value=5, usedefault=True,
78+
field='subj.defaults.defaultsval.mflags.fwhm',
79+
desc='gaussian smoothing kernel width');
80+
nerode = traits.Range(low=0, value=2, usedefault=True,
81+
field='subj.defaults.defaultsval.mflags.nerode',
82+
desc='number of erosions');
83+
ndilate = traits.Range(low=0, value=4, usedefault=True,
84+
field='subj.defaults.defaultsval.mflags.ndilate',
85+
desc='number of erosions');
86+
thresh = traits.Float(0.5, usedefault=True,
87+
field='subj.defaults.defaultsval.mflags.thresh',
88+
desc='threshold used to create brain mask from segmented data');
89+
reg = traits.Float(0.02, usedefault=True,
90+
field='subj.defaults.defaultsval.mflags.reg',
91+
desc='regularization value used in the segmentation');
92+
# EPI unwarping for quality check
93+
epi_file = File(copyfile=False, exists=True, mandatory=True,
94+
field='subj.session.epi',
95+
desc='EPI to unwarp');
96+
matchvdm = traits.Bool(True, usedefault=True,
97+
field='subj.matchvdm',
98+
desc='match VDM to EPI');
99+
sessname = Str('_run-', usedefault=True,
100+
field='subj.sessname',
101+
desc='VDM filename extension');
102+
writeunwarped = traits.Bool(False, usedefault=True,
103+
field='subj.writeunwarped',
104+
desc='write unwarped EPI');
105+
anat_file = File(copyfile=False, exists=True,
106+
field='subj.anat',
107+
desc='anatomical image for comparison');
108+
matchanat = traits.Bool(True, usedefault=True,
109+
field='subj.matchanat',
110+
desc='match anatomical image to EPI');
111+
112+
113+
class FieldMapOutputSpec(TraitedSpec):
114+
vdm = File(exists=True, desc='voxel difference map')
115+
116+
117+
class FieldMap(SPMCommand):
118+
"""Use the fieldmap toolbox from spm to calculate the voxel displacement map (VDM).
119+
120+
http://www.fil.ion.ucl.ac.uk/spm/doc/manual.pdf#page=173
121+
122+
To do
123+
-----
124+
Deal with real/imag magnitude images and with the two phase files case.
125+
126+
Examples
127+
--------
128+
>>> from nipype.interfaces.spm import FieldMap
129+
>>> fm = FieldMap()
130+
>>> fm.inputs.phase_file = 'phase.nii'
131+
>>> fm.inputs.magnitude_file = 'magnitude.nii'
132+
>>> fm.inputs.echo_times = (5.19, 7.65)
133+
>>> fm.inputs.blip_direction = 1
134+
>>> fm.inputs.total_readout_time = 15.6
135+
>>> fm.inputs.epi_file = 'epi.nii'
136+
>>> fm.run() # doctest: +SKIP
137+
138+
"""
139+
140+
input_spec = FieldMapInputSpec
141+
output_spec = FieldMapOutputSpec
142+
_jobtype = 'tools'
143+
_jobname = 'fieldmap'
144+
145+
def _format_arg(self, opt, spec, val):
146+
"""Convert input to appropriate format for spm
147+
"""
148+
if opt in ['phase_file', 'magnitude_file', 'anat_file', 'epi_file']:
149+
return scans_for_fname(filename_to_list(val))
150+
151+
return super(FieldMap, self)._format_arg(opt, spec, val)
152+
153+
def _parse_inputs(self):
154+
"""validate spm fieldmap options if set to None ignore
155+
"""
156+
einputs = super(FieldMap, self)._parse_inputs()
157+
return [{self.inputs.jobtype: einputs[0]}]
158+
159+
def _list_outputs(self):
160+
outputs = self._outputs().get()
161+
jobtype = self.inputs.jobtype
162+
if jobtype == "calculatevdm":
163+
outputs['vdm'] = fname_presuffix(self.inputs.phase_file, prefix='vdm5_sc')
164+
165+
return outputs
166+
167+
33168
class SliceTimingInputSpec(SPMCommandInputSpec):
34169
in_files = InputMultiPath(
35170
traits.Either(

0 commit comments

Comments
 (0)