##// END OF EJS Templates
Merge pull request #8545 from Carreau/remove-magic...
Min RK -
r21484:7298a152 merge
parent child Browse files
Show More
@@ -1,43 +1,21 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 **DEPRECATED**
4
3 The cython magic has been integrated into Cython itself,
5 The cython magic has been integrated into Cython itself,
4 which is now released in version 0.21.
6 which is now released in version 0.21.
5
7
6 cf github `Cython` organisation, `Cython` repo, under the
8 cf github `Cython` organisation, `Cython` repo, under the
7 file `Cython/Build/IpythonMagic.py`
9 file `Cython/Build/IpythonMagic.py`
8 """
10 """
9 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
10 # Copyright (C) 2010-2011, IPython Development Team.
12 # Copyright (C) 2010-2011, IPython Development Team.
11 #
12 # Distributed under the terms of the Modified BSD License.
13 #
14 # The full license is in the file COPYING.txt, distributed with this software.
15 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
16
14
17 from __future__ import print_function
15 import warnings
18
19 import IPython.utils.version as version
20
21 try:
22 import Cython
23 except:
24 Cython = None
25
26 try:
27 from Cython.Build.IpythonMagic import CythonMagics
28 except :
29 pass
30
31
16
32 ## still load the magic in IPython 3.x, remove completely in future versions.
17 ## still load the magic in IPython 3.x, remove completely in future versions.
33 def load_ipython_extension(ip):
18 def load_ipython_extension(ip):
34 """Load the extension in IPython."""
19 """Load the extension in IPython."""
35
20
36 print("""The Cython magic has been moved to the Cython package, hence """)
21 warnings.warn("""The Cython magic has been moved to the Cython package""")
37 print("""`%load_ext cythonmagic` is deprecated; please use `%load_ext Cython` instead.""")
38
39 if Cython is None or not version.check_version(Cython.__version__, "0.21"):
40 print("You need Cython version >=0.21 to use the Cython magic")
41 return
42 print("""\nThough, because I am nice, I'll still try to load it for you this time.""")
43 Cython.load_ipython_extension(ip)
This diff has been collapsed as it changes many lines, (694 lines changed) Show them Hide them
@@ -1,702 +1,12 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
3 ======
4 Rmagic
5 ======
6
7 Magic command interface for interactive work with R via rpy2
8
9 .. note::
10
11 The ``rpy2`` package needs to be installed separately. It
12 can be obtained using ``easy_install`` or ``pip``.
13
14 You will also need a working copy of R.
15
16 Usage
17 =====
18
19 To enable the magics below, execute ``%load_ext rmagic``.
20
21 ``%R``
22
23 {R_DOC}
24
25 ``%Rpush``
26
27 {RPUSH_DOC}
28
29 ``%Rpull``
30
31 {RPULL_DOC}
32
33 ``%Rget``
34
35 {RGET_DOC}
36
37 """
38 from __future__ import print_function
39
2
40 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
41 # Copyright (C) 2012 The IPython Development Team
4 # Copyright (C) 2012 The IPython Development Team
42 #
43 # Distributed under the terms of the BSD License. The full license is in
44 # the file COPYING, distributed as part of this software.
45 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
46
6
47 import sys
48 import tempfile
49 from glob import glob
50 from shutil import rmtree
51 import warnings
7 import warnings
52
8
53 # numpy and rpy2 imports
54
55 import numpy as np
56
57 import rpy2.rinterface as ri
58 import rpy2.robjects as ro
59 try:
60 from rpy2.robjects import pandas2ri
61 pandas2ri.activate()
62 except ImportError:
63 pandas2ri = None
64 from rpy2.robjects import numpy2ri
65 numpy2ri.activate()
66
67 # IPython imports
68
69 from IPython.core.displaypub import publish_display_data
70 from IPython.core.magic import (Magics, magics_class, line_magic,
71 line_cell_magic, needs_local_scope)
72 from IPython.core.magic_arguments import (
73 argument, magic_arguments, parse_argstring
74 )
75 from simplegeneric import generic
76 from IPython.utils.py3compat import (str_to_unicode, unicode_to_str, PY3,
77 unicode_type)
78 from IPython.utils.text import dedent
79
80 class RInterpreterError(ri.RRuntimeError):
81 """An error when running R code in a %%R magic cell."""
82 def __init__(self, line, err, stdout):
83 self.line = line
84 self.err = err.rstrip()
85 self.stdout = stdout.rstrip()
86
87 def __unicode__(self):
88 s = 'Failed to parse and evaluate line %r.\nR error message: %r' % \
89 (self.line, self.err)
90 if self.stdout and (self.stdout != self.err):
91 s += '\nR stdout:\n' + self.stdout
92 return s
93
94 if PY3:
95 __str__ = __unicode__
96 else:
97 def __str__(self):
98 return unicode_to_str(unicode(self), 'utf-8')
99
100 def Rconverter(Robj, dataframe=False):
101 """
102 Convert an object in R's namespace to one suitable
103 for ipython's namespace.
104
105 For a data.frame, it tries to return a structured array.
106 It first checks for colnames, then names.
107 If all are NULL, it returns np.asarray(Robj), else
108 it tries to construct a recarray
109
110 Parameters
111 ----------
112
113 Robj: an R object returned from rpy2
114 """
115 is_data_frame = ro.r('is.data.frame')
116 colnames = ro.r('colnames')
117 rownames = ro.r('rownames') # with pandas, these could be used for the index
118 names = ro.r('names')
119
120 if dataframe:
121 as_data_frame = ro.r('as.data.frame')
122 cols = colnames(Robj)
123 _names = names(Robj)
124 if cols != ri.NULL:
125 Robj = as_data_frame(Robj)
126 names = tuple(np.array(cols))
127 elif _names != ri.NULL:
128 names = tuple(np.array(_names))
129 else: # failed to find names
130 return np.asarray(Robj)
131 Robj = np.rec.fromarrays(Robj, names = names)
132 return np.asarray(Robj)
133
134 @generic
135 def pyconverter(pyobj):
136 """Convert Python objects to R objects. Add types using the decorator:
137
138 @pyconverter.when_type
139 """
140 return pyobj
141
142 # The default conversion for lists seems to make them a nested list. That has
143 # some advantages, but is rarely convenient, so for interactive use, we convert
144 # lists to a numpy array, which becomes an R vector.
145 @pyconverter.when_type(list)
146 def pyconverter_list(pyobj):
147 return np.asarray(pyobj)
148
149 if pandas2ri is None:
150 # pandas2ri was new in rpy2 2.3.3, so for now we'll fallback to pandas'
151 # conversion function.
152 try:
153 from pandas import DataFrame
154 from pandas.rpy.common import convert_to_r_dataframe
155 @pyconverter.when_type(DataFrame)
156 def pyconverter_dataframe(pyobj):
157 return convert_to_r_dataframe(pyobj, strings_as_factors=True)
158 except ImportError:
159 pass
160
161 @magics_class
162 class RMagics(Magics):
163 """A set of magics useful for interactive work with R via rpy2.
164 """
165
166 def __init__(self, shell, Rconverter=Rconverter,
167 pyconverter=pyconverter,
168 cache_display_data=False):
169 """
170 Parameters
171 ----------
172
173 shell : IPython shell
174
175 Rconverter : callable
176 To be called on values taken from R before putting them in the
177 IPython namespace.
178
179 pyconverter : callable
180 To be called on values in ipython namespace before
181 assigning to variables in rpy2.
182
183 cache_display_data : bool
184 If True, the published results of the final call to R are
185 cached in the variable 'display_cache'.
186
187 """
188 super(RMagics, self).__init__(shell)
189 self.cache_display_data = cache_display_data
190
191 self.r = ro.R()
192
193 self.Rstdout_cache = []
194 self.pyconverter = pyconverter
195 self.Rconverter = Rconverter
196
197 def eval(self, line):
198 '''
199 Parse and evaluate a line of R code with rpy2.
200 Returns the output to R's stdout() connection,
201 the value generated by evaluating the code, and a
202 boolean indicating whether the return value would be
203 visible if the line of code were evaluated in an R REPL.
204
205 R Code evaluation and visibility determination are
206 done via an R call of the form withVisible({<code>})
207
208 '''
209 old_writeconsole = ri.get_writeconsole()
210 ri.set_writeconsole(self.write_console)
211 try:
212 res = ro.r("withVisible({%s\n})" % line)
213 value = res[0] #value (R object)
214 visible = ro.conversion.ri2py(res[1])[0] #visible (boolean)
215 except (ri.RRuntimeError, ValueError) as exception:
216 warning_or_other_msg = self.flush() # otherwise next return seems to have copy of error
217 raise RInterpreterError(line, str_to_unicode(str(exception)), warning_or_other_msg)
218 text_output = self.flush()
219 ri.set_writeconsole(old_writeconsole)
220 return text_output, value, visible
221
222 def write_console(self, output):
223 '''
224 A hook to capture R's stdout in a cache.
225 '''
226 self.Rstdout_cache.append(output)
227
228 def flush(self):
229 '''
230 Flush R's stdout cache to a string, returning the string.
231 '''
232 value = ''.join([str_to_unicode(s, 'utf-8') for s in self.Rstdout_cache])
233 self.Rstdout_cache = []
234 return value
235
236 @needs_local_scope
237 @line_magic
238 def Rpush(self, line, local_ns=None):
239 '''
240 A line-level magic for R that pushes
241 variables from python to rpy2. The line should be made up
242 of whitespace separated variable names in the IPython
243 namespace::
244
245 In [7]: import numpy as np
246
247 In [8]: X = np.array([4.5,6.3,7.9])
248
249 In [9]: X.mean()
250 Out[9]: 6.2333333333333343
251
252 In [10]: %Rpush X
253
254 In [11]: %R mean(X)
255 Out[11]: array([ 6.23333333])
256
257 '''
258 if local_ns is None:
259 local_ns = {}
260
261 inputs = line.split(' ')
262 for input in inputs:
263 try:
264 val = local_ns[input]
265 except KeyError:
266 try:
267 val = self.shell.user_ns[input]
268 except KeyError:
269 # reraise the KeyError as a NameError so that it looks like
270 # the standard python behavior when you use an unnamed
271 # variable
272 raise NameError("name '%s' is not defined" % input)
273
274 self.r.assign(input, self.pyconverter(val))
275
276 @magic_arguments()
277 @argument(
278 '-d', '--as_dataframe', action='store_true',
279 default=False,
280 help='Convert objects to data.frames before returning to ipython.'
281 )
282 @argument(
283 'outputs',
284 nargs='*',
285 )
286 @line_magic
287 def Rpull(self, line):
288 '''
289 A line-level magic for R that pulls
290 variables from python to rpy2::
291
292 In [18]: _ = %R x = c(3,4,6.7); y = c(4,6,7); z = c('a',3,4)
293
294 In [19]: %Rpull x y z
295
296 In [20]: x
297 Out[20]: array([ 3. , 4. , 6.7])
298
299 In [21]: y
300 Out[21]: array([ 4., 6., 7.])
301
302 In [22]: z
303 Out[22]:
304 array(['a', '3', '4'],
305 dtype='|S1')
306
307
308 If --as_dataframe, then each object is returned as a structured array
309 after first passed through "as.data.frame" in R before
310 being calling self.Rconverter.
311 This is useful when a structured array is desired as output, or
312 when the object in R has mixed data types.
313 See the %%R docstring for more examples.
314
315 Notes
316 -----
317
318 Beware that R names can have '.' so this is not fool proof.
319 To avoid this, don't name your R objects with '.'s...
320
321 '''
322 args = parse_argstring(self.Rpull, line)
323 outputs = args.outputs
324 for output in outputs:
325 self.shell.push({output:self.Rconverter(self.r(output),dataframe=args.as_dataframe)})
326
327 @magic_arguments()
328 @argument(
329 '-d', '--as_dataframe', action='store_true',
330 default=False,
331 help='Convert objects to data.frames before returning to ipython.'
332 )
333 @argument(
334 'output',
335 nargs=1,
336 type=str,
337 )
338 @line_magic
339 def Rget(self, line):
340 '''
341 Return an object from rpy2, possibly as a structured array (if possible).
342 Similar to Rpull except only one argument is accepted and the value is
343 returned rather than pushed to self.shell.user_ns::
344
345 In [3]: dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')]
346
347 In [4]: datapy = np.array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5, 'e')], dtype=dtype)
348
349 In [5]: %R -i datapy
350
351 In [6]: %Rget datapy
352 Out[6]:
353 array([['1', '2', '3', '4'],
354 ['2', '3', '2', '5'],
355 ['a', 'b', 'c', 'e']],
356 dtype='|S1')
357
358 In [7]: %Rget -d datapy
359 Out[7]:
360 array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5.0, 'e')],
361 dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')])
362
363 '''
364 args = parse_argstring(self.Rget, line)
365 output = args.output
366 return self.Rconverter(self.r(output[0]),dataframe=args.as_dataframe)
367
368
369 @magic_arguments()
370 @argument(
371 '-i', '--input', action='append',
372 help='Names of input variable from shell.user_ns to be assigned to R variables of the same names after calling self.pyconverter. Multiple names can be passed separated only by commas with no whitespace.'
373 )
374 @argument(
375 '-o', '--output', action='append',
376 help='Names of variables to be pushed from rpy2 to shell.user_ns after executing cell body and applying self.Rconverter. Multiple names can be passed separated only by commas with no whitespace.'
377 )
378 @argument(
379 '-w', '--width', type=int,
380 help='Width of png plotting device sent as an argument to *png* in R.'
381 )
382 @argument(
383 '-h', '--height', type=int,
384 help='Height of png plotting device sent as an argument to *png* in R.'
385 )
386
387 @argument(
388 '-d', '--dataframe', action='append',
389 help='Convert these objects to data.frames and return as structured arrays.'
390 )
391 @argument(
392 '-u', '--units', type=unicode_type, choices=["px", "in", "cm", "mm"],
393 help='Units of png plotting device sent as an argument to *png* in R. One of ["px", "in", "cm", "mm"].'
394 )
395 @argument(
396 '-r', '--res', type=int,
397 help='Resolution of png plotting device sent as an argument to *png* in R. Defaults to 72 if *units* is one of ["in", "cm", "mm"].'
398 )
399 @argument(
400 '-p', '--pointsize', type=int,
401 help='Pointsize of png plotting device sent as an argument to *png* in R.'
402 )
403 @argument(
404 '-b', '--bg',
405 help='Background of png plotting device sent as an argument to *png* in R.'
406 )
407 @argument(
408 '-n', '--noreturn',
409 help='Force the magic to not return anything.',
410 action='store_true',
411 default=False
412 )
413 @argument(
414 'code',
415 nargs='*',
416 )
417 @needs_local_scope
418 @line_cell_magic
419 def R(self, line, cell=None, local_ns=None):
420 '''
421 Execute code in R, and pull some of the results back into the Python namespace.
422
423 In line mode, this will evaluate an expression and convert the returned value to a Python object.
424 The return value is determined by rpy2's behaviour of returning the result of evaluating the
425 final line.
426
427 Multiple R lines can be executed by joining them with semicolons::
428
429 In [9]: %R X=c(1,4,5,7); sd(X); mean(X)
430 Out[9]: array([ 4.25])
431
432 In cell mode, this will run a block of R code. The resulting value
433 is printed if it would printed be when evaluating the same code
434 within a standard R REPL.
435
436 Nothing is returned to python by default in cell mode::
437
438 In [10]: %%R
439 ....: Y = c(2,4,3,9)
440 ....: summary(lm(Y~X))
441
442 Call:
443 lm(formula = Y ~ X)
444
445 Residuals:
446 1 2 3 4
447 0.88 -0.24 -2.28 1.64
448
449 Coefficients:
450 Estimate Std. Error t value Pr(>|t|)
451 (Intercept) 0.0800 2.3000 0.035 0.975
452 X 1.0400 0.4822 2.157 0.164
453
454 Residual standard error: 2.088 on 2 degrees of freedom
455 Multiple R-squared: 0.6993,Adjusted R-squared: 0.549
456 F-statistic: 4.651 on 1 and 2 DF, p-value: 0.1638
457
458 In the notebook, plots are published as the output of the cell::
459
460 %R plot(X, Y)
461
462 will create a scatter plot of X bs Y.
463
464 If cell is not None and line has some R code, it is prepended to
465 the R code in cell.
466
467 Objects can be passed back and forth between rpy2 and python via the -i -o flags in line::
468
469 In [14]: Z = np.array([1,4,5,10])
470
471 In [15]: %R -i Z mean(Z)
472 Out[15]: array([ 5.])
473
474
475 In [16]: %R -o W W=Z*mean(Z)
476 Out[16]: array([ 5., 20., 25., 50.])
477
478 In [17]: W
479 Out[17]: array([ 5., 20., 25., 50.])
480
481 The return value is determined by these rules:
482
483 * If the cell is not None, the magic returns None.
484
485 * If the cell evaluates as False, the resulting value is returned
486 unless the final line prints something to the console, in
487 which case None is returned.
488
489 * If the final line results in a NULL value when evaluated
490 by rpy2, then None is returned.
491
492 * No attempt is made to convert the final value to a structured array.
493 Use the --dataframe flag or %Rget to push / return a structured array.
494
495 * If the -n flag is present, there is no return value.
496
497 * A trailing ';' will also result in no return value as the last
498 value in the line is an empty string.
499
500 The --dataframe argument will attempt to return structured arrays.
501 This is useful for dataframes with
502 mixed data types. Note also that for a data.frame,
503 if it is returned as an ndarray, it is transposed::
504
505 In [18]: dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')]
506
507 In [19]: datapy = np.array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5, 'e')], dtype=dtype)
508
509 In [20]: %%R -o datar
510 datar = datapy
511 ....:
512
513 In [21]: datar
514 Out[21]:
515 array([['1', '2', '3', '4'],
516 ['2', '3', '2', '5'],
517 ['a', 'b', 'c', 'e']],
518 dtype='|S1')
519
520 In [22]: %%R -d datar
521 datar = datapy
522 ....:
523
524 In [23]: datar
525 Out[23]:
526 array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5.0, 'e')],
527 dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')])
528
529 The --dataframe argument first tries colnames, then names.
530 If both are NULL, it returns an ndarray (i.e. unstructured)::
531
532 In [1]: %R mydata=c(4,6,8.3); NULL
533
534 In [2]: %R -d mydata
535
536 In [3]: mydata
537 Out[3]: array([ 4. , 6. , 8.3])
538
539 In [4]: %R names(mydata) = c('a','b','c'); NULL
540
541 In [5]: %R -d mydata
542
543 In [6]: mydata
544 Out[6]:
545 array((4.0, 6.0, 8.3),
546 dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8')])
547
548 In [7]: %R -o mydata
549
550 In [8]: mydata
551 Out[8]: array([ 4. , 6. , 8.3])
552
553 '''
554
555 args = parse_argstring(self.R, line)
556
557 # arguments 'code' in line are prepended to
558 # the cell lines
559
560 if cell is None:
561 code = ''
562 return_output = True
563 line_mode = True
564 else:
565 code = cell
566 return_output = False
567 line_mode = False
568
569 code = ' '.join(args.code) + code
570
571 # if there is no local namespace then default to an empty dict
572 if local_ns is None:
573 local_ns = {}
574
575 if args.input:
576 for input in ','.join(args.input).split(','):
577 try:
578 val = local_ns[input]
579 except KeyError:
580 try:
581 val = self.shell.user_ns[input]
582 except KeyError:
583 raise NameError("name '%s' is not defined" % input)
584 self.r.assign(input, self.pyconverter(val))
585
586 if getattr(args, 'units') is not None:
587 if args.units != "px" and getattr(args, 'res') is None:
588 args.res = 72
589 args.units = '"%s"' % args.units
590
591 png_argdict = dict([(n, getattr(args, n)) for n in ['units', 'res', 'height', 'width', 'bg', 'pointsize']])
592 png_args = ','.join(['%s=%s' % (o,v) for o, v in png_argdict.items() if v is not None])
593 # execute the R code in a temporary directory
594
595 tmpd = tempfile.mkdtemp()
596 self.r('png("%s/Rplots%%03d.png",%s)' % (tmpd.replace('\\', '/'), png_args))
597
598 text_output = ''
599 try:
600 if line_mode:
601 for line in code.split(';'):
602 text_result, result, visible = self.eval(line)
603 text_output += text_result
604 if text_result:
605 # the last line printed something to the console so we won't return it
606 return_output = False
607 else:
608 text_result, result, visible = self.eval(code)
609 text_output += text_result
610 if visible:
611 old_writeconsole = ri.get_writeconsole()
612 ri.set_writeconsole(self.write_console)
613 ro.r.show(result)
614 text_output += self.flush()
615 ri.set_writeconsole(old_writeconsole)
616
617 except RInterpreterError as e:
618 print(e.stdout)
619 if not e.stdout.endswith(e.err):
620 print(e.err)
621 rmtree(tmpd)
622 return
623 finally:
624 self.r('dev.off()')
625
626 # read out all the saved .png files
627
628 images = [open(imgfile, 'rb').read() for imgfile in glob("%s/Rplots*png" % tmpd)]
629
630 # now publish the images
631 # mimicking IPython/zmq/pylab/backend_inline.py
632 fmt = 'png'
633 mimetypes = { 'png' : 'image/png', 'svg' : 'image/svg+xml' }
634 mime = mimetypes[fmt]
635
636 # publish the printed R objects, if any
637
638 display_data = []
639 if text_output:
640 display_data.append(('RMagic.R', {'text/plain':text_output}))
641
642 # flush text streams before sending figures, helps a little with output
643 for image in images:
644 # synchronization in the console (though it's a bandaid, not a real sln)
645 sys.stdout.flush(); sys.stderr.flush()
646 display_data.append(('RMagic.R', {mime: image}))
647
648 # kill the temporary directory
649 rmtree(tmpd)
650
651 # try to turn every output into a numpy array
652 # this means that output are assumed to be castable
653 # as numpy arrays
654
655 if args.output:
656 for output in ','.join(args.output).split(','):
657 self.shell.push({output:self.Rconverter(self.r(output), dataframe=False)})
658
659 if args.dataframe:
660 for output in ','.join(args.dataframe).split(','):
661 self.shell.push({output:self.Rconverter(self.r(output), dataframe=True)})
662
663 for tag, disp_d in display_data:
664 publish_display_data(data=disp_d, source=tag)
665
666 # this will keep a reference to the display_data
667 # which might be useful to other objects who happen to use
668 # this method
669
670 if self.cache_display_data:
671 self.display_cache = display_data
672
673 # if in line mode and return_output, return the result as an ndarray
674 if return_output and not args.noreturn:
675 if result != ri.NULL:
676 return self.Rconverter(result, dataframe=False)
677
678 __doc__ = __doc__.format(
679 R_DOC = dedent(RMagics.R.__doc__),
680 RPUSH_DOC = dedent(RMagics.Rpush.__doc__),
681 RPULL_DOC = dedent(RMagics.Rpull.__doc__),
682 RGET_DOC = dedent(RMagics.Rget.__doc__)
683 )
684
685
686 def load_ipython_extension(ip):
9 def load_ipython_extension(ip):
687 """Load the extension in IPython."""
10 """Load the extension in IPython."""
688 warnings.warn("The rmagic extension in IPython is deprecated in favour of "
11 warnings.warn("The rmagic extension in IPython has moved to "
689 "rpy2.ipython. If available, that will be loaded instead.\n"
12 "`rpy2.ipython`, please see `rpy2` documentation.")
690 "http://rpy.sourceforge.net/")
691 try:
692 import rpy2.ipython
693 except ImportError:
694 pass # Fall back to our own implementation for now
695 else:
696 return rpy2.ipython.load_ipython_extension(ip)
697
698 ip.register_magics(RMagics)
699 # Initialising rpy2 interferes with readline. Since, at this point, we've
700 # probably just loaded rpy2, we reset the delimiters. See issue gh-2759.
701 if ip.has_readline:
702 ip.readline.set_completer_delims(ip.readline_delims)
@@ -1,170 +1,32 b''
1 """
1 """
2 **DEPRECATED**
3
2 A print function that pretty prints sympy Basic objects.
4 A print function that pretty prints sympy Basic objects.
3
5
4 :moduleauthor: Brian Granger
6 :moduleauthor: Brian Granger
5
7
6 Usage
8 Usage
7 =====
9 =====
8
10
9 Once the extension is loaded, Sympy Basic objects are automatically
11 Once the extension is loaded, Sympy Basic objects are automatically
10 pretty-printed.
12 pretty-printed.
11
13
12 As of SymPy 0.7.2, maintenance of this extension has moved to SymPy under
14 As of SymPy 0.7.2, maintenance of this extension has moved to SymPy under
13 sympy.interactive.ipythonprinting, any modifications to account for changes to
15 sympy.interactive.ipythonprinting, any modifications to account for changes to
14 SymPy should be submitted to SymPy rather than changed here. This module is
16 SymPy should be submitted to SymPy rather than changed here. This module is
15 maintained here for backwards compatablitiy with old SymPy versions.
17 maintained here for backwards compatablitiy with old SymPy versions.
16
18
17 """
19 """
18 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
19 # Copyright (C) 2008 The IPython Development Team
21 # Copyright (C) 2008 The IPython Development Team
20 #
21 # Distributed under the terms of the BSD License. The full license is in
22 # the file COPYING, distributed as part of this software.
23 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
24
23
25 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
26 # Imports
25 # Imports
27 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
28
27
29 from IPython.lib.latextools import latex_to_png
30 from IPython.utils.py3compat import string_types
31
32 try:
33 from sympy import pretty, latex
34 except ImportError:
35 pass
36
37 import warnings
28 import warnings
38
29
39 #-----------------------------------------------------------------------------
40 # Definitions of special display functions for use with IPython
41 #-----------------------------------------------------------------------------
42
43 def print_basic_unicode(o, p, cycle):
44 """A function to pretty print sympy Basic objects."""
45 if cycle:
46 return p.text('Basic(...)')
47 out = pretty(o, use_unicode=True)
48 if '\n' in out:
49 p.text(u'\n')
50 p.text(out)
51
52
53 def print_png(o):
54 """
55 A function to display sympy expression using inline style LaTeX in PNG.
56 """
57 s = latex(o, mode='inline')
58 # mathtext does not understand certain latex flags, so we try to replace
59 # them with suitable subs.
60 s = s.replace('\\operatorname','')
61 s = s.replace('\\overline', '\\bar')
62 png = latex_to_png(s)
63 return png
64
65
66 def print_display_png(o):
67 """
68 A function to display sympy expression using display style LaTeX in PNG.
69 """
70 s = latex(o, mode='plain')
71 s = s.strip('$')
72 # As matplotlib does not support display style, dvipng backend is
73 # used here.
74 png = latex_to_png(s, backend='dvipng', wrap=True)
75 return png
76
77
78 def can_print_latex(o):
79 """
80 Return True if type o can be printed with LaTeX.
81
82 If o is a container type, this is True if and only if every element of o
83 can be printed with LaTeX.
84 """
85 import sympy
86 if isinstance(o, (list, tuple, set, frozenset)):
87 return all(can_print_latex(i) for i in o)
88 elif isinstance(o, dict):
89 return all((isinstance(i, string_types) or can_print_latex(i)) and can_print_latex(o[i]) for i in o)
90 elif isinstance(o,(sympy.Basic, sympy.matrices.Matrix, int, long, float)):
91 return True
92 return False
93
94 def print_latex(o):
95 """A function to generate the latex representation of sympy
96 expressions."""
97 if can_print_latex(o):
98 s = latex(o, mode='plain')
99 s = s.replace('\\dag','\\dagger')
100 s = s.strip('$')
101 return '$$%s$$' % s
102 # Fallback to the string printer
103 return None
104
105 _loaded = False
106
107 def load_ipython_extension(ip):
30 def load_ipython_extension(ip):
108 """Load the extension in IPython."""
31 warnings.warn("The sympyprinting extension as move to `sympy`, "
109 import sympy
32 "use `from sympy import init_printing; init_printing()`")
110
111 # sympyprinting extension has been moved to SymPy as of 0.7.2, if it
112 # exists there, warn the user and import it
113 try:
114 import sympy.interactive.ipythonprinting
115 except ImportError:
116 pass
117 else:
118 warnings.warn("The sympyprinting extension in IPython is deprecated, "
119 "use 'from sympy import init_printing; init_printing()'")
120 ip.extension_manager.load_extension('sympy.interactive.ipythonprinting')
121 return
122
123 global _loaded
124 if not _loaded:
125 plaintext_formatter = ip.display_formatter.formatters['text/plain']
126
127 for cls in (object, str):
128 plaintext_formatter.for_type(cls, print_basic_unicode)
129
130 printable_containers = [list, tuple]
131
132 # set and frozen set were broken with SymPy's latex() function, but
133 # was fixed in the 0.7.1-git development version. See
134 # http://code.google.com/p/sympy/issues/detail?id=3062.
135 if sympy.__version__ > '0.7.1':
136 printable_containers += [set, frozenset]
137 else:
138 plaintext_formatter.for_type(cls, print_basic_unicode)
139
140 plaintext_formatter.for_type_by_name(
141 'sympy.core.basic', 'Basic', print_basic_unicode
142 )
143 plaintext_formatter.for_type_by_name(
144 'sympy.matrices.matrices', 'Matrix', print_basic_unicode
145 )
146
147 png_formatter = ip.display_formatter.formatters['image/png']
148
149 png_formatter.for_type_by_name(
150 'sympy.core.basic', 'Basic', print_png
151 )
152 png_formatter.for_type_by_name(
153 'sympy.matrices.matrices', 'Matrix', print_display_png
154 )
155 for cls in [dict, int, long, float] + printable_containers:
156 png_formatter.for_type(cls, print_png)
157
158 latex_formatter = ip.display_formatter.formatters['text/latex']
159 latex_formatter.for_type_by_name(
160 'sympy.core.basic', 'Basic', print_latex
161 )
162 latex_formatter.for_type_by_name(
163 'sympy.matrices.matrices', 'Matrix', print_latex
164 )
165
166 for cls in printable_containers:
167 # Use LaTeX only if every element is printable by latex
168 latex_formatter.for_type(cls, print_latex)
169
170 _loaded = True
General Comments 0
You need to be logged in to leave comments. Login now