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.
  • [get | view] (2010-12-16 05:58:35, 30.1 KB) [[attachment:In_Action.png]]
  • [get | view] (2010-12-16 05:58:18, 9.1 KB) [[attachment:Matplotlib_Math_Equation_Editor_Demo.py]]
  • [get | view] (2010-12-16 05:59:05, 40.3 KB) [[attachment:Rendered_Equation.png]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.