##// END OF EJS Templates
Check if latex/dvipng exist before calling them
Takafumi Arakaki -
Show More
@@ -1,176 +1,181 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tools for handling LaTeX.
3 3
4 4 Authors:
5 5
6 6 * Brian Granger
7 7 """
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2010 IPython Development Team.
10 10 #
11 11 # Distributed under the terms of the Modified BSD License.
12 12 #
13 13 # The full license is in the file COPYING.txt, distributed with this software.
14 14 #-----------------------------------------------------------------------------
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Imports
18 18 #-----------------------------------------------------------------------------
19 19
20 20 from StringIO import StringIO
21 21 from base64 import encodestring
22 22 import os
23 23 import tempfile
24 24 import shutil
25 25 import subprocess
26 26
27 from IPython.utils.process import find_cmd, FindCmdError
28
27 29 #-----------------------------------------------------------------------------
28 30 # Tools
29 31 #-----------------------------------------------------------------------------
30 32
31 33
32 34 def latex_to_png(s, encode=False, backend='mpl'):
33 35 """Render a LaTeX string to PNG.
34 36
35 37 Parameters
36 38 ----------
37 39 s : str
38 40 The raw string containing valid inline LaTeX.
39 41 encode : bool, optional
40 42 Should the PNG data bebase64 encoded to make it JSON'able.
41 43 backend : {mpl, dvipng}
42 44 Backend for producing PNG data.
43 45
44 46 None is returned when the backend cannot be used.
45 47
46 48 """
47 49 if backend == 'mpl':
48 50 f = latex_to_png_mpl
49 51 elif backend == 'dvipng':
50 52 f = latex_to_png_dvipng
51 53 else:
52 54 raise ValueError('No such backend {0}'.format(backend))
53 55 bin_data = f(s)
54 56 if encode and bin_data:
55 57 bin_data = encodestring(bin_data)
56 58 return bin_data
57 59
58 60
59 61 def latex_to_png_mpl(s):
60 62 try:
61 63 from matplotlib import mathtext
62 64 except ImportError:
63 65 return None
64 66
65 67 mt = mathtext.MathTextParser('bitmap')
66 68 f = StringIO()
67 69 mt.to_png(f, s, fontsize=12)
68 70 return f.getvalue()
69 71
70 72
71 73 def latex_to_png_dvipng(s):
72 74 try:
75 find_cmd('latex')
76 find_cmd('dvipng')
77 except FindCmdError:
78 return None
79 try:
73 80 workdir = tempfile.mkdtemp()
74 81 tmpfile = os.path.join(workdir, "tmp.tex")
75 82 dvifile = os.path.join(workdir, "tmp.dvi")
76 83 outfile = os.path.join(workdir, "tmp.png")
77 84
78 85 with open(tmpfile, "w") as f:
79 86 f.write(_latex_header)
80 87 f.write(s)
81 88 f.write(_latex_footer)
82 89
83 90 subprocess.check_call(
84 91 ["latex", "-halt-on-errror", tmpfile], cwd=workdir,
85 92 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
86 93
87 94 subprocess.check_call(
88 95 ["dvipng", "-T", "tight", "-x", "1500", "-z", "9",
89 96 "-bg", "transparent", "-o", outfile, dvifile], cwd=workdir,
90 97 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
91 98
92 99 with open(outfile) as f:
93 100 bin_data = f.read()
94 except subprocess.CalledProcessError:
95 bin_data = None
96 101 finally:
97 102 shutil.rmtree(workdir)
98 103 return bin_data
99 104
100 105
101 106 _latex_header = r'''
102 107 \documentclass{article}
103 108 \usepackage{amsmath}
104 109 \usepackage{amsthm}
105 110 \usepackage{amssymb}
106 111 \usepackage{bm}
107 112 \pagestyle{empty}
108 113 \begin{document}
109 114 '''
110 115
111 116 _latex_footer = r'\end{document}'
112 117
113 118
114 119 _data_uri_template_png = """<img src="data:image/png;base64,%s" alt=%s />"""
115 120
116 121 def latex_to_html(s, alt='image'):
117 122 """Render LaTeX to HTML with embedded PNG data using data URIs.
118 123
119 124 Parameters
120 125 ----------
121 126 s : str
122 127 The raw string containing valid inline LateX.
123 128 alt : str
124 129 The alt text to use for the HTML.
125 130 """
126 131 base64_data = latex_to_png(s, encode=True)
127 132 if base64_data:
128 133 return _data_uri_template_png % (base64_data, alt)
129 134
130 135
131 136 # From matplotlib, thanks to mdboom. Once this is in matplotlib releases, we
132 137 # will remove.
133 138 def math_to_image(s, filename_or_obj, prop=None, dpi=None, format=None):
134 139 """
135 140 Given a math expression, renders it in a closely-clipped bounding
136 141 box to an image file.
137 142
138 143 *s*
139 144 A math expression. The math portion should be enclosed in
140 145 dollar signs.
141 146
142 147 *filename_or_obj*
143 148 A filepath or writable file-like object to write the image data
144 149 to.
145 150
146 151 *prop*
147 152 If provided, a FontProperties() object describing the size and
148 153 style of the text.
149 154
150 155 *dpi*
151 156 Override the output dpi, otherwise use the default associated
152 157 with the output format.
153 158
154 159 *format*
155 160 The output format, eg. 'svg', 'pdf', 'ps' or 'png'. If not
156 161 provided, will be deduced from the filename.
157 162 """
158 163 from matplotlib import figure
159 164 # backend_agg supports all of the core output formats
160 165 from matplotlib.backends import backend_agg
161 166 from matplotlib.font_manager import FontProperties
162 167 from matplotlib.mathtext import MathTextParser
163 168
164 169 if prop is None:
165 170 prop = FontProperties()
166 171
167 172 parser = MathTextParser('path')
168 173 width, height, depth, _, _ = parser.parse(s, dpi=72, prop=prop)
169 174
170 175 fig = figure.Figure(figsize=(width / 72.0, height / 72.0))
171 176 fig.text(0, depth/height, s, fontproperties=prop)
172 177 backend_agg.FigureCanvasAgg(fig)
173 178 fig.savefig(filename_or_obj, dpi=dpi, format=format)
174 179
175 180 return depth
176 181
General Comments 0
You need to be logged in to leave comments. Login now