Skip to content

Commit ec4d612

Browse files
authored
Merge branch 'master' into fix/1407
2 parents 82263dc + 4801a4c commit ec4d612

File tree

7 files changed

+277
-74
lines changed

7 files changed

+277
-74
lines changed

CHANGES

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ Upcoming release
33

44
* ENH: Improve terminal_output feature (https://github.com/nipy/nipype/pull/2209)
55
* ENH: Simple interface to FSL std2imgcoords (https://github.com/nipy/nipype/pull/2209, prev #1398)
6-
6+
* ENH: Centralize virtual/physical $DISPLAYs (https://github.com/nipy/nipype/pull/#2203)
7+
* ENH: New ResourceMonitor - replaces resource profiler (https://github.com/nipy/nipype/pull/#2200)
78

89
0.13.1 (May 20, 2017)
910
=====================

doc/users/config_file.rst

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,16 @@ Execution
7373
``false``; default value: ``true``)
7474

7575
*display_variable*
76-
What ``DISPLAY`` variable should all command line interfaces be
77-
run with. This is useful if you are using `xnest
78-
<http://www.x.org/archive/X11R7.5/doc/man/man1/Xnest.1.html>`_
79-
or `Xvfb <http://www.x.org/archive/X11R6.8.1/doc/Xvfb.1.html>`_
80-
and you would like to redirect all spawned windows to
81-
it. (possible values: any X server address; default value: not
82-
set)
76+
Override the ``$DISPLAY`` environment variable for interfaces that require
77+
an X server. This option is useful if there is a running X server, but
78+
``$DISPLAY`` was not defined in nipype's environment. For example, if an X
79+
server is listening on the default port of 6000, set ``display_variable = :0``
80+
to enable nipype interfaces to use it. It may also point to displays provided
81+
by VNC, `xnest <http://www.x.org/archive/X11R7.5/doc/man/man1/Xnest.1.html>`_
82+
or `Xvfb <http://www.x.org/archive/X11R6.8.1/doc/Xvfb.1.html>`_.
83+
If neither ``display_variable`` nor the ``$DISPLAY`` environment variable are
84+
set, nipype will try to configure a new virtual server using Xvfb.
85+
(possible values: any X server address; default value: not set)
8386

8487
*remove_unnecessary_outputs*
8588
This will remove any interface outputs not needed by the workflow. If the

nipype/interfaces/afni/preprocess.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2157,11 +2157,12 @@ class SkullStrip(AFNICommand):
21572157

21582158
def __init__(self, **inputs):
21592159
super(SkullStrip, self).__init__(**inputs)
2160+
21602161
if not no_afni():
21612162
v = Info.version()
21622163

2163-
# As of AFNI 16.0.00, redirect_x is not needed
2164-
if v[0] > 2015:
2164+
# Between AFNI 16.0.00 and 16.2.07, redirect_x is not needed
2165+
if v >= (2016, 0, 0) and v < (2016, 2, 7):
21652166
self._redirect_x = False
21662167

21672168

nipype/interfaces/base.py

Lines changed: 11 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,14 @@
5656

5757

5858
class Str(traits.Unicode):
59-
pass
60-
59+
"""Replacement for the default traits.Str based in bytes"""
6160

6261
traits.Str = Str
6362

6463

6564
class NipypeInterfaceError(Exception):
65+
"""Custom error for interfaces"""
66+
6667
def __init__(self, value):
6768
self.value = value
6869

@@ -1016,31 +1017,6 @@ def _check_version_requirements(self, trait_object, raise_exception=True):
10161017
version, max_ver))
10171018
return unavailable_traits
10181019

1019-
def _run_wrapper(self, runtime):
1020-
if self._redirect_x:
1021-
try:
1022-
from xvfbwrapper import Xvfb
1023-
except ImportError:
1024-
iflogger.error('Xvfb wrapper could not be imported')
1025-
raise
1026-
1027-
vdisp = Xvfb(nolisten='tcp')
1028-
vdisp.start()
1029-
try:
1030-
vdisp_num = vdisp.new_display
1031-
except AttributeError: # outdated version of xvfbwrapper
1032-
vdisp_num = vdisp.vdisplay_num
1033-
1034-
iflogger.info('Redirecting X to :%d' % vdisp_num)
1035-
runtime.environ['DISPLAY'] = ':%d' % vdisp_num
1036-
1037-
runtime = self._run_interface(runtime)
1038-
1039-
if self._redirect_x:
1040-
vdisp.stop()
1041-
1042-
return runtime
1043-
10441020
def _run_interface(self, runtime):
10451021
""" Core function that executes interface
10461022
"""
@@ -1082,6 +1058,9 @@ def run(self, **inputs):
10821058
store_provenance = str2bool(config.get(
10831059
'execution', 'write_provenance', 'false'))
10841060
env = deepcopy(dict(os.environ))
1061+
if self._redirect_x:
1062+
env['DISPLAY'] = config.get_display()
1063+
10851064
runtime = Bunch(cwd=os.getcwd(),
10861065
returncode=None,
10871066
duration=None,
@@ -1104,8 +1083,9 @@ def run(self, **inputs):
11041083
# Grab inputs now, as they should not change during execution
11051084
inputs = self.inputs.get_traitsfree()
11061085
outputs = None
1086+
11071087
try:
1108-
runtime = self._run_wrapper(runtime)
1088+
runtime = self._run_interface(runtime)
11091089
outputs = self.aggregate_outputs(runtime)
11101090
except Exception as e:
11111091
import traceback
@@ -1315,21 +1295,14 @@ def _canonicalize_env(env):
13151295
return out_env
13161296

13171297

1318-
def run_command(runtime, output=None, timeout=0.01, redirect_x=False):
1298+
def run_command(runtime, output=None, timeout=0.01):
13191299
"""Run a command, read stdout and stderr, prefix with timestamp.
13201300
13211301
The returned runtime contains a merged stdout+stderr log with timestamps
13221302
"""
13231303

13241304
# Init variables
13251305
cmdline = runtime.cmdline
1326-
1327-
if redirect_x:
1328-
exist_xvfb, _ = _exists_in_path('xvfb-run', runtime.environ)
1329-
if not exist_xvfb:
1330-
raise RuntimeError('Xvfb was not found, X redirection aborted')
1331-
cmdline = 'xvfb-run -a ' + cmdline
1332-
13331306
env = _canonicalize_env(runtime.environ)
13341307

13351308
default_encoding = locale.getdefaultlocale()[1]
@@ -1586,17 +1559,7 @@ def raise_exception(self, runtime):
15861559
**runtime.dictcopy()))
15871560

15881561
def _get_environ(self):
1589-
out_environ = {}
1590-
if not self._redirect_x:
1591-
try:
1592-
display_var = config.get('execution', 'display_variable')
1593-
out_environ = {'DISPLAY': display_var}
1594-
except NoOptionError:
1595-
pass
1596-
iflogger.debug(out_environ)
1597-
if isdefined(self.inputs.environ):
1598-
out_environ.update(self.inputs.environ)
1599-
return out_environ
1562+
return getattr(self.inputs, 'environ', {})
16001563

16011564
def version_from_command(self, flag='-v'):
16021565
cmdname = self.cmd.split()[0]
@@ -1613,10 +1576,6 @@ def version_from_command(self, flag='-v'):
16131576
o, e = proc.communicate()
16141577
return o
16151578

1616-
def _run_wrapper(self, runtime):
1617-
runtime = self._run_interface(runtime)
1618-
return runtime
1619-
16201579
def _run_interface(self, runtime, correct_return_codes=(0,)):
16211580
"""Execute command via subprocess
16221581
@@ -1648,8 +1607,7 @@ def _run_interface(self, runtime, correct_return_codes=(0,)):
16481607

16491608
runtime.command_path = cmd_path
16501609
runtime.dependencies = get_dependencies(executable_name, runtime.environ)
1651-
runtime = run_command(runtime, output=self.terminal_output,
1652-
redirect_x=self._redirect_x)
1610+
runtime = run_command(runtime, output=self.inputs.terminal_output)
16531611
if runtime.returncode is None or \
16541612
runtime.returncode not in correct_return_codes:
16551613
self.raise_exception(runtime)

nipype/interfaces/tests/test_base.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -638,26 +638,42 @@ def _gen_filename(self, name):
638638
nib.CommandLine.input_spec = nib.CommandLineInputSpec
639639

640640

641-
def test_Commandline_environ():
641+
def test_Commandline_environ(monkeypatch, tmpdir):
642642
from nipype import config
643643
config.set_default_config()
644+
645+
tmpdir.chdir()
646+
monkeypatch.setitem(os.environ, 'DISPLAY', ':1')
647+
# Test environment
644648
ci3 = nib.CommandLine(command='echo')
645649
res = ci3.run()
646650
assert res.runtime.environ['DISPLAY'] == ':1'
651+
652+
# Test display_variable option
653+
monkeypatch.delitem(os.environ, 'DISPLAY', raising=False)
647654
config.set('execution', 'display_variable', ':3')
648655
res = ci3.run()
649656
assert not 'DISPLAY' in ci3.inputs.environ
657+
assert not 'DISPLAY' in res.runtime.environ
658+
659+
# If the interface has _redirect_x then yes, it should be set
660+
ci3._redirect_x = True
661+
res = ci3.run()
650662
assert res.runtime.environ['DISPLAY'] == ':3'
663+
664+
# Test overwrite
665+
monkeypatch.setitem(os.environ, 'DISPLAY', ':1')
651666
ci3.inputs.environ = {'DISPLAY': ':2'}
652667
res = ci3.run()
653668
assert res.runtime.environ['DISPLAY'] == ':2'
654669

655670

656671
def test_CommandLine_output(tmpdir):
657-
# Create a file
658-
name = 'foo.txt'
672+
# Create one file
659673
tmpdir.chdir()
660-
tmpdir.join(name).write('foo')
674+
file = tmpdir.join('foo.txt')
675+
file.write('123456\n')
676+
name = os.path.basename(file.strpath)
661677

662678
ci = nib.CommandLine(command='ls -l')
663679
ci.terminal_output = 'allatonce'

0 commit comments

Comments
 (0)