Skip to content

Commit 4e55f51

Browse files
committed
Merge remote-tracking branch 'upstream/master' into enh/restingconn
* upstream/master: (27 commits) add: prov:type for activity that includes nipype module fix: attribute names are lowercase camelcase fix: class names are capitalized camelcase add missing argument to FLIRT simplified code auto_tests DcmStack: add option for unsetting force reading of files without DICM marker, skip gif images in input add PrepareFieldmap test update make specs add to CHANGES Polish interface, add examples, add tests modify manual test to pass with new ordering update make specs run make specs remove subjects dir from example too remove redundant subjects directory input modify example to pass test run make specs Remove position from --warp argument, not necessary create automatic test ...
2 parents d57c863 + a44b546 commit 4e55f51

23 files changed

+347
-32
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
Next Release
22
============
33

4+
* ENH: New FSL interface: EpiReg
5+
* ENH: New Freesurfer interface: Tkregister2 (for conversion of fsl style matrices to freesurfer format)
46
* ENH: New FSL interfaces: WarpPoints, WarpPointsToStd.
57
* ENH: New Freesurfer interface: MRIPretess
68
* ENH: New miscelaneous interface: AddCSVRow

nipype/interfaces/dcmstack.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
)
2323
import nibabel as nb
2424
from nipype.interfaces.traits_extension import isdefined, Undefined
25+
import imghdr
2526

2627
have_dcmstack = True
2728
try:
@@ -83,6 +84,9 @@ class DcmStackInputSpec(NiftiGeneratorBaseInputSpec):
8384
"any default exclude filters")
8485
include_regexes = traits.List(desc="Meta data to include, overriding any "
8586
"exclude filters")
87+
force_read = traits.Bool(True, usedefault=True,
88+
desc=('Force reading files without DICM marker'))
89+
8690

8791
class DcmStackOutputSpec(TraitedSpec):
8892
out_file = File(exists=True)
@@ -125,8 +129,9 @@ def _run_interface(self, runtime):
125129
include_regexes)
126130
stack = dcmstack.DicomStack(meta_filter=meta_filter)
127131
for src_path in src_paths:
128-
src_dcm = dicom.read_file(src_path, force=True)
129-
stack.add_dcm(src_dcm)
132+
if not imghdr.what(src_path)=="gif":
133+
src_dcm = dicom.read_file(src_path, force=self.inputs.force_read)
134+
stack.add_dcm(src_dcm)
130135
nii = stack.to_nifti(embed_meta=True)
131136
nw = NiftiWrapper(nii)
132137
self.out_path = \

nipype/interfaces/freesurfer/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@
1212
from .utils import (SampleToSurface, SurfaceSmooth, SurfaceTransform, Surface2VolTransform,
1313
SurfaceSnapshots,ApplyMask, MRIsConvert, MRITessellate, MRIPretess,
1414
MRIMarchingCubes, SmoothTessellation, MakeAverageSubject,
15-
ExtractMainComponent)
15+
ExtractMainComponent, Tkregister2)

nipype/interfaces/freesurfer/preprocess.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ class BBRegisterInputSpec(FSTraitedSpec):
807807
init = traits.Enum('spm', 'fsl', 'header', argstr='--init-%s',
808808
mandatory=True, xor=['init_reg_file'],
809809
desc='initialize registration spm, fsl, header')
810-
init_reg_file = File(exists=True,
810+
init_reg_file = File(exists=True, argstr='--init-reg %s',
811811
desc='existing registration file',
812812
xor=['init'], mandatory=True)
813813
contrast_type = traits.Enum('t1', 't2', argstr='--%s',

nipype/interfaces/freesurfer/tests/test_auto_BBRegister.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ def test_BBRegister_inputs():
2020
mandatory=True,
2121
xor=['init_reg_file'],
2222
),
23-
init_reg_file=dict(mandatory=True,
23+
init_reg_file=dict(argstr='--init-reg %s',
24+
mandatory=True,
2425
xor=['init'],
2526
),
2627
intermediate_file=dict(argstr='--int %s',
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from nipype.testing import assert_equal
3+
from nipype.interfaces.freesurfer.utils import Tkregister2
4+
5+
def test_Tkregister2_inputs():
6+
input_map = dict(args=dict(argstr='%s',
7+
),
8+
environ=dict(nohash=True,
9+
usedefault=True,
10+
),
11+
fsl_in_matrix=dict(argstr='--fsl %s',
12+
),
13+
ignore_exception=dict(nohash=True,
14+
usedefault=True,
15+
),
16+
moving_image=dict(argstr='--mov %s',
17+
mandatory=True,
18+
),
19+
noedit=dict(argstr='--noedit',
20+
usedefault=True,
21+
),
22+
reg_file=dict(argstr='--reg %s',
23+
mandatory=True,
24+
name_source='fsl',
25+
name_template='%s.dat',
26+
),
27+
subject_id=dict(argstr='--s %s',
28+
mandatory=True,
29+
),
30+
subjects_dir=dict(),
31+
terminal_output=dict(mandatory=True,
32+
nohash=True,
33+
),
34+
)
35+
inputs = Tkregister2.input_spec()
36+
37+
for key, metadata in input_map.items():
38+
for metakey, value in metadata.items():
39+
yield assert_equal, getattr(inputs.traits()[key], metakey), value
40+
41+
def test_Tkregister2_outputs():
42+
output_map = dict(reg_file=dict(),
43+
)
44+
outputs = Tkregister2.output_spec()
45+
46+
for key, metadata in output_map.items():
47+
for metakey, value in metadata.items():
48+
yield assert_equal, getattr(outputs.traits()[key], metakey), value
49+

nipype/interfaces/freesurfer/utils.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,3 +1188,42 @@ class ExtractMainComponent(CommandLine):
11881188
_cmd='mris_extract_main_component'
11891189
input_spec=ExtractMainComponentInputSpec
11901190
output_spec=ExtractMainComponentOutputSpec
1191+
1192+
1193+
class Tkregister2InputSpec(FSTraitedSpec):
1194+
moving_image = File(exists=True, mandatory=True, argstr="--mov %s",
1195+
desc='moving volume')
1196+
fsl_in_matrix = File(exists=True, argstr="--fsl %s",
1197+
desc='fsl-style registration input matrix')
1198+
subject_id = traits.String(argstr="--s %s", mandatory=True,
1199+
desc='freesurfer subject ID')
1200+
noedit = traits.Bool(True, argstr="--noedit", desc='do not open edit window (exit)', usedefault=True)
1201+
reg_file = File(name_template='%s.dat', name_source='fsl',
1202+
mandatory=True, argstr="--reg %s",
1203+
desc='freesurfer-style registration file')
1204+
1205+
1206+
class Tkregister2OutputSpec(TraitedSpec):
1207+
reg_file = File(exists=True, desc='freesurfer-style registration file')
1208+
1209+
1210+
class Tkregister2(FSCommand):
1211+
"""Use tkregister2 without the manual editing stage to convert
1212+
FSL-style registration matrix (.mat) to FreeSurfer-style registration matrix (.dat)
1213+
1214+
Examples
1215+
--------
1216+
1217+
>>> from nipype.interfaces.freesurfer import Tkregister2
1218+
>>> tk2 = Tkregister2(reg_file='register.dat')
1219+
>>> tk2.inputs.moving_image = 'epi.nii'
1220+
>>> tk2.inputs.fsl_in_matrix = 'flirt.mat'
1221+
>>> tk2.inputs.subject_id = 'test_subject'
1222+
>>> tk2.run() # doctest: +SKIP
1223+
"""
1224+
_cmd = "tkregister2"
1225+
input_spec = Tkregister2InputSpec
1226+
output_spec = Tkregister2OutputSpec
1227+
1228+
1229+

nipype/interfaces/fsl/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
Complex, InvWarp, WarpUtils, ConvertWarp, WarpPoints, WarpPointsToStd)
2020

2121
from .epi import (PrepareFieldmap, TOPUP, ApplyTOPUP, Eddy, EPIDeWarp,
22-
SigLoss, EddyCorrect)
22+
SigLoss, EddyCorrect, EpiReg)
2323

2424
from .dti import (BEDPOSTX, DTIFit, ProbTrackX, ProbTrackX2,
2525
VecReg, ProjThresh, FindTheBiggest, DistanceMap,

nipype/interfaces/fsl/epi.py

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class PrepareFieldmapInputSpec(FSLCommandInputSpec):
4646
usedefault=True,
4747
desc=('do not perform sanity checks for image '
4848
'size/range/dimensions'))
49-
out_fieldmap = File(argstr='%s', position=5,
49+
out_fieldmap = File(argstr='%s', position=4,
5050
desc='output name for prepared fieldmap')
5151

5252

@@ -534,6 +534,129 @@ def _gen_filename(self, name):
534534
return self._list_outputs()['out_file']
535535
return None
536536

537+
538+
class EpiRegInputSpec(FSLCommandInputSpec):
539+
epi = File(exists=True, argstr='--epi=%s', mandatory=True,
540+
position=-4, desc='EPI image')
541+
t1_head = File(exists=True, argstr='--t1=%s', mandatory=True,
542+
position=-3, desc='wholehead T1 image')
543+
t1_brain = File(exists=True, argstr='--t1brain=%s', mandatory=True,
544+
position=-2, desc='brain extracted T1 image')
545+
out_base = traits.String(desc='output base name', argstr='--out=%s',
546+
position=-1)
547+
fmap = File(exists=True, argstr='--fmap=%s',
548+
desc='fieldmap image (in rad/s)')
549+
fmapmag = File(exists=True, argstr='--fmapmag=%s',
550+
desc='fieldmap magnitude image - wholehead')
551+
fmapmagbrain = File(exists=True, argstr='--fmapmagbrain=%s',
552+
desc='fieldmap magnitude image - brain extracted')
553+
wmseg = File(exists=True, argstr='--wmseg=%s',
554+
desc='white matter segmentation of T1 image, has to be named \
555+
like the t1brain and end on _wmseg')
556+
echospacing = traits.Float(argstr='--echospacing=%f',
557+
desc='Effective EPI echo spacing \
558+
(sometimes called dwell time) - in seconds')
559+
pedir = traits.Enum('x', 'y', 'z', '-x', '-y', '-z', argstr='--pedir=%s',
560+
desc='phase encoding direction, dir = x/y/z/-x/-y/-z')
561+
562+
weight_image = File(exists=True, argstr='--weight=%s',
563+
desc='weighting image (in T1 space)')
564+
no_fmapreg = traits.Bool(False, argstr='--nofmapreg',
565+
desc='do not perform registration of fmap to T1 \
566+
(use if fmap already registered)')
567+
no_clean = traits.Bool(False, argstr='--noclean',
568+
desc='do not clean up intermediate files')
569+
570+
571+
class EpiRegOutputSpec(TraitedSpec):
572+
out_file = File(exists=True,
573+
desc='unwarped and coregistered epi input')
574+
out_1vol = File(exists=True,
575+
desc='unwarped and coregistered single volume')
576+
fmap2str_mat = File(exists=True,
577+
desc='rigid fieldmap-to-structural transform')
578+
fmap2epi_mat = File(exists=True,
579+
desc='rigid fieldmap-to-epi transform')
580+
fmap_epi = File(exists=True, desc='fieldmap in epi space')
581+
fmap_str = File(exists=True, desc='fieldmap in structural space')
582+
fmapmag_str = File(exists=True,
583+
desc='fieldmap magnitude image in structural space')
584+
epi2str_inv = File(exists=True,
585+
desc='rigid structural-to-epi transform')
586+
epi2str_mat = File(exists=True,
587+
desc='rigid epi-to-structural transform')
588+
shiftmap = File(exists=True, desc='shiftmap in epi space')
589+
fullwarp = File(exists=True,
590+
desc='warpfield to unwarp epi and transform into \
591+
structural space')
592+
wmseg = File(exists=True, desc='white matter segmentation used in flirt bbr')
593+
wmedge = File(exists=True, desc='white matter edges for visualization')
594+
595+
596+
class EpiReg(FSLCommand):
597+
"""
598+
599+
Runs FSL epi_reg script for simultaneous coregistration and fieldmap
600+
unwarping.
601+
602+
Examples
603+
--------
604+
605+
>>> from nipype.interfaces.fsl import EpiReg
606+
>>> epireg = EpiReg()
607+
>>> epireg.inputs.epi='epi.nii'
608+
>>> epireg.inputs.t1_head='T1.nii'
609+
>>> epireg.inputs.t1_brain='T1_brain.nii'
610+
>>> epireg.inputs.out_base='epi2struct'
611+
>>> epireg.inputs.fmap='fieldmap_phase_fslprepared.nii'
612+
>>> epireg.inputs.fmapmag='fieldmap_mag.nii'
613+
>>> epireg.inputs.fmapmagbrain='fieldmap_mag_brain.nii'
614+
>>> epireg.inputs.echospacing=0.00067
615+
>>> epireg.inputs.pedir='y'
616+
>>> epireg.cmdline #doctest: +ELLIPSIS
617+
'epi_reg --echospacing=0.000670 --fmap=fieldmap_phase_fslprepared.nii \
618+
--fmapmag=fieldmap_mag.nii --fmapmagbrain=fieldmap_mag_brain.nii --pedir=y \
619+
--epi=epi.nii --t1=T1.nii --t1brain=T1_brain.nii --out=epi2struct'
620+
>>> epireg.run() # doctest: +SKIP
621+
622+
"""
623+
_cmd = 'epi_reg'
624+
input_spec = EpiRegInputSpec
625+
output_spec = EpiRegOutputSpec
626+
627+
def _list_outputs(self):
628+
outputs = self.output_spec().get()
629+
outputs['out_file'] = os.path.join(os.getcwd(),
630+
self.inputs.out_base + '.nii.gz')
631+
outputs['out_1vol'] = os.path.join(os.getcwd(),
632+
self.inputs.out_base + '_1vol.nii.gz')
633+
outputs['fmap2str_mat'] = os.path.join(os.getcwd(),
634+
self.inputs.out_base + '_fieldmap2str.mat')
635+
outputs['fmap2epi_mat'] = os.path.join(os.getcwd(),
636+
self.inputs.out_base + '_fieldmaprads2epi.mat')
637+
outputs['fmap_epi'] = os.path.join(os.getcwd(),
638+
self.inputs.out_base + '_fieldmaprads2epi.nii.gz')
639+
outputs['fmap_str'] = os.path.join(os.getcwd(),
640+
self.inputs.out_base + '_fieldmaprads2str.nii.gz')
641+
outputs['fmapmag_str'] = os.path.join(os.getcwd(),
642+
self.inputs.out_base + '_fieldmap2str.nii.gz')
643+
outputs['epi2str_inv'] = os.path.join(os.getcwd(),
644+
self.inputs.out_base + '_inv.mat')
645+
outputs['epi2str_mat'] = os.path.join(os.getcwd(),
646+
self.inputs.out_base + '.mat')
647+
outputs['shiftmap'] = os.path.join(os.getcwd(),
648+
self.inputs.out_base + '_fieldmaprads2epi_shift.nii.gz')
649+
outputs['fullwarp'] = os.path.join(os.getcwd(),
650+
self.inputs.out_base + '_warp.nii.gz')
651+
outputs['wmedge'] = os.path.join(os.getcwd(),
652+
self.inputs.out_base + '_fast_wmedge.nii.gz')
653+
outputs['wmseg'] = os.path.join(os.getcwd(),
654+
self.inputs.out_base + '_fast_wmseg.nii.gz')
655+
656+
return outputs
657+
658+
659+
537660
#######################################
538661
# deprecated interfaces
539662
#######################################

nipype/interfaces/fsl/preprocess.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -471,10 +471,12 @@ class FLIRTInputSpec(FSLCommandInputSpec):
471471
desc='do not use blurring on downsampling')
472472
rigid2D = traits.Bool(argstr='-2D',
473473
desc='use 2D rigid body mode - ignores dof')
474-
475474
save_log = traits.Bool(desc='save to log file')
476475
verbose = traits.Int(argstr='-verbose %d',
477476
desc='verbose mode, 0 is least')
477+
bgvalue = traits.Float(0, argstr='-setbackground %f',
478+
desc=('use specified background value for points '
479+
'outside FOV'))
478480

479481
# BBR options
480482
wm_seg = File(
@@ -941,18 +943,18 @@ def write_config(self, configfile):
941943

942944
class ApplyWarpInputSpec(FSLCommandInputSpec):
943945
in_file = File(exists=True, argstr='--in=%s',
944-
mandatory=True,
946+
mandatory=True, position=0,
945947
desc='image to be warped')
946-
out_file = File(argstr='--out=%s', genfile=True,
948+
out_file = File(argstr='--out=%s', genfile=True, position=2,
947949
desc='output filename', hash_files=False)
948950
ref_file = File(exists=True, argstr='--ref=%s',
949-
mandatory=True,
951+
mandatory=True, position=1,
950952
desc='reference image')
951953
field_file = File(exists=True, argstr='--warp=%s',
952954
desc='file containing warp field')
953955
abswarp = traits.Bool(argstr='--abs', xor=['relwarp'],
954956
desc="treat warp field as absolute: x' = w(x)")
955-
relwarp = traits.Bool(argstr='--rel', xor=['abswarp'],
957+
relwarp = traits.Bool(argstr='--rel', xor=['abswarp'], position=-1,
956958
desc="treat warp field as relative: x' = x + w(x)")
957959
datatype = traits.Enum('char', 'short', 'int', 'float', 'double',
958960
argstr='--datatype=%s',
@@ -969,7 +971,7 @@ class ApplyWarpInputSpec(FSLCommandInputSpec):
969971
mask_file = File(exists=True, argstr='--mask=%s',
970972
desc='filename for mask image (in reference space)')
971973
interp = traits.Enum(
972-
'nn', 'trilinear', 'sinc', 'spline', argstr='--interp=%s',
974+
'nn', 'trilinear', 'sinc', 'spline', argstr='--interp=%s', position=-2,
973975
desc='interpolation method')
974976

975977

0 commit comments

Comments
 (0)