##// END OF EJS Templates
More improvements to the display system....
Brian Granger -
Show More
@@ -0,0 +1,62 b''
1 # -*- coding: utf-8 -*-
2 """Tools for handling LaTeX.
3
4 Authors:
5
6 * Brian Granger
7 """
8 #-----------------------------------------------------------------------------
9 # Copyright (c) 2010, IPython Development Team.
10 #
11 # Distributed under the terms of the Modified BSD License.
12 #
13 # The full license is in the file COPYING.txt, distributed with this software.
14 #-----------------------------------------------------------------------------
15
16 #-----------------------------------------------------------------------------
17 # Imports
18 #-----------------------------------------------------------------------------
19
20 from StringIO import StringIO
21 from base64 import encodestring
22
23 #-----------------------------------------------------------------------------
24 # Tools
25 #-----------------------------------------------------------------------------
26
27
28 def latex_to_png(s, encode=True):
29 """Render a LaTeX string to PNG using matplotlib.mathtext.
30
31 Parameters
32 ----------
33 s : str
34 The raw string containing valid inline LaTeX.
35 encode : bool, optional
36 Should the PNG data bebase64 encoded to make it JSON'able.
37 """
38 from matplotlib import mathtext
39
40 mt = mathtext.MathTextParser('bitmap')
41 f = StringIO()
42 mt.to_png(f, s, fontsize=12)
43 bin_data = f.getvalue()
44 if encode:
45 bin_data = encodestring(bin_data)
46 return bin_data
47
48 _data_uri_template_png = """<img src="data:image/png;base64,%s" alt=%s />"""
49
50 def latex_to_html(s, alt='image'):
51 """Render LaTeX to HTML with embedded PNG data using data URIs.
52
53 Parameters
54 ----------
55 s : str
56 The raw string containing valid inline LateX.
57 alt : str
58 The alt text to use for the HTML.
59 """
60 base64_data = latex_to_png(s, encode=True)
61 return _data_uri_template_png % (base64_data, alt)
62
@@ -48,6 +48,17 b' def display(obj, include=None, exclude=None):'
48 publish('IPython.core.display.display', format_dict)
48 publish('IPython.core.display.display', format_dict)
49
49
50
50
51 def display_pretty(obj):
52 """Display the pretty (default) representation of an object.
53
54 Parameters
55 ----------
56 obj : object
57 The Python object to display.
58 """
59 display(obj, include=['text/plain'])
60
61
51 def display_html(obj):
62 def display_html(obj):
52 """Display the HTML representation of an object.
63 """Display the HTML representation of an object.
53
64
@@ -15,6 +15,10 b' Authors:'
15 # The full license is in the file COPYING.txt, distributed with this software.
15 # The full license is in the file COPYING.txt, distributed with this software.
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 #-----------------------------------------------------------------------------
19 # Imports
20 #-----------------------------------------------------------------------------
21
18 # Stdlib imports
22 # Stdlib imports
19 import abc
23 import abc
20 # We must use StringIO, as cStringIO doesn't handle unicode properly.
24 # We must use StringIO, as cStringIO doesn't handle unicode properly.
@@ -259,6 +263,23 b' class BaseFormatter(Configurable):'
259 self.deferred_printers[key] = func
263 self.deferred_printers[key] = func
260 return oldfunc
264 return oldfunc
261
265
266 def _in_deferred_types(self, cls):
267 """
268 Check if the given class is specified in the deferred type registry.
269
270 Returns the printer from the registry if it exists, and None if the
271 class is not in the registry. Successful matches will be moved to the
272 regular type registry for future use.
273 """
274 mod = getattr(cls, '__module__', None)
275 name = getattr(cls, '__name__', None)
276 key = (mod, name)
277 printer = None
278 if key in self.deferred_printers:
279 # Move the printer over to the regular registry.
280 printer = self.deferred_printers.pop(key)
281 self.type_printers[cls] = printer
282 return printer
262
283
263 class PlainTextFormatter(BaseFormatter):
284 class PlainTextFormatter(BaseFormatter):
264 """The default pretty-printer.
285 """The default pretty-printer.
@@ -14,7 +14,9 b' Authors:'
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 from sympy import pretty
17 from IPython.lib.latextools import latex_to_png
18
19 from sympy import pretty, latex
18
20
19 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
20 # Definitions of magic functions for use with IPython
22 # Definitions of magic functions for use with IPython
@@ -30,6 +32,12 b' def print_basic_unicode(o, p, cycle):'
30 p.text(out)
32 p.text(out)
31
33
32
34
35 def print_png(o):
36 """A funciton to display sympy expression using LaTex -> PNG."""
37 s = latex(o)
38 png = latex_to_png(s, encode=True)
39 return png
40
33 _loaded = False
41 _loaded = False
34
42
35
43
@@ -41,5 +49,9 b' def load_ipython_extension(ip):'
41 plaintext_formatter.for_type_by_name(
49 plaintext_formatter.for_type_by_name(
42 'sympy.core.basic', 'Basic', print_basic_unicode
50 'sympy.core.basic', 'Basic', print_basic_unicode
43 )
51 )
52 png_formatter = ip.display_formatter.formatters['image/png']
53 png_formatter.for_type_by_name(
54 'sympy.core.basic', 'Basic', print_png
55 )
44 _loaded = True
56 _loaded = True
45
57
@@ -210,6 +210,8 b' class IPythonWidget(FrontendWidget):'
210 elif data.has_key('text/plain'):
210 elif data.has_key('text/plain'):
211 text = data['text/plain']
211 text = data['text/plain']
212 self._append_plain_text(text)
212 self._append_plain_text(text)
213 # This newline seems to be needed for text and html output.
214 self._append_plain_text(u'\n')
213
215
214 def _started_channels(self):
216 def _started_channels(self):
215 """ Reimplemented to make a history request.
217 """ Reimplemented to make a history request.
@@ -1,6 +1,7 b''
1 # System library imports
1 # System library imports
2 import os
2 import os
3 import re
3 import re
4 from base64 import decodestring
4 from PyQt4 import QtCore, QtGui
5 from PyQt4 import QtCore, QtGui
5
6
6 # Local imports
7 # Local imports
@@ -74,6 +75,13 b' class RichIPythonWidget(IPythonWidget):'
74 # TODO: try/except this call.
75 # TODO: try/except this call.
75 self._append_svg(data['image/svg+xml'])
76 self._append_svg(data['image/svg+xml'])
76 self._append_html(self.output_sep2)
77 self._append_html(self.output_sep2)
78 elif data.has_key('image/png'):
79 self._append_plain_text(self.output_sep)
80 self._append_html(self._make_out_prompt(prompt_number))
81 # TODO: try/except these calls
82 png = decodestring(data['image/png'])
83 self._append_png(png)
84 self._append_html(self.output_sep2)
77 else:
85 else:
78 # Default back to the plain text representation.
86 # Default back to the plain text representation.
79 return super(RichIPythonWidget, self)._handle_pyout(msg)
87 return super(RichIPythonWidget, self)._handle_pyout(msg)
@@ -91,6 +99,12 b' class RichIPythonWidget(IPythonWidget):'
91 svg = data['image/svg+xml']
99 svg = data['image/svg+xml']
92 # TODO: try/except this call.
100 # TODO: try/except this call.
93 self._append_svg(svg)
101 self._append_svg(svg)
102 elif data.has_key('image/png'):
103 # TODO: try/except these calls
104 # PNG data is base64 encoded as it passes over the network
105 # in a JSON structure so we decode it.
106 png = decodestring(data['image/png'])
107 self._append_png(png)
94 else:
108 else:
95 # Default back to the plain text representation.
109 # Default back to the plain text representation.
96 return super(RichIPythonWidget, self)._handle_display_data(msg)
110 return super(RichIPythonWidget, self)._handle_display_data(msg)
@@ -135,6 +149,21 b' class RichIPythonWidget(IPythonWidget):'
135 cursor.insertImage(format)
149 cursor.insertImage(format)
136 cursor.insertBlock()
150 cursor.insertBlock()
137
151
152 def _append_png(self, png):
153 """ Append raw svg data to the widget.
154 """
155 try:
156 image = QtGui.QImage()
157 image.loadFromData(png, 'PNG')
158 except ValueError:
159 self._append_plain_text('Received invalid plot data.')
160 else:
161 format = self._add_image(image)
162 cursor = self._get_end_cursor()
163 cursor.insertBlock()
164 cursor.insertImage(format)
165 cursor.insertBlock()
166
138 def _add_image(self, image):
167 def _add_image(self, image):
139 """ Adds the specified QImage to the document and returns a
168 """ Adds the specified QImage to the document and returns a
140 QTextImageFormat that references it.
169 QTextImageFormat that references it.
General Comments 0
You need to be logged in to leave comments. Login now