Skip to content

Commit d9a8eec

Browse files
authored
Merge branch 'nipy:master' into cat12_sanlm
2 parents 0fa255e + 7080ef9 commit d9a8eec

File tree

12 files changed

+201
-145
lines changed

12 files changed

+201
-145
lines changed

nipype/algorithms/confounds.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class ComputeDVARS(BaseInterface):
104104

105105
input_spec = ComputeDVARSInputSpec
106106
output_spec = ComputeDVARSOutputSpec
107-
references_ = [
107+
_references = [
108108
{
109109
"entry": BibTeX(
110110
"""\
@@ -311,7 +311,7 @@ class FramewiseDisplacement(BaseInterface):
311311
input_spec = FramewiseDisplacementInputSpec
312312
output_spec = FramewiseDisplacementOutputSpec
313313

314-
references_ = [
314+
_references = [
315315
{
316316
"entry": BibTeX(
317317
"""\
@@ -556,7 +556,7 @@ class CompCor(SimpleInterface):
556556

557557
input_spec = CompCorInputSpec
558558
output_spec = CompCorOutputSpec
559-
references_ = [
559+
_references = [
560560
{
561561
"tags": ["method", "implementation"],
562562
"entry": BibTeX(

nipype/interfaces/afni/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ class AFNICommand(AFNICommandBase):
151151
input_spec = AFNICommandInputSpec
152152
_outputtype = None
153153

154-
references_ = [
154+
_references = [
155155
{
156156
"entry": BibTeX(
157157
"@article{Cox1996,"

nipype/interfaces/afni/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,7 +1032,7 @@ class Edge3(AFNICommand):
10321032
_cmd = "3dedge3"
10331033
input_spec = Edge3InputSpec
10341034
output_spec = AFNICommandOutputSpec
1035-
references_ = [
1035+
_references = [
10361036
{
10371037
"entry": BibTeX(
10381038
"""\
@@ -1341,7 +1341,7 @@ class FWHMx(AFNICommandBase):
13411341
input_spec = FWHMxInputSpec
13421342
output_spec = FWHMxOutputSpec
13431343

1344-
references_ = [
1344+
_references = [
13451345
{
13461346
"entry": BibTeX(
13471347
"@article{CoxReynoldsTaylor2016,"

nipype/interfaces/ants/segmentation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1734,7 +1734,7 @@ class KellyKapowski(ANTSCommand):
17341734
input_spec = KellyKapowskiInputSpec
17351735
output_spec = KellyKapowskiOutputSpec
17361736

1737-
references_ = [
1737+
_references = [
17381738
{
17391739
"entry": BibTeX(
17401740
"""\

nipype/interfaces/base/core.py

Lines changed: 53 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,31 @@
1-
# -*- coding: utf-8 -*-
21
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
32
# vi: set ft=python sts=4 ts=4 sw=4 et:
43
"""
54
Nipype interfaces core
65
......................
76
8-
97
Defines the ``Interface`` API and the body of the
108
most basic interfaces.
119
The I/O specifications corresponding to these base
1210
interfaces are found in the ``specs`` module.
1311
1412
"""
15-
from copy import deepcopy
16-
from datetime import datetime as dt
1713
import os
18-
import platform
1914
import subprocess as sp
2015
import shlex
21-
import sys
2216
import simplejson as json
23-
from dateutil.parser import parse as parseutc
2417
from traits.trait_errors import TraitError
2518

2619
from ... import config, logging, LooseVersion
2720
from ...utils.provenance import write_provenance
28-
from ...utils.misc import str2bool, rgetcwd
29-
from ...utils.filemanip import split_filename, which, get_dependencies, canonicalize_env
21+
from ...utils.misc import str2bool
22+
from ...utils.filemanip import (
23+
canonicalize_env,
24+
get_dependencies,
25+
indirectory,
26+
split_filename,
27+
which,
28+
)
3029
from ...utils.subprocess import run_command
3130

3231
from ...external.due import due
@@ -39,7 +38,12 @@
3938
MpiCommandLineInputSpec,
4039
get_filecopy_info,
4140
)
42-
from .support import Bunch, InterfaceResult, NipypeInterfaceError, format_help
41+
from .support import (
42+
RuntimeContext,
43+
InterfaceResult,
44+
NipypeInterfaceError,
45+
format_help,
46+
)
4347

4448
iflogger = logging.getLogger("nipype.interface")
4549

@@ -63,8 +67,15 @@ class Interface(object):
6367
6468
"""
6569

66-
input_spec = None # A traited input specification
67-
output_spec = None # A traited output specification
70+
input_spec = None
71+
"""
72+
The specification of the input, defined by a :py:class:`~traits.has_traits.HasTraits` class.
73+
"""
74+
output_spec = None
75+
"""
76+
The specification of the output, defined by a :py:class:`~traits.has_traits.HasTraits` class.
77+
"""
78+
6879
_can_resume = False # See property below
6980
_always_run = False # See property below
7081

@@ -161,7 +172,7 @@ class BaseInterface(Interface):
161172
_version = None
162173
_additional_metadata = []
163174
_redirect_x = False
164-
references_ = []
175+
_references = []
165176
resource_monitor = True # Enabled for this interface IFF enabled in the config
166177
_etelemetry_version_data = None
167178

@@ -343,7 +354,7 @@ def _run_interface(self, runtime):
343354

344355
def _duecredit_cite(self):
345356
"""Add the interface references to the duecredit citations"""
346-
for r in self.references_:
357+
for r in self._references:
347358
r["path"] = self.__module__
348359
due.cite(**r)
349360

@@ -365,131 +376,44 @@ def run(self, cwd=None, ignore_exception=None, **inputs):
365376
if successful, results
366377
367378
"""
368-
from ...utils.profiler import ResourceMonitor
369-
370-
# if ignore_exception is not provided, taking self.ignore_exception
371-
if ignore_exception is None:
372-
ignore_exception = self.ignore_exception
373-
374-
# Tear-up: get current and prev directories
375-
syscwd = rgetcwd(error=False) # Recover when wd does not exist
376-
if cwd is None:
377-
cwd = syscwd
378-
379-
os.chdir(cwd) # Change to the interface wd
379+
rtc = RuntimeContext(
380+
resource_monitor=config.resource_monitor and self.resource_monitor,
381+
ignore_exception=ignore_exception
382+
if ignore_exception is not None
383+
else self.ignore_exception,
384+
)
380385

381-
enable_rm = config.resource_monitor and self.resource_monitor
382-
self.inputs.trait_set(**inputs)
386+
with indirectory(cwd or os.getcwd()):
387+
self.inputs.trait_set(**inputs)
383388
self._check_mandatory_inputs()
384389
self._check_version_requirements(self.inputs)
385-
interface = self.__class__
386-
self._duecredit_cite()
387390

388-
# initialize provenance tracking
389-
store_provenance = str2bool(
390-
config.get("execution", "write_provenance", "false")
391-
)
392-
env = deepcopy(dict(os.environ))
393-
if self._redirect_x:
394-
env["DISPLAY"] = config.get_display()
395-
396-
runtime = Bunch(
397-
cwd=cwd,
398-
prevcwd=syscwd,
399-
returncode=None,
400-
duration=None,
401-
environ=env,
402-
startTime=dt.isoformat(dt.utcnow()),
403-
endTime=None,
404-
platform=platform.platform(),
405-
hostname=platform.node(),
406-
version=self.version,
407-
)
408-
runtime_attrs = set(runtime.dictcopy())
409-
410-
mon_sp = None
411-
if enable_rm:
412-
mon_freq = float(config.get("execution", "resource_monitor_frequency", 1))
413-
proc_pid = os.getpid()
414-
iflogger.debug(
415-
"Creating a ResourceMonitor on a %s interface, PID=%d.",
416-
self.__class__.__name__,
417-
proc_pid,
418-
)
419-
mon_sp = ResourceMonitor(proc_pid, freq=mon_freq)
420-
mon_sp.start()
391+
with rtc(self, cwd=cwd, redirect_x=self._redirect_x) as runtime:
421392

422-
# Grab inputs now, as they should not change during execution
423-
inputs = self.inputs.get_traitsfree()
424-
outputs = None
425-
426-
try:
393+
# Grab inputs now, as they should not change during execution
394+
inputs = self.inputs.get_traitsfree()
395+
outputs = None
396+
# Run interface
427397
runtime = self._pre_run_hook(runtime)
428398
runtime = self._run_interface(runtime)
429399
runtime = self._post_run_hook(runtime)
400+
# Collect outputs
430401
outputs = self.aggregate_outputs(runtime)
431-
except Exception as e:
432-
import traceback
433-
434-
# Retrieve the maximum info fast
435-
runtime.traceback = traceback.format_exc()
436-
# Gather up the exception arguments and append nipype info.
437-
exc_args = e.args if getattr(e, "args") else tuple()
438-
exc_args += (
439-
"An exception of type %s occurred while running interface %s."
440-
% (type(e).__name__, self.__class__.__name__),
441-
)
442-
if config.get("logging", "interface_level", "info").lower() == "debug":
443-
exc_args += ("Inputs: %s" % str(self.inputs),)
444-
445-
runtime.traceback_args = ("\n".join(["%s" % arg for arg in exc_args]),)
446-
447-
if not ignore_exception:
448-
raise
449-
finally:
450-
if runtime is None or runtime_attrs - set(runtime.dictcopy()):
451-
raise RuntimeError(
452-
"{} interface failed to return valid "
453-
"runtime object".format(interface.__class__.__name__)
454-
)
455-
# This needs to be done always
456-
runtime.endTime = dt.isoformat(dt.utcnow())
457-
timediff = parseutc(runtime.endTime) - parseutc(runtime.startTime)
458-
runtime.duration = (
459-
timediff.days * 86400 + timediff.seconds + timediff.microseconds / 1e6
460-
)
461-
results = InterfaceResult(
462-
interface, runtime, inputs=inputs, outputs=outputs, provenance=None
463-
)
464402

465-
# Add provenance (if required)
466-
if store_provenance:
467-
# Provenance will only throw a warning if something went wrong
468-
results.provenance = write_provenance(results)
469-
470-
# Make sure runtime profiler is shut down
471-
if enable_rm:
472-
import numpy as np
473-
474-
mon_sp.stop()
475-
476-
runtime.mem_peak_gb = None
477-
runtime.cpu_percent = None
478-
479-
# Read .prof file in and set runtime values
480-
vals = np.loadtxt(mon_sp.fname, delimiter=",")
481-
if vals.size:
482-
vals = np.atleast_2d(vals)
483-
runtime.mem_peak_gb = vals[:, 2].max() / 1024
484-
runtime.cpu_percent = vals[:, 1].max()
485-
486-
runtime.prof_dict = {
487-
"time": vals[:, 0].tolist(),
488-
"cpus": vals[:, 1].tolist(),
489-
"rss_GiB": (vals[:, 2] / 1024).tolist(),
490-
"vms_GiB": (vals[:, 3] / 1024).tolist(),
491-
}
492-
os.chdir(syscwd)
403+
results = InterfaceResult(
404+
self.__class__,
405+
rtc.runtime,
406+
inputs=inputs,
407+
outputs=outputs,
408+
provenance=None,
409+
)
410+
411+
# Add provenance (if required)
412+
if str2bool(config.get("execution", "write_provenance", "false")):
413+
# Provenance will only throw a warning if something went wrong
414+
results.provenance = write_provenance(results)
415+
416+
self._duecredit_cite()
493417

494418
return results
495419

0 commit comments

Comments
 (0)