forked from nilqed/IPyXt
/
ipy_tex.py
345 lines (282 loc) · 10.8 KB
/
ipy_tex.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#;;; _____ _ ____ _____ _ _______ ____
#;;; / ___/_____(_) __ \/ ___/ |/ / ___// _/
#;;; \__ \/ ___/ / / / /\__ \ | /\__ \ / /
#;;; ___/ / /__/ / /_/ /___/ / / |___/ // /
#;;; /____/\___/_/\____//____/ /_/_/____/___/
#;;;
#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#;;; $Id:: ipy_tex.py 5 2011-08-27 17:33:13Z scios $
#;;; (C) 1998-2011 SciOS Scientific Operating Systems GmbH
#;;; http://www.scios.ch
#;;; FOR INTERNAL USE ONLY.
#;;; HEAD URL: $HeadURL:: file:///F:/SVN/IPy/ipy_tex.py $
#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#;;; PROJECT ...............................: XSI
#;;; SUBPROJECT ............................: IPy
#;;; MODULE ................................: ipy_tex.py
#;;; VERSION ...............................: 0.0.1
#;;; CREATION DATE .........................: 01.01.2000
#;;; MODIFICATION DATE .....................: 16.08.2011
#;;; PROGRAMMING LANGUAGE(S) ...............: Python
#;;; INTERPRETER/COMPILER ..................: Python 2.7 r27:82525
#;;; OPERATING SYSTEM(S) ...................: WIN32 (should be OS independent)
#;;; CREATOR(S) ............................: pagani@scios.ch
#;;; CLIENT(S) .............................: scios
#;;; URL ...................................: research.scios.ch/ipy
#;;; EMAIL .................................: xps@scios.ch
#;;; COPYRIGHT .............................: (C) 2011, SciOS GmbH
#;;; LICENSE ...............................: BSD
#;;; DEPENDENCIES ..........................: IPython, LaTeX (dvipng)
#;;; IMPORTS ...............................: see import list
#;;; EXPORTS ...............................: TeX[0,1,2]
#;;; COMMENTS ..............................: IPython QT console
#;;; SHORT DESCRIPTION .....................: use _repr_png_ to display TeX
#;;; DOCUMENTATION PATH ....................: see XSI/RTy: rty_latex.py
#;;; IDE ...................................: PyScripter V 2.4.2.2
#;;; SVN REVISION ..........................: $Rev:: 5 $
#;;; REVISION DATE .........................: $Date:: 2011-08-27 19:33:13 +02#$
#;;; REVISED BY ............................: $Author:: scios $
#;;; REVISION HISTORY ......................: --
#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#
# Copyright (c) 2011, SciOS Scientific Operating Systems GmbH
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of SciOS GmbH nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL SciOS GmbH BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# ==============================================================================
"""
Doc:
"""
import os, os.path, re, subprocess
from IPython.lib.latextools import latex_to_png
from matplotlib.mathtext import MathTextParser, MathtextBackendBitmap
from tempfile import NamedTemporaryFile
from StringIO import StringIO
from base64 import encodestring
#;;;;;;;;;;;;;;;
# Class TeX0 ;;;
#;;;;;;;;;;;;;;;
class TeX0():
"""
Render TeX code with IPython lib latextools (not many options here ;)
"""
def __init__(self, s, encode = False):
self.png = latex_to_png(s, encode)
def _repr_png_(self):
return self.png
#;;;;;;;;;;;;;;;
# Class TeX1 ;;;
#;;;;;;;;;;;;;;;
class TeX1():
"""
Render TeX code with matplotlib mathtext. Doesn't need a LaTeX installation.
@texstr ........ TeX code as string
@color ......... Font color
@dpi ........... Resolution (dots per inch)
@fontsize ...... Font size
@enocde ........ Enocde base64
@init_render ... Render the PNG image when creating an instance.
If 'False' one has to call the render method explicitly.
"""
def __init__(self, texstr, color = 'black', dpi = 120, fontsize = 12,
encode=False, init_render = True):
self.texstr = texstr
self.color = color
self.dpi = dpi
self.fontsize = fontsize
self.encode = encode
self.init_render = init_render
self.png = None
if self.init_render:
self.render()
def render(self):
self.mtp = MathTextParser('bitmap')
f = StringIO()
self.mtp.to_png(f, self.texstr, self.color, self.dpi, self.fontsize)
bin_data = f.getvalue()
if self.encode:
bin_data = encodestring(bin_data)
self.png = bin_data
f.close()
def set_texstr(self, texstr):
self.texstr = texstr
self.render()
def set_color(self, color):
self.color = color
self.render()
def set_dpi(self, dpi):
self.dpi = dpi
self.render()
def set_fontsize(self, fontsize):
self.fontsize = fontsize
self.render()
def set_encode(self, encode):
self.encode = encode
self.render()
def _repr_png_(self):
return self.png
#;;;;;;;;;;;;;;;
# Class TeX2 ;;;
#;;;;;;;;;;;;;;;
class TeX2():
"""
Converts TeX code to a PNG image via dvi using 'dvipng'
Credit: dvipng 1.XX Copyright 2002-2008 Jan-Ake Larsson
Details: http://www.nongnu.org/dvipng/dvipng_4.html
D = # Output resolution
O = c Image offset
T = c Image size (also accepts '-T bbox' and '-T tight')
bg = s Background color (TeX-style color or 'Transparent')
fg = s Foreground color (TeX-style color)
bd = # Transparent border width in dots
bd = s Transparent border fallback color (TeX-style color)
pt = # Font size set in \documentstyle[#pt]
cleanup = True | False ... removes .aux, .tex, .log and .dvi files.
latex_template = Tex preambel + begin/end{document}
# = number f = file s = string * = suffix, '0' to turn off
c = comma-separated dimension pair (e.g., 3.2in,-32.1cm)
color-spec: ex. rgb 1.0 0.0 0.0 , 'White', 'transparent' ...
Return value: 'False' if an error occurs (check the variables
latex_log, dvipng_log respectively).
It is up to the user to delete/copy/move the PNG file from its
temporary location.
"""
def __init__(self, tex, pt = 12, D = 150, T = 'tight', bg = 'White',
fg = 'Blue', O = '0cm, 0cm', bd = '0', cleanup = True, init_render = True):
self.tex = tex
self.pt = pt
self.D = D
self.T = T
self.bg = bg
self.fg =fg
self.O = O
self.bd = bd
self.cleanup = cleanup
self.init_render = init_render
self.latex_exe = 'latex'
self.dvipng_exe = 'dvipng'
self.default_template = r'''\documentclass[%ipt]{article}
\usepackage{amssymb,amsmath,bm,color}
\usepackage[latin1]{inputenc}
\usepackage{flexisym}
\usepackage{breqn}
\pagestyle{empty}
\begin{document}
%s
\end{document}'''
self.dvipng_opt_template = "-T %s -D %i -bg %s -fg %s -O %s -bd %s"
self.latex_template = self.default_template
self.pngfile = None
self.png = None
if self.init_render:
self.render()
def render(self):
# Create a named temporary file for the TeX source code
tex_file = NamedTemporaryFile(suffix = ".tex", delete = False)
tex_file_name = tex_file.name
tmp_file_base = tex_file_name[:-4]
# Create the TeX source (template % (font_size, tex_string)
tex_input = self.latex_template % (self.pt, self.tex)
# Write TeX input to temp file and close it
tex_file.write(tex_input)
tex_file.close()
# LaTeX process
opt = "-output-directory=" + os.path.dirname(tex_file_name)
cmd = ('%s ' + opt + " -halt-on-error " + '%s') % (self.latex_exe, tex_file_name)
latex = subprocess.Popen(cmd, shell = True, stdout = subprocess.PIPE)
# Read stdout/stderr
latex_log = latex.communicate()
if latex.returncode != 0:
print latex_log, cmd, opt
return False
# Run conversion
pngfile = tmp_file_base + ".png"
dvifile = tmp_file_base + ".dvi"
opt = self.dvipng_opt_template % (self.T, self.D, self.bg, self.fg,
self.O, self.bd)
cmd = ('%s ' + opt + " -o %s %s") % (self.dvipng_exe, pngfile, dvifile)
dvipng = subprocess.Popen(cmd, shell = True, stdout = subprocess.PIPE)
# Read stdout/stderr
dvipng_log = dvipng.communicate()
if dvipng.returncode != 0:
print dvipng_log, cmd, opt
return False
# Cleanup
if self.cleanup:
to_remove = [tmp_file_base + ".dvi", tmp_file_base + ".aux", \
tmp_file_base + ".log", tmp_file_base + ".tex"]
for item in to_remove:
os.remove(item)
# Set png image path
self.pngfile = pngfile
# Read the image
f = open(self.pngfile,'rb') # b may be important here
self.png = f.read()
f.close()
def remove_pngfile(self):
os.remove(self.pngfile)
def _repr_png_(self):
return self.png
#;;;;;;;;;;;;;;;;;;;;;;;;;
# DISPLAY TeX Function ;;;
#;;;;;;;;;;;;;;;;;;;;;;;;;
def dt(arg, m = 1):
"""
Create a TeX instance. Try the matplotlib version first (quite fast) otherwise
try the dvipng version (may be a little slower).
Note: the instance is available with _n, where n is the ipy output number.
The available attributes depend on the class used.
"""
if m == 2: return TeX2(arg)
try:
return TeX1(arg)
except:
return TeX2(arg)
##try:
## __IPy__ = __IPYTHON__active
##
##except:
## __IPy__ = None
##
##
##if __IPy__ is not None:
## ip = get_ipython()
##
## def _tex(self, arg):
## #ip.ex('')
## try:
## return TeX1(arg)
## except:
## return TeX2(arg)
##
## ip.define_magic('tex', _tex)
#;;;;;;;;;
# MAIN ;;;
#;;;;;;;;;
def main():
X=TeX1(r"$\sum_{n=0}^\infty A_n \forall x \in \Lambda$", 'blue', 120, 10)
if __name__ == '__main__':
main()