Attachment 'Matplotlib_Math_Equation_Editor_Demo.py'
Download 1 #!/usr/bin/env python
2
3 """
4 Test of embedding matplotlib, and using it to render a mathematical equation.
5
6 Original demo by Chris Barker 2010-12-15
7
8 Ergonomic, cropping and file saving additions by Ray Pasco 2010-12-15
9
10 Tested using :
11
12 Windows 6.1.7600
13 Python 2.6.5 (r265:79096, Mar 19 2010, 21:48:26) [MSC v.1500 32 bit (Intel)]
14 Wx 2.8.11.0
15 Matplotlib 1.0.0
16 PIL 1.1.7
17
18 """
19
20 import time
21
22 import wx
23
24 # These imports take an incredibly long time.
25 # Let the user know this is normal and expected.
26 print '\n---- Importing Matplotlib and Related Modules...'
27 start = time.clock()
28 #
29 import matplotlib
30 matplotlib.use( 'WXAgg' ) # AggDraw for wxPython.
31 import matplotlib.figure
32 import matplotlib.backends.backend_wxagg
33 #
34 end = time.clock()
35 print ' Import Time =', end-start, 'seconds'
36
37 #------------------------------------------------------------------------------
38
39 class MathPanel( wx.Panel ) :
40 """
41 The MathPanel is a very simple panel with just and MPL figure on it,
42 it will automatically render text in the middle of the figure
43 """
44
45 def __init__( self, parent ) :
46
47 wx.Panel.__init__( self, parent=parent, size=(500, 200) )
48
49 #-----
50
51 # initialize matplotlib stuff.
52 # To always make figure backgrounds be initialized to white
53 # edit file [ \Lib\site-packages\matplotlib\mpl-data\matplotlibrc ]
54 # line [ figure.facecolor : 0.75 ] in section [ ### FIGURE ] to
55 # [ figure.facecolor : 1.00 ]. Who would want a gray background color by default ?
56 #
57 # Create the "figure" and set its background color to white,
58 self.figure = matplotlib.figure.Figure( None, facecolor='white' )
59 self.canvas = matplotlib.backends.backend_wxagg.FigureCanvasWxAgg( \
60 self, -1, self.figure )
61
62 self._SetSize()
63
64 self.Bind( wx.EVT_SIZE, self._SetSize )
65
66 self.TeX = ''
67 self.font_size = 20
68
69 self.RenderEquation()
70
71 #end __init__
72
73 #----------------------------------
74
75 def SetTeX( self, str ) :
76
77 self.TeX = '$%s$' % (str)
78 self.RenderEquation()
79
80 #----------------------------------
81
82 def RenderEquation( self ) :
83
84 self.renderError = False # Can save to file only if False
85
86 try :
87 self.figure.clear()
88 self.figure.text( 0.05, 0.5, self.TeX, size=self.font_size )
89 self.canvas.draw()
90
91 except matplotlib.pyparsing.ParseFatalException :
92
93 self.renderError = True # Can't save current rendering to a file.
94
95 self.figure.clear()
96 self.figure.text( 0.05, 0.5, 'Parsing Error in MathTeX', size=self.font_size )
97 self.canvas.draw()
98
99 #end try
100
101 #end def
102
103 #----------------------------------
104
105 def _SetSize( self, evt=None ) :
106
107 pixels = self.GetSize()
108 self.SetSize( pixels )
109 self.canvas.SetSize( pixels )
110 self.figure.set_size_inches( float( pixels[0] ) / self.figure.get_dpi(),
111 float( pixels[1] ) / self.figure.get_dpi() )
112 #end def
113
114 #------------------------------------------------------------------------------
115
116 class MathFrame( wx.Frame ) :
117
118 def __init__( self ) :
119
120 wx.Frame.__init__( self, None, -1, pos=(10, 10),
121 title='Matplotlib Math EquationRenderer Test' )
122 self.ClientSize = (800, 275)
123
124 # Frames need an initial panel to provide tab traversal and
125 # cross-platform background color capabilities.
126 frmPanel = wx.Panel( self )
127
128 #-----
129
130 self.math_panel = MathPanel( frmPanel )
131
132 self.input_box = wx.TextCtrl( frmPanel, size=(500, -1) )
133 self.input_box.Font = wx.Font( 10,
134 wx.FONTFAMILY_TELETYPE,
135 wx.FONTSTYLE_NORMAL,
136 wx.FONTWEIGHT_NORMAL )
137 self.input_box.Bind( wx.EVT_TEXT, self.OnText )
138
139 # Set a default equation. Show som special symbols.
140 equation = r'Goober = {\min(\int\ (\ {\delta{(\ \pi{}*\frac{\sum(\ a+\O\o\l\S\P\L\{b\}\ )\ } {( c-d )}})}\ )}'
141 self.input_box.Value = equation
142
143 label_stTxt = wx.StaticText( frmPanel, label='Type some TeX here :' )
144
145 saveBtn = wx.Button( frmPanel, label='Save Equation to File' )
146 saveBtn.Bind( wx.EVT_LEFT_DOWN, self.OnSaveToFileBtn )
147
148 exitBtn = wx.Button( frmPanel, label='Exit' )
149 exitBtn.Bind( wx.EVT_LEFT_DOWN, self.OnExit )
150
151 #----- Layout
152
153 frmPnl_vertSzr = wx.BoxSizer( wx.VERTICAL )
154
155 frmPnl_vertSzr.Add( label_stTxt, proportion=0, flag=wx.TOP|wx.LEFT, border=5 )
156 frmPnl_vertSzr.Add( self.input_box, proportion=0, flag=wx.GROW|wx.ALL, border=5 )
157 frmPnl_vertSzr.Add( self.math_panel, proportion=1, flag=wx.GROW )
158 frmPnl_vertSzr.Add( saveBtn, proportion=0,
159 flag=wx.ALIGN_CENTER|wx.BOTTOM|wx.TOP, border=10 )
160 frmPnl_vertSzr.Add( exitBtn, proportion=0,
161 flag=wx.ALIGN_CENTER|wx.BOTTOM, border=10 )
162
163 frmPanel.SetSizerAndFit( frmPnl_vertSzr )
164
165 #end __init__
166
167 #----------------------------------
168
169 def OnText( self, evt ) :
170
171 self.math_panel.SetTeX( self.input_box.Value )
172
173 #----------------------------------
174
175 def OnExit( self, evt ) :
176
177 self.Close()
178
179 #----------------------------------
180
181 def OnSaveToFileBtn( self, event ) :
182
183 if not self.math_panel.renderError :
184
185 filename = 'Rendered_Equation.png'
186 self.math_panel.figure.savefig( filename, dpi=300 )
187 print '\n---- Equation Graphic Saved to File [ %s ]' % filename
188
189 # See if the PIL package is installed.
190 pilIsInstalled = True
191 try :
192 # Try to crop the image to its near-minimum extent.
193 import Image # PIL (Python Image Library)
194 import ImageChops # Image Channel Operations library
195 import ImageStat # Image Statistics library
196 import ImageOps # Various whole image operations.
197
198 except :
199 pilIsInstalled = False # Image will not get cropped.
200 #end try
201
202 if pilIsInstalled :
203
204 pilImg = Image.open( filename )
205
206 # Find the ordinates of the minimally enclosing bounding box.
207 #
208 # Examine a simplified version of the original image
209 invertedImage = ImageChops.invert( pilImg.convert( 'L' ) )
210
211 # Get the bounding box's ordinates.
212 box = invertedImage.getbbox()
213
214 ## Add back a bit of padding all around the minimum extent.
215 #xLeft, yTop, xRight, yRight = box
216 #xLeft -= 10 # arbitrary padding amount
217 #yTop -= 10
218 #xRight += 10
219 #yRight += 10
220 #box = (xLeft, yTop, xRight, yRight) # the expanded extent box
221
222 # Crop the original image.
223 pilImg = pilImg.crop( box )
224
225 # Add back a thin border.
226 pilImg = ImageOps.expand( pilImg, border=10, fill=(255, 255, 255) )
227
228 # Save it to a disk file. Only PNG and TIFF formats are non-destructive.
229 pilImg.save( filename )
230 print ' Cropped Equation Graphic Saved'
231
232 #end if
233
234 else :
235 print '\n---- Figure NOT Saved to File Due to the Previous Rendering Error.'
236 #end if
237
238 #end def
239
240 #end MathFrame class
241
242 #==============================================================================
243
244 if __name__ == '__main__' :
245
246 # What packages are installed ?
247 import os, sys, platform
248 print
249 if os.name == 'nt' :
250 print 'Windows ', platform.win32_ver()[1]
251 else :
252 print 'Platform ', platform.system()
253 #end if
254 print 'Python ', sys.version
255
256 addon_pkgs = [ ('Wx ', 'wx.VERSION_STRING'),
257 ('Matplotlib', 'matplotlib.__version__'), ]
258
259 try :
260 import Image # Doesn't need to be installed.
261 pilStr = 'PIL '
262 pilAddonStr = 'Image.VERSION'
263 addon_pkgs.append( (pilStr , pilAddonStr) )
264 except :
265 pass
266 #end try
267
268 for addonStr, attribute in addon_pkgs :
269 try :
270 print addonStr, eval( attribute )
271 except NameError :
272 print
273 #end try
274 #end for
275 print
276
277 #----
278
279 app = wx.App( redirect=False )
280 appFrame = MathFrame().Show()
281 app.MainLoop()
282
283 #end if
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.