import pydoc
from rpy2 import robjects
import operator
from biorpy.conversion import convertToR, addResultWrapper
def isIPy():
try:
__IPYTHON__
return True
except NameError:
return False
def isInteractive():
import __main__ as main
return not hasattr(main, '__file__')
## DEFAULT ARGS, OUTPUT HANDLING
[docs]def rx(name):
""" extracts a value by name from an R object """
def f(x):
return x.rx(name)
return f
[docs]def item(i):
""" Short name for operator.itemgetter() """
return operator.itemgetter(i)
def getDefaultHandlers(converter):
handlers = []
handlers.append(Handler("wilcox.test",
# outputs={"p.value":[rx("p.value"), item(0), item(0)]},
converter=converter)
)
handlers.append(Handler("plot",
defaults={"xlab":"", "ylab":"", "main":""},
converter=converter)
)
handlers.append(Handler("hist",
defaults={"xlab":"", "main":""},
converter=converter)
)
return handlers
def getDefaultAliases():
return {"devoff":"dev.off"}
[docs]class Handler(object):
""" Wrapper for R objects to implement:
1. default arguments
2. argument conversion
3. output conversion
"""
[docs] def __init__(self, rname, pyname=None, defaults=None, converter=convertToR):
"""
Args
name: name of the R function
defaults: a dictionary of default arguments to the function
outputs: a dictionary whose values are lists of functions used to extract values from
the return R value. For example: {"p.value":[rx("p.value"), item(0), item(0)]}
converter: a conversion function used to convert python objects into R objects
"""
self.rname = rname
if pyname is None:
self.pyname = rname
else:
self.pyname = pyname
self.defaults = defaults if defaults else {}
# self.outputs = outputs if outputs else {}
self.converter = converter
# may want some extra error checking here
self._robject = robjects.r[self.rname]
def __call__(self, *args, **kwdargs):
# python -> R conversion
args = [self.converter(arg) for arg in args]
for kwd in kwdargs:
kwdargs[kwd] = self.converter(kwdargs[kwd])
# default arguments
defaults = self.defaults.copy()
defaults.update(kwdargs)
# call R
rval = robjects.r[self.rname](*args, **defaults)
#rval = super(Handler, self).__call__(*args, **defaults)
# output conversion
addResultWrapper(rval)
# if self.outputs:
# result = {}
# for output in self.outputs:
# result[output] = reduce(lambda x, f: f(x), self.outputs[output], rval)
# rval.py = result
return rval
[docs] def help(self):
""" Displays the R help for the current object """
pydoc.pager(robjects.help.pages(self.rname)[0].to_docstring())
# @property
# def __doc__(self):
# return str(robjects.r.help(self.rname))
[docs]class BetteR(object):
""" Wrapper for rpy2.robjects.R """
[docs] def __init__(self, converter=convertToR):
""" Initialize the RPy2 wrapper instance """
self.aliases = getDefaultAliases()
self._handlers = {}
for handler in getDefaultHandlers(converter):
self.addHandler_(handler)
if isInteractive():
self.initInteractive()
[docs] def initInteractive(self):
""" Checks to see if we're running interactively (eg ipython), and if so,
starts the event manager in RPy2. (This allows resizing of interactive
plot windows.) """
# This allows graphics windows to be resized
from rpy2.interactive import process_revents
try:
process_revents.start()
except RuntimeError:
# this can occur when we've already called process_revents.start()
# in any case, it's not a big deal if the above didn't work
# so let's ignore the error
pass
[docs] def addHandler_(self, handler):
""" Add a :class:`biorpy.betteR.Handler`."""
self._handlers[handler.pyname] = handler
def __getattribute__(self, attr):
try:
return super(BetteR, self).__getattribute__(attr)
except AttributeError as ae:
orig_ae = ae
try:
return self.__getitem__(attr)
except LookupError:
raise orig_ae
def __getitem__(self, attr):
if attr in self.aliases:
attr = self.aliases[attr]
if attr.startswith("gg"):
print "do something for ggplot..."
if not attr in self._handlers:
self._handlers[attr] = Handler(attr)
return self._handlers[attr]
def __call__(self, string):
rval = robjects.r(string)
addResultWrapper(rval)
return rval
if __name__ == '__main__':
r = BetteR()
result = r["wilcox.test"](robjects.FloatVector(range(5)), robjects.FloatVector([1,2,55,3,6]))
print result.py["p.value"]
#r.plot(robjects.FloatVector(range(5)), robjects.FloatVector([1,2,55,3,6]))
r.plot([1,2,3,4,5], [1,3,4,4.5,5], col=["red" for i in range(5)])
for i in range(100000):
for j in range(1000):
pass