-
Notifications
You must be signed in to change notification settings - Fork 532
/
Copy pathr.py
122 lines (99 loc) · 3.58 KB
/
r.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# -*- coding: utf-8 -*-
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
"""Interfaces to run R scripts."""
import os
from shutil import which
from .. import config
from .base import (
CommandLineInputSpec,
InputMultiPath,
isdefined,
CommandLine,
traits,
File,
Directory,
)
def get_r_command():
if "NIPYPE_NO_R" in os.environ:
return None
r_cmd = os.getenv("RCMD", default="R")
return r_cmd if which(r_cmd) else None
no_r = get_r_command() is None
class RInputSpec(CommandLineInputSpec):
"""Basic expected inputs to R interface"""
script = traits.Str(
argstr='-e "%s"', desc="R code to run", mandatory=True, position=-1
)
# non-commandline options
rfile = traits.Bool(True, desc="Run R using R script", usedefault=True)
script_file = File(
"pyscript.R", usedefault=True, desc="Name of file to write R code to"
)
class RCommand(CommandLine):
"""Interface that runs R code
>>> import nipype.interfaces.r as r
>>> r = r.RCommand(rfile=False) # doctest: +SKIP
>>> r.inputs.script = "Sys.getenv('USER')" # doctest: +SKIP
>>> out = r.run() # doctest: +SKIP
"""
_cmd = get_r_command()
input_spec = RInputSpec
def __init__(self, r_cmd=None, **inputs):
"""initializes interface to r
(default 'R')
"""
super(RCommand, self).__init__(**inputs)
if r_cmd and isdefined(r_cmd):
self._cmd = r_cmd
# For r commands force all output to be returned since r
# does not have a clean way of notifying an error
self.terminal_output = "allatonce"
def set_default_r_cmd(self, r_cmd):
"""Set the default R command line for R classes.
This method is used to set values for all R
subclasses.
"""
self._cmd = r_cmd
def set_default_rfile(self, rfile):
"""Set the default R script file format for R classes.
This method is used to set values for all R
subclasses.
"""
self._rfile = rfile
def _run_interface(self, runtime):
self.terminal_output = "allatonce"
runtime = super(RCommand, self)._run_interface(runtime)
if "R code threw an exception" in runtime.stderr:
self.raise_exception(runtime)
return runtime
def _format_arg(self, name, trait_spec, value):
if name in ["script"]:
argstr = trait_spec.argstr
return self._gen_r_command(argstr, value)
return super(RCommand, self)._format_arg(name, trait_spec, value)
def _gen_r_command(self, argstr, script_lines):
"""Generates commands and, if rfile specified, writes it to disk."""
if not self.inputs.rfile:
# replace newlines with ;
script = "; ".join(
list(
filter(
None, # drop empty lines
[
line
for line in script_lines.split("\n")
if not line.strip().startswith("#") # strip comments
],
)
)
)
# escape " and $
script = script.replace('"', '\\"')
script = script.replace("$", "\\$")
else:
script_path = os.path.join(os.getcwd(), self.inputs.script_file)
with open(script_path, "wt") as rfile:
rfile.write(script_lines)
script = "source('%s')" % script_path
return argstr % script