PageRenderTime 56ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/rpy/ipython/tests/test_rmagic.py

https://bitbucket.org/jergosh/rpy2_mplgrdev
Python | 216 lines | 204 code | 5 blank | 7 comment | 8 complexity | 709ba54c73effebf1ac603d2272193ce MD5 | raw file
Possible License(s): AGPL-3.0, GPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. import unittest
  2. from itertools import product
  3. # Currently numpy is a testing requirement, but rpy2 should work without numpy
  4. import numpy as np
  5. has_pandas = True
  6. try:
  7. import pandas as pd
  8. except:
  9. has_pandas = False
  10. from IPython.testing.globalipapp import get_ipython
  11. from IPython.utils.py3compat import PY3
  12. if PY3:
  13. from io import StringIO
  14. else:
  15. from StringIO import StringIO
  16. from rpy2.ipython import rmagic
  17. if rmagic.py2ri is not None:
  18. activate = rmagic.py2ri.activate
  19. deactivate = rmagic.py2ri.deactivate
  20. else:
  21. def activate():
  22. pass
  23. deactivate = activate
  24. # from IPython.core.getipython import get_ipython
  25. from rpy2 import rinterface
  26. from rpy2.robjects import r
  27. import rpy2.robjects.packages as rpacks
  28. class TestRmagic(unittest.TestCase):
  29. @classmethod
  30. def setUpClass(cls):
  31. '''Set up an IPython session just once.
  32. It'd be safer to set it up for each test, but for now, I'm mimicking the
  33. IPython team's logic.
  34. '''
  35. cls.ip = get_ipython()
  36. # This is just to get a minimally modified version of the changes
  37. # working
  38. cls.ip.magic('load_ext rpy2.ipython')
  39. def setUp(self):
  40. activate()
  41. def tearDown(self):
  42. # This seems like the safest thing to return to a safe state
  43. self.ip.run_line_magic('Rdevice', 'png')
  44. deactivate()
  45. def test_push(self):
  46. self.ip.push({'X':np.arange(5), 'Y':np.array([3,5,4,6,7])})
  47. self.ip.run_line_magic('Rpush', 'X Y')
  48. np.testing.assert_almost_equal(np.asarray(r('X')), self.ip.user_ns['X'])
  49. np.testing.assert_almost_equal(np.asarray(r('Y')), self.ip.user_ns['Y'])
  50. def test_push_localscope(self):
  51. """Test that Rpush looks for variables in the local scope first."""
  52. self.ip.run_cell('''
  53. def rmagic_addone(u):
  54. %Rpush u
  55. %R result = u+1
  56. %Rpull result
  57. return result[0]
  58. u = 0
  59. result = rmagic_addone(12344)
  60. ''')
  61. result = self.ip.user_ns['result']
  62. np.testing.assert_equal(result, 12345)
  63. @unittest.skipUnless(has_pandas, 'pandas is not available in python')
  64. def test_push_dataframe(self):
  65. df = pd.DataFrame([{'a': 1, 'b': 'bar'}, {'a': 5, 'b': 'foo', 'c': 20}])
  66. self.ip.push({'df':df})
  67. self.ip.run_line_magic('Rpush', 'df')
  68. # This is converted to factors, which are currently converted back to Python
  69. # as integers, so for now we test its representation in R.
  70. sio = StringIO()
  71. rinterface.set_writeconsole(sio.write)
  72. try:
  73. r('print(df$b[1])')
  74. self.assertIn('[1] bar', sio.getvalue())
  75. finally:
  76. rinterface.set_writeconsole(None)
  77. # Values come packaged in arrays, so we unbox them to test.
  78. self.assertEqual(r('df$a[2]')[0], 5)
  79. missing = r('df$c[1]')[0]
  80. assert np.isnan(missing), missing
  81. def test_pull(self):
  82. r('Z=c(11:20)')
  83. self.ip.run_line_magic('Rpull', 'Z')
  84. np.testing.assert_almost_equal(np.asarray(r('Z')), self.ip.user_ns['Z'])
  85. np.testing.assert_almost_equal(self.ip.user_ns['Z'], np.arange(11,21))
  86. def test_Rconverter(self):
  87. # Set up a helper functions
  88. def test_eq_arrays(a,b):
  89. np.testing.assert_array_equal(a,b)
  90. # If we get to dropping numpy requirement, we might use something
  91. # like the following:
  92. # self.assertSequenceEqual(buffer(a).buffer_info(),
  93. # buffer(b).buffer_info())
  94. datapy= np.array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c')],
  95. dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')])
  96. self.ip.user_ns['datapy'] = datapy
  97. self.ip.run_line_magic('Rpush', 'datapy')
  98. # test to see if a copy is being made
  99. v = self.ip.run_line_magic('Rget', 'datapy')
  100. w = self.ip.run_line_magic('Rget', 'datapy')
  101. test_eq_arrays(w['x'], v['x'])
  102. test_eq_arrays(w['y'], v['y'])
  103. self.ip.run_cell_magic('R', '-o datar', 'datar=datapy')
  104. u = self.ip.run_line_magic('Rget', 'datar')
  105. w = self.ip.user_ns['datar']
  106. test_eq_arrays(u['x'], v['x'])
  107. test_eq_arrays(u['y'], v['y'])
  108. test_eq_arrays(w['x'], v['x'])
  109. test_eq_arrays(w['y'], v['y'])
  110. def test_cell_magic(self):
  111. self.ip.push({'x':np.arange(5), 'y':np.array([3,5,4,6,7])})
  112. # For now, print statements are commented out because they print
  113. # erroneous ERRORs when running via rpy2.tests
  114. snippet = '''
  115. print(summary(a))
  116. plot(x, y, pch=23, bg='orange', cex=2)
  117. plot(x, x)
  118. print(summary(x))
  119. r = resid(a)
  120. xc = coef(a)
  121. '''
  122. self.ip.run_cell_magic('R', '-i x,y -o r,xc -w 150 -u mm a=lm(y~x)', snippet)
  123. np.testing.assert_almost_equal(self.ip.user_ns['xc'], [3.2, 0.9])
  124. np.testing.assert_almost_equal(self.ip.user_ns['r'], np.array([-0.2, 0.9, -1. , 0.1, 0.2]))
  125. def test_rmagic_localscope(self):
  126. self.ip.push({'x':0})
  127. self.ip.run_line_magic('R', '-i x -o result result <-x+1')
  128. result = self.ip.user_ns['result']
  129. self.assertEqual(result[0], 1)
  130. self.ip.run_cell('''def rmagic_addone(u):
  131. %R -i u -o result result <- u+1
  132. return result[0]''')
  133. self.ip.run_cell('result = rmagic_addone(1)')
  134. result = self.ip.user_ns['result']
  135. self.assertEqual(result, 2)
  136. self.assertRaises(
  137. NameError,
  138. self.ip.run_line_magic,
  139. "R",
  140. "-i var_not_defined 1+1")
  141. def test_png_plotting_args(self):
  142. '''Exercise the PNG plotting machinery'''
  143. self.ip.push({'x':np.arange(5), 'y':np.array([3,5,4,6,7])})
  144. cell = '''
  145. plot(x, y, pch=23, bg='orange', cex=2)
  146. '''
  147. png_px_args = [' '.join(('--units=px',w,h,p)) for
  148. w, h, p in product(['--width=400 ',''],
  149. ['--height=400',''],
  150. ['-p=10', ''])]
  151. for line in png_px_args:
  152. self.ip.run_line_magic('Rdevice', 'png')
  153. self.ip.run_cell_magic('R', line, cell)
  154. @unittest.skipUnless(rpacks.isinstalled('Cairo'), 'Cairo not installed')
  155. def test_svg_plotting_args(self):
  156. '''Exercise the plotting machinery
  157. To pass SVG tests, we need Cairo installed in R.'''
  158. self.ip.push({'x':np.arange(5), 'y':np.array([3,5,4,6,7])})
  159. cell = '''
  160. plot(x, y, pch=23, bg='orange', cex=2)
  161. '''
  162. basic_args = [' '.join((w,h,p)) for w, h, p in product(['--width=6 ',''],
  163. ['--height=6',''],
  164. ['-p=10', ''])]
  165. for line in basic_args:
  166. self.ip.run_line_magic('Rdevice', 'svg')
  167. self.ip.run_cell_magic('R', line, cell)
  168. png_args = ['--units=in --res=1 ' + s for s in basic_args]
  169. for line in png_args:
  170. self.ip.run_line_magic('Rdevice', 'png')
  171. self.ip.run_cell_magic('R', line, cell)
  172. @unittest.skip('Test for X11 skipped.')
  173. def test_plotting_X11(self):
  174. self.ip.push({'x':np.arange(5), 'y':np.array([3,5,4,6,7])})
  175. cell = '''
  176. plot(x, y, pch=23, bg='orange', cex=2)
  177. '''
  178. self.ip.run_line_magic('Rdevice', 'X11')
  179. self.ip.run_cell_magic('R', '', cell)