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