Skip to content

Commit e5b5f76

Browse files
author
bpinsard
committed
Merge branch 'master' into afni_interfaces
* master: (21 commits) doc: updated debug config message. ants code cleanup (PEP8, unused variables) removed in_file from DTLUTGen docstring added changelog message removed unused variables removed unused imports pep8 and reindent removed an evil trailing comma from WIMT fix: added test to check that inputs are not modified when setting display variable via config fix: added tests, actually added display variable to config fix: interface environment always overwrites config environ DISPLAY doc: change closes nipy#368 fix: environment inputs not changed by config display variable AFNITraitedSpec for Calc Renamed NBS interface Threshold to a float Typo fix Replaced CFF option with multiple network output Added optional node position network Initial NBS commit ...
2 parents 76c592e + 626b3f4 commit e5b5f76

File tree

13 files changed

+197
-21
lines changed

13 files changed

+197
-21
lines changed

CHANGES

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
Since last release
22
==================
33

4-
* ENH: New interfaces: MySQLSink, nipy.Similarity, WatershedBEM
4+
* API: display variable no longer encoded as inputs in commandline interfaces
5+
6+
* ENH: New interfaces: MySQLSink, nipy.Similarity, WatershedBEM,
7+
NetworkBasedStatistic
58

69
* FIX: Afni outputs should inherit from TraitedSpec
710

doc/users/debug.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,16 @@ performance issues.
1717

1818
#. Use the debug config mode. This can be done by setting::
1919

20-
import config
20+
from nipype import config
2121
config.enable_debug_mode()
2222

2323
as the first import of your nipype script.
2424

25+
.. note::
26+
27+
Turning on debug will rerun your workflows and will rerun them after debugging
28+
is turned off.
29+
2530
#. There are several configuration options that can help with debugging. See
2631
:ref:`config_file` for more details::
2732

nipype/interfaces/afni/preprocess.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1588,7 +1588,7 @@ def aggregate_outputs(self, runtime=None, needed_outputs=None):
15881588
"""
15891589

15901590

1591-
class CalcInputSpec(CommandLineInputSpec):
1591+
class CalcInputSpec(AFNITraitedSpec):
15921592
in_file_a = File(desc='input file to 3dcalc',
15931593
argstr='-a %s', position=0, mandatory=True)
15941594
in_file_b = File(desc='operand file to 3dcalc',

nipype/interfaces/ants/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,5 @@
33

44
"""Top-level namespace for ants."""
55

6-
from .normalize import (BuildTemplate, WarpImageMultiTransform,
6+
from .normalize import (BuildTemplate, WarpImageMultiTransform,
77
WarpTimeSeriesImageMultiTransform, GenWarpFields)
8-

nipype/interfaces/ants/normalize.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ def _list_outputs(self):
146146
self.inputs.out_prefix)
147147
outputs['subject_outfiles'] = []
148148
for filename in self.inputs.in_files:
149-
pth, base, ext = split_filename(filename)
149+
_, base, _ = split_filename(filename)
150150
temp = glob(os.path.realpath('%s%s*' % (self.inputs.out_prefix,
151151
base)))
152152
for file_ in temp:
@@ -222,7 +222,7 @@ def _format_arg(self, opt, spec, val):
222222
isdefined(self.inputs.invert_affine):
223223
affine_counter += 1
224224
if affine_counter in self.inputs.invert_affine:
225-
series += ['-i'],
225+
series += ['-i']
226226
series += [transformation]
227227
return ' '.join(series)
228228
return super(WarpImageMultiTransform, self)._format_arg(opt, spec, val)

nipype/interfaces/ants/setup.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
22
# vi: set ft=python sts=4 ts=4 sw=4 et:
3-
def configuration(parent_package='',top_path=None):
3+
4+
5+
def configuration(parent_package='', top_path=None):
46
from numpy.distutils.misc_util import Configuration
57

68
config = Configuration('ants', parent_package, top_path)

nipype/interfaces/base.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,11 +1033,6 @@ def __init__(self, command=None, **inputs):
10331033
raise Exception("Missing command")
10341034
if command:
10351035
self._cmd = command
1036-
try:
1037-
display_var = config.get('execution', 'display_variable')
1038-
self.inputs.environ['DISPLAY'] = display_var
1039-
except NoOptionError:
1040-
pass
10411036

10421037
@property
10431038
def cmd(self):
@@ -1087,7 +1082,16 @@ def _run_interface(self, runtime):
10871082
setattr(runtime, 'stdout', None)
10881083
setattr(runtime, 'stderr', None)
10891084
setattr(runtime, 'cmdline', self.cmdline)
1090-
runtime.environ.update(self.inputs.environ)
1085+
out_environ = {}
1086+
try:
1087+
display_var = config.get('execution', 'display_variable')
1088+
out_environ = {'DISPLAY': display_var}
1089+
except NoOptionError:
1090+
pass
1091+
iflogger.info(out_environ)
1092+
if isdefined(self.inputs.environ):
1093+
out_environ.update(self.inputs.environ)
1094+
runtime.environ.update(out_environ)
10911095
if not self._exists_in_path(self.cmd.split()[0]):
10921096
raise IOError("%s could not be found on host %s" % (self.cmd.split()[0],
10931097
runtime.hostname))

nipype/interfaces/camino/dti.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,6 @@ class DTLUTGen(StdOutCommandLine):
209209
>>> dtl = cmon.DTLUTGen()
210210
>>> dtl.inputs.snr = 16
211211
>>> dtl.inputs.scheme_file = 'A.scheme'
212-
>>> dtl.inputs.in_file = 'tensor_fitted_data.Bfloat'
213212
>>> dtl.run() # doctest: +SKIP
214213
"""
215214
_cmd = 'dtlutgen'

nipype/interfaces/cmtk/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
from .nx import NetworkXMetrics, AverageNetworks
33
from .parcellation import Parcellate
44
from .convert import CFFConverter, MergeCNetworks
5+
from .nbs import NetworkBasedStatistic

nipype/interfaces/cmtk/nbs.py

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
2+
# vi: set ft=python sts=4 ts=4 sw=4 et:
3+
from nipype.interfaces.base import (BaseInterface, BaseInterfaceInputSpec, traits,
4+
File, TraitedSpec, InputMultiPath,
5+
OutputMultiPath, isdefined)
6+
import os.path as op
7+
import numpy as np
8+
import networkx as nx
9+
from nipype.utils.misc import package_check
10+
import warnings
11+
12+
from ... import logging
13+
iflogger = logging.getLogger('interface')
14+
15+
have_cv = True
16+
try:
17+
package_check('cviewer')
18+
except Exception, e:
19+
have_cv = False
20+
warnings.warn('ConnectomeViewer not installed')
21+
else:
22+
import cviewer.libs.pyconto.groupstatistics.nbs as nbs
23+
24+
25+
def ntwks_to_matrices(in_files, edge_key):
26+
first = nx.read_gpickle(in_files[0])
27+
files = len(in_files)
28+
nodes = len(first.nodes())
29+
matrix = np.zeros((nodes, nodes, files))
30+
for idx, name in enumerate(in_files):
31+
graph = nx.read_gpickle(name)
32+
for u, v, d in graph.edges(data=True):
33+
graph[u][v]['weight'] = d[edge_key] # Setting the edge requested edge value as weight value
34+
matrix[:, :, idx] = nx.to_numpy_matrix(graph) # Retrieve the matrix
35+
return matrix
36+
37+
38+
class NetworkBasedStatisticInputSpec(BaseInterfaceInputSpec):
39+
in_group1 = InputMultiPath(File(exists=True), mandatory=True, desc='Networks for the first group of subjects')
40+
in_group2 = InputMultiPath(File(exists=True), mandatory=True, desc='Networks for the second group of subjects')
41+
node_position_network = File(desc='An optional network used to position the nodes for the output networks')
42+
number_of_permutations = traits.Int(1000, usedefault=True, desc='Number of permutations to perform')
43+
threshold = traits.Float(3, usedefault=True, desc='T-statistic threshold')
44+
t_tail = traits.Enum('left', 'right', 'both', usedefault=True, desc='Can be one of "left", "right", or "both"')
45+
edge_key = traits.Str('number_of_fibers', usedefault=True, desc='Usually "number_of_fibers, "fiber_length_mean", "fiber_length_std" for matrices made with CMTK' \
46+
'Sometimes "weight" or "value" for functional networks.')
47+
out_nbs_network = File(desc='Output network with edges identified by the NBS')
48+
out_nbs_pval_network = File(desc='Output network with p-values to weight the edges identified by the NBS')
49+
50+
51+
class NetworkBasedStatisticOutputSpec(TraitedSpec):
52+
nbs_network = File(exists=True, desc='Output network with edges identified by the NBS')
53+
nbs_pval_network = File(exists=True, desc='Output network with p-values to weight the edges identified by the NBS')
54+
network_files = OutputMultiPath(File(exists=True), desc='Output network with edges identified by the NBS')
55+
56+
57+
class NetworkBasedStatistic(BaseInterface):
58+
"""
59+
Calculates and outputs the average network given a set of input NetworkX gpickle files
60+
61+
For documentation of Network-based statistic parameters:
62+
63+
https://github.com/LTS5/connectomeviewer/blob/master/cviewer/libs/pyconto/groupstatistics/nbs/_nbs.py
64+
65+
Example
66+
-------
67+
68+
>>> import nipype.interfaces.cmtk as cmtk
69+
>>> nbs = cmtk.NetworkBasedStatistic()
70+
>>> nbs.inputs.in_group1 = ['subj1.pck', 'subj2.pck'] # doctest: +SKIP
71+
>>> nbs.inputs.in_group2 = ['pat1.pck', 'pat2.pck'] # doctest: +SKIP
72+
>>> nbs.run() # doctest: +SKIP
73+
"""
74+
input_spec = NetworkBasedStatisticInputSpec
75+
output_spec = NetworkBasedStatisticOutputSpec
76+
77+
def _run_interface(self, runtime):
78+
THRESH = self.inputs.threshold
79+
K = self.inputs.number_of_permutations
80+
TAIL = self.inputs.t_tail
81+
edge_key = self.inputs.edge_key
82+
details = edge_key + '-thresh-' + str(THRESH) + '-k-' + str(K) + '-tail-' + TAIL + '.pck'
83+
84+
# Fill in the data from the networks
85+
X = ntwks_to_matrices(self.inputs.in_group1, edge_key)
86+
Y = ntwks_to_matrices(self.inputs.in_group2, edge_key)
87+
88+
PVAL, ADJ, _ = nbs.compute_nbs(X, Y, THRESH, K, TAIL)
89+
90+
iflogger.info('p-values:')
91+
iflogger.info(PVAL)
92+
93+
pADJ = ADJ.copy()
94+
for idx, _ in enumerate(PVAL):
95+
x, y = np.where(ADJ == idx + 1)
96+
pADJ[x, y] = PVAL[idx]
97+
98+
# Create networkx graphs from the adjacency matrix
99+
nbsgraph = nx.from_numpy_matrix(ADJ)
100+
nbs_pval_graph = nx.from_numpy_matrix(pADJ)
101+
102+
# Relabel nodes because they should not start at zero for our convention
103+
nbsgraph = nx.relabel_nodes(nbsgraph, lambda x: x + 1)
104+
nbs_pval_graph = nx.relabel_nodes(nbs_pval_graph, lambda x: x + 1)
105+
106+
if isdefined(self.inputs.node_position_network):
107+
node_ntwk_name = self.inputs.node_position_network
108+
else:
109+
node_ntwk_name = self.inputs.in_group1[0]
110+
111+
node_network = nx.read_gpickle(node_ntwk_name)
112+
iflogger.info('Populating node dictionaries with attributes from {node}'.format(node=node_ntwk_name))
113+
114+
for nid, ndata in node_network.nodes_iter(data=True):
115+
nbsgraph.node[nid] = ndata
116+
nbs_pval_graph.node[nid] = ndata
117+
118+
path = op.abspath('NBS_Result_' + details)
119+
iflogger.info(path)
120+
nx.write_gpickle(nbsgraph, path)
121+
iflogger.info('Saving output NBS edge network as {out}'.format(out=path))
122+
123+
pval_path = op.abspath('NBS_P_vals_' + details)
124+
iflogger.info(pval_path)
125+
nx.write_gpickle(nbs_pval_graph, pval_path)
126+
iflogger.info('Saving output p-value network as {out}'.format(out=pval_path))
127+
return runtime
128+
129+
def _list_outputs(self):
130+
outputs = self.output_spec().get()
131+
132+
THRESH = self.inputs.threshold
133+
K = self.inputs.number_of_permutations
134+
TAIL = self.inputs.t_tail
135+
edge_key = self.inputs.edge_key
136+
details = edge_key + '-thresh-' + str(THRESH) + '-k-' + str(K) + '-tail-' + TAIL + '.pck'
137+
path = op.abspath('NBS_Result_' + details)
138+
pval_path = op.abspath('NBS_P_vals_' + details)
139+
140+
outputs['nbs_network'] = path
141+
outputs['nbs_pval_network'] = pval_path
142+
outputs['network_files'] = [path, pval_path]
143+
return outputs
144+
145+
def _gen_outfilename(self, name, ext):
146+
return name + '.' + ext

nipype/interfaces/fsl/preprocess.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def _gen_outfilename(self):
133133
if not isdefined(out_file) and isdefined(self.inputs.in_file):
134134
out_file = self._gen_fname(self.inputs.in_file,
135135
suffix='_brain')
136-
return out_file
136+
return os.path.abspath(out_file)
137137

138138
def _list_outputs(self):
139139
outputs = self.output_spec().get()
@@ -474,6 +474,7 @@ def _list_outputs(self):
474474
if not isdefined(outputs['out_file']) and isdefined(self.inputs.in_file):
475475
outputs['out_file'] = self._gen_fname(self.inputs.in_file,
476476
suffix='_flirt')
477+
outputs['out_file'] = os.path.abspath(self.inputs.out_file)
477478
outputs['out_matrix_file'] = self.inputs.out_matrix_file
478479
# Generate an out_matrix file if one is not provided
479480
if not isdefined(outputs['out_matrix_file']) and \
@@ -904,7 +905,7 @@ def _list_outputs(self):
904905
outputs['out_file'] = self._gen_fname(self.inputs.in_file,
905906
suffix='_warp')
906907
else:
907-
outputs['out_file'] = self.inputs.out_file
908+
outputs['out_file'] = os.path.abspath(self.inputs.out_file)
908909
return outputs
909910

910911
def _gen_filename(self, name):
@@ -963,7 +964,7 @@ def _list_outputs(self):
963964
if not isdefined(out_file):
964965
out_file = self._gen_fname(self.inputs.in_file,
965966
suffix='_st')
966-
outputs['slice_time_corrected_file'] = out_file
967+
outputs['slice_time_corrected_file'] = os.path.abspath(out_file)
967968
return outputs
968969

969970
def _gen_filename(self, name):
@@ -1041,7 +1042,7 @@ def _list_outputs(self):
10411042
if not isdefined(out_file):
10421043
out_file = self._gen_fname(self.inputs.in_file,
10431044
suffix='_smooth')
1044-
outputs['smoothed_file'] = out_file
1045+
outputs['smoothed_file'] = os.path.abspath(out_file)
10451046
return outputs
10461047

10471048
def _gen_filename(self, name):
@@ -1143,7 +1144,7 @@ def _list_outputs(self):
11431144
if not isdefined(out_file):
11441145
out_file = self._gen_fname(self.inputs.in_file,
11451146
suffix='_unwarped')
1146-
outputs['unwarped_file'] = out_file
1147+
outputs['unwarped_file'] = os.path.abspath(out_file)
11471148
return outputs
11481149

11491150
def _gen_filename(self, name):
@@ -1222,7 +1223,7 @@ def _list_outputs(self):
12221223
if not isdefined(out_file):
12231224
out_file = self._gen_fname(self.inputs.in_file,
12241225
suffix='_unwrapped')
1225-
outputs['unwrapped_phase_file'] = out_file
1226+
outputs['unwrapped_phase_file'] = os.path.abspath(out_file)
12261227
return outputs
12271228

12281229
def _gen_filename(self, name):

nipype/interfaces/tests/test_base.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,3 +263,18 @@ def _gen_filename(self, name):
263263
ci6 = DerivedClass(command='cmd')
264264
yield assert_equal, ci6._parse_inputs()[0], 'filename'
265265
nib.CommandLine.input_spec = nib.CommandLineInputSpec
266+
267+
268+
def test_Commandline_environ():
269+
from nipype import config
270+
config.set_default_config()
271+
ci3 = nib.CommandLine(command='echo')
272+
res = ci3.run()
273+
yield assert_equal, res.runtime.environ['DISPLAY'], ':1'
274+
config.set('execution', 'display_variable', ':3')
275+
res = ci3.run()
276+
yield assert_false, 'DISPLAY' in ci3.inputs.environ
277+
yield assert_equal, res.runtime.environ['DISPLAY'], ':3'
278+
ci3.inputs.environ = {'DISPLAY' : ':2'}
279+
res = ci3.run()
280+
yield assert_equal, res.runtime.environ['DISPLAY'], ':2'

nipype/utils/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
[execution]
3333
create_report = true
3434
crashdump_dir = %s
35+
display_variable = :1
3536
hash_method = timestamp
3637
job_finished_timeout = 5
3738
keep_inputs = false

0 commit comments

Comments
 (0)