##// END OF EJS Templates
remove unused import
Srinivas Reddy Thatiparthy -
Show More
@@ -1,201 +1,201 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tools for handling LaTeX."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7 from io import BytesIO, open
8 8 import os
9 9 import tempfile
10 10 import shutil
11 11 import subprocess
12 12 from base64 import encodebytes
13 13
14 14 from IPython.utils.process import find_cmd, FindCmdError
15 15 from traitlets.config import get_config
16 16 from traitlets.config.configurable import SingletonConfigurable
17 17 from traitlets import List, Bool, Unicode
18 from IPython.utils.py3compat import cast_unicode, cast_unicode_py2 as u, PY3
18 from IPython.utils.py3compat import cast_unicode, cast_unicode_py2 as u
19 19
20 20
21 21 class LaTeXTool(SingletonConfigurable):
22 22 """An object to store configuration of the LaTeX tool."""
23 23 def _config_default(self):
24 24 return get_config()
25 25
26 26 backends = List(
27 27 Unicode(), ["matplotlib", "dvipng"],
28 28 help="Preferred backend to draw LaTeX math equations. "
29 29 "Backends in the list are checked one by one and the first "
30 30 "usable one is used. Note that `matplotlib` backend "
31 31 "is usable only for inline style equations. To draw "
32 32 "display style equations, `dvipng` backend must be specified. ",
33 33 # It is a List instead of Enum, to make configuration more
34 34 # flexible. For example, to use matplotlib mainly but dvipng
35 35 # for display style, the default ["matplotlib", "dvipng"] can
36 36 # be used. To NOT use dvipng so that other repr such as
37 37 # unicode pretty printing is used, you can use ["matplotlib"].
38 38 ).tag(config=True)
39 39
40 40 use_breqn = Bool(
41 41 True,
42 42 help="Use breqn.sty to automatically break long equations. "
43 43 "This configuration takes effect only for dvipng backend.",
44 44 ).tag(config=True)
45 45
46 46 packages = List(
47 47 ['amsmath', 'amsthm', 'amssymb', 'bm'],
48 48 help="A list of packages to use for dvipng backend. "
49 49 "'breqn' will be automatically appended when use_breqn=True.",
50 50 ).tag(config=True)
51 51
52 52 preamble = Unicode(
53 53 help="Additional preamble to use when generating LaTeX source "
54 54 "for dvipng backend.",
55 55 ).tag(config=True)
56 56
57 57
58 58 def latex_to_png(s, encode=False, backend=None, wrap=False):
59 59 """Render a LaTeX string to PNG.
60 60
61 61 Parameters
62 62 ----------
63 63 s : str
64 64 The raw string containing valid inline LaTeX.
65 65 encode : bool, optional
66 66 Should the PNG data base64 encoded to make it JSON'able.
67 67 backend : {matplotlib, dvipng}
68 68 Backend for producing PNG data.
69 69 wrap : bool
70 70 If true, Automatically wrap `s` as a LaTeX equation.
71 71
72 72 None is returned when the backend cannot be used.
73 73
74 74 """
75 75 s = cast_unicode(s)
76 76 allowed_backends = LaTeXTool.instance().backends
77 77 if backend is None:
78 78 backend = allowed_backends[0]
79 79 if backend not in allowed_backends:
80 80 return None
81 81 if backend == 'matplotlib':
82 82 f = latex_to_png_mpl
83 83 elif backend == 'dvipng':
84 84 f = latex_to_png_dvipng
85 85 else:
86 86 raise ValueError('No such backend {0}'.format(backend))
87 87 bin_data = f(s, wrap)
88 88 if encode and bin_data:
89 89 bin_data = encodebytes(bin_data)
90 90 return bin_data
91 91
92 92
93 93 def latex_to_png_mpl(s, wrap):
94 94 try:
95 95 from matplotlib import mathtext
96 96 from pyparsing import ParseFatalException
97 97 except ImportError:
98 98 return None
99 99
100 100 # mpl mathtext doesn't support display math, force inline
101 101 s = s.replace('$$', '$')
102 102 if wrap:
103 103 s = u'${0}$'.format(s)
104 104
105 105 try:
106 106 mt = mathtext.MathTextParser('bitmap')
107 107 f = BytesIO()
108 108 mt.to_png(f, s, fontsize=12)
109 109 return f.getvalue()
110 110 except (ValueError, RuntimeError, ParseFatalException):
111 111 return None
112 112
113 113
114 114 def latex_to_png_dvipng(s, wrap):
115 115 try:
116 116 find_cmd('latex')
117 117 find_cmd('dvipng')
118 118 except FindCmdError:
119 119 return None
120 120 try:
121 121 workdir = tempfile.mkdtemp()
122 122 tmpfile = os.path.join(workdir, "tmp.tex")
123 123 dvifile = os.path.join(workdir, "tmp.dvi")
124 124 outfile = os.path.join(workdir, "tmp.png")
125 125
126 126 with open(tmpfile, "w", encoding='utf8') as f:
127 127 f.writelines(genelatex(s, wrap))
128 128
129 129 with open(os.devnull, 'wb') as devnull:
130 130 subprocess.check_call(
131 131 ["latex", "-halt-on-error", "-interaction", "batchmode", tmpfile],
132 132 cwd=workdir, stdout=devnull, stderr=devnull)
133 133
134 134 subprocess.check_call(
135 135 ["dvipng", "-T", "tight", "-x", "1500", "-z", "9",
136 136 "-bg", "transparent", "-o", outfile, dvifile], cwd=workdir,
137 137 stdout=devnull, stderr=devnull)
138 138
139 139 with open(outfile, "rb") as f:
140 140 return f.read()
141 141 except subprocess.CalledProcessError:
142 142 return None
143 143 finally:
144 144 shutil.rmtree(workdir)
145 145
146 146
147 147 def kpsewhich(filename):
148 148 """Invoke kpsewhich command with an argument `filename`."""
149 149 try:
150 150 find_cmd("kpsewhich")
151 151 proc = subprocess.Popen(
152 152 ["kpsewhich", filename],
153 153 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
154 154 (stdout, stderr) = proc.communicate()
155 155 return stdout.strip().decode('utf8', 'replace')
156 156 except FindCmdError:
157 157 pass
158 158
159 159
160 160 def genelatex(body, wrap):
161 161 """Generate LaTeX document for dvipng backend."""
162 162 lt = LaTeXTool.instance()
163 163 breqn = wrap and lt.use_breqn and kpsewhich("breqn.sty")
164 164 yield u(r'\documentclass{article}')
165 165 packages = lt.packages
166 166 if breqn:
167 167 packages = packages + ['breqn']
168 168 for pack in packages:
169 169 yield u(r'\usepackage{{{0}}}'.format(pack))
170 170 yield u(r'\pagestyle{empty}')
171 171 if lt.preamble:
172 172 yield lt.preamble
173 173 yield u(r'\begin{document}')
174 174 if breqn:
175 175 yield u(r'\begin{dmath*}')
176 176 yield body
177 177 yield u(r'\end{dmath*}')
178 178 elif wrap:
179 179 yield u'$${0}$$'.format(body)
180 180 else:
181 181 yield body
182 182 yield u'\end{document}'
183 183
184 184
185 185 _data_uri_template_png = u"""<img src="data:image/png;base64,%s" alt=%s />"""
186 186
187 187 def latex_to_html(s, alt='image'):
188 188 """Render LaTeX to HTML with embedded PNG data using data URIs.
189 189
190 190 Parameters
191 191 ----------
192 192 s : str
193 193 The raw string containing valid inline LateX.
194 194 alt : str
195 195 The alt text to use for the HTML.
196 196 """
197 197 base64_data = latex_to_png(s, encode=True).decode('ascii')
198 198 if base64_data:
199 199 return _data_uri_template_png % (base64_data, alt)
200 200
201 201
General Comments 0
You need to be logged in to leave comments. Login now