Figure with pyQt

That's great. I'm a real newbie with mpl and I would like to know how to
change figure after a PyQt-Event.
That's must be simple but I don't see how to do this. My idea would be for
example to show different kinds of draw like for example the sin function
and another function. The users just have to click on some button. This is
only to understand the way mpl manage changes in the figure.

If someone could helpme that would be greater than great.

Regards.
Christophe.

----Message d'origine----

Date: Fri, 16 Jan 2009 07:00:07 -0800 (PST)
De: B Clowers
Sujet: Re: [Matplotlib-users] Figure with pyQt
A: matplotlib-users@lists.sourceforge.net, projetmbc@...748...

You'll have to excuse some of the comments in the code (it's in a constant

state of revision), but this is a basic PyQt4/matplotlib widget that I use
quite often and can be embedded using QtDesigner as well. You'll
obviously need PyQt4, Matplotlib, and Numpy to run it. Of course mods can
be made as you see fit for your particular application.

I should note that Ctrl+Z zooms using the Spanselector and the top of the

drawn span is the max Y and the the min Y always defaults to 0 (this works
for my data sets). Ctrl+A zooms out. Save to csv is also an option
(Ctrl+Alt+S)--this can fail if you've a weird data set. Ctrl+C copies a png of
the current figure to the user's home directory (works for both Linux and
Windows) and also puts the image on the current clipboard.

I've also added an option to make multiple plot layouts that are stored in

a dictionary that can be accessed to plot to the given axes. If anyone has
a more elegant solution please share. Let me know if you've questions.

Cheers,

Brian

##############################
#!/usr/bin/env python

import os

import sys

from PyQt4 import QtCore, QtGui

from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as

FigureCanvas

from matplotlib.backends.backend_qt4 import NavigationToolbar2QT as

NavigationToolbar

#from matplotlib.backend_bases import NavigationToolbar2

from matplotlib.figure import Figure

from matplotlib.widgets import SpanSelector

#from matplotlib.pyplot import savefig

import numpy as N

class MyMplCanvas(FigureCanvas):

def \_\_init\_\_\(self, parent=None, width = 5, height = 5, dpi = 100, 

sharex = None, sharey = None):

    self\.fig = Figure\(figsize = \(width, height\), dpi=dpi, facecolor = 

'#FFFFFF')

    self\.axDict = \{\}

    self\.figInit = False


    self\.sharey = sharey

    self\.sharey = sharey

# self.ax1.hold(True)

    FigureCanvas\.\_\_init\_\_\(self, self\.fig\)

    \#self\.fc = FigureCanvas\(self\.fig\)

    FigureCanvas\.setSizePolicy\(self,

        QtGui\.QSizePolicy\.Expanding,

        QtGui\.QSizePolicy\.Expanding\)

    FigureCanvas\.updateGeometry\(self\)

    self\.setupSub\(1\)


def setupSub\(self, numSubRows, numSubCols = 1, sharex = False, 

sharey = False):

    self\.fig\.clf\(\)

    for m in range\(1,numSubRows\+1\):

        for n in range\(1,numSubCols\+1\):

            axName = 'ax%s'%m

            axLoc = 100\*numSubRows\+10\*n\+m

            \#print axLoc

            if sharex:

                if m>1:

                    self\.axDict\[axName\] = self\.fig\.add\_subplot\(axLoc, sharex 

= self.axDict['ax%s'%(m-1)])

                else:

                    self\.axDict\[axName\] = self\.fig\.add\_subplot\(axLoc\)\#, 

sharex = self.sharex, sharey = self.sharey)

            else:

                self\.axDict\[axName\] = self\.fig\.add\_subplot\(axLoc\)\#, sharex 

= self.sharex, sharey = self.sharey)

    self\.figInit = True


    self\.fig\.subplots\_adjust\(left=0\.1, bottom=0\.1, right=0\.9, top=0\.9\)

    self\.xtitle=""

    self\.ytitle=""

    \#self\.PlotTitle = "Plot"

    self\.grid\_status = True

    self\.xaxis\_style = 'linear'

    self\.yaxis\_style = 'linear'

    self\.format\_labels\(\)




def format\_labels\(self\):

    if self\.figInit:

        for ax in self\.axDict\.itervalues\(\):

            ax\.title\.set\_fontsize\(10\)

            ax\.set\_xlabel\(self\.xtitle, fontsize = 9\)

            ax\.set\_ylabel\(self\.ytitle, fontsize = 9\)

            labels\_x = ax\.get\_xticklabels\(\)

            labels\_y = ax\.get\_yticklabels\(\)


            for xlabel in labels\_x:

                xlabel\.set\_fontsize\(8\)

            for ylabel in labels\_y:

                ylabel\.set\_fontsize\(8\)

                ylabel\.set\_color\('b'\)

            if ax\.get\_legend\(\) \!= None:

                texts = ax\.get\_legend\(\)\.get\_texts\(\)

                for text in texts:

                    text\.set\_fontsize\(8\)

    else:

        print "please initiate the number of subplots\. Call 

*.canvas.setupSub(numofSubs)"

def sizeHint\(self\):

    w, h = self\.get\_width\_height\(\)

    return QtCore\.QSize\(w, h\)


def minimumSizeHint\(self\):

    return QtCore\.QSize\(10, 10\)


def sizeHint\(self\):

    w, h = self\.get\_width\_height\(\)

    return QtCore\.QSize\(w, h\)


def minimumSizeHint\(self\):

    return QtCore\.QSize\(10, 10\)

class MyNavigationToolbar(NavigationToolbar) :

def \_\_init\_\_\(self , parent , canvas , direction = 'h' \) :

    \#NavigationToolbar\.\_\_init\_\_\(self,parent,canvas\)

    \#self\.layout = QVBoxLayout\( self \)


    self\.canvas = canvas

    QWidget\.\_\_init\_\_\( self, parent \)


    if direction=='h' :

        self\.layout = QHBoxLayout\( self \)

    else :

        self\.layout = QVBoxLayout\( self \)


    self\.layout\.setMargin\( 2 \)

    self\.layout\.setSpacing\( 0 \)


    NavigationToolbar2\.\_\_init\_\_\( self, canvas \)



def set\_message\( self, s \):

    pass

class MPL_Widget(QtGui.QWidget):

def \_\_init\_\_\(self, parent = None\):

    QtGui\.QWidget\.\_\_init\_\_\(self, parent\)

    self\.setAttribute\(QtCore\.Qt\.WA\_DeleteOnClose\)

    self\.canvas = MyMplCanvas\(\)

    self\.toolbar = NavigationToolbar\(self\.canvas, self\.canvas\)

    \#self\.toolbar\.hide\(\)

    self\.vbox = QtGui\.QVBoxLayout\(\)

    self\.vbox\.addWidget\(self\.canvas\)

    self\.vbox\.addWidget\(self\.toolbar\)

    self\.setLayout\(self\.vbox\)

    self\.ax1 = self\.canvas\.axDict\['ax1'\]

    \#\#\#\#\#\#\#\#\#\#\#\#\#\#\#ZOOM CONTROLS \#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#


    self\.ZoomChrom = QtGui\.QAction\("Zoom Chrom",  self\)

    self\.ZoomChrom\.setShortcut\("Ctrl\+Z"\)

    self\.addAction\(self\.ZoomChrom\)

QtCore.QObject.connect(self.ZoomChrom,QtCore.SIGNAL("triggered()"),
self.ZoomToggle)

    self\.actionAutoScaleChrom = QtGui\.QAction\("AutoScale",  

self)#self.MainWindow)

    self\.actionAutoScaleChrom\.setShortcut\("Ctrl\+A"\)

    self\.addAction\(self\.actionAutoScaleChrom\)

QtCore.QObject.connect(self.actionAutoScaleChrom,QtCore.SIGNAL("trigge
red()"), self.autoscale_plot)

    self\.span = SpanSelector\(self\.ax1, self\.onselect, 'horizontal', 

minspan =0.01,

                             useblit=True, rectprops=dict\(alpha=0\.5, 

facecolor='#C6DEFF') )

    self\.hZoom = False

    self\.span\.visible = False


    self\.localYMax = 0

    self\.canvas\.mpl\_connect\('button\_press\_event', self\.onclick\)


    \#\#\#\#\#\#\#\#\#\#\#SAVING FIGURE TO CLIPBOARD\#\#\#\#\#\#\#\#\#\#

    self\.cb = None \#will be used for the clipboard

    self\.tempPath = getHomeDir\(\)

    self\.tempPath = os\.path\.join\(self\.tempPath,'tempMPL\.png'\)


    self\.mpl2ClipAction = QtGui\.QAction\("Save to Clipboard",  self\)

    self\.mpl2ClipAction\.setShortcut\("Ctrl\+C"\)

    self\.addAction\(self\.mpl2ClipAction\)

QtCore.QObject.connect(self.mpl2ClipAction,QtCore.SIGNAL("triggered()"),
self.mpl2Clip)

    \#\#\#\#\#\#\#SAVING FIGURE 

DATA############################

# self.saveCSVAction = QtGui.QAction("Save to CSV", self)

# self.saveCSVAction.setShortcut("Ctrl+Alt+S")

# self.addAction(self.saveCSVAction)

#

QtCore.QObject.connect(self.saveCSVAction,QtCore.SIGNAL("triggered()"),
self.save2CSV)

···
    \#\#\#\#\#\#\#\#\#\#\# HELPER FUNCTIONS 

#########################

def ZoomToggle\(self\):

    \#self\.toolbar\.zoom\(\) \#this implements the classic zoom

    if self\.hZoom:

        self\.hZoom = False

        self\.span\.visible = False

    else:

        self\.hZoom = True

        self\.span\.visible = True


def autoscale\_plot\(self\):

# print "autoscale"

    \#self\.toolbar\.home\(\) \#implements the classic return to home

    self\.ax1\.autoscale\_view\(tight = False, scalex=True, scaley=True\)

    self\.canvas\.draw\(\)


def onclick\(self, event\):

    \#sets up the maximum Y level to be displayed after the zoom\.

    \#if not set then it maxes to the largest point in the data

    \#not necessarily the local max

    if event\.ydata \!= None:

        self\.localYMax = int\(event\.ydata\)


def onselect\(self, xmin, xmax\):

    \#print xmin,  xmax

    if self\.hZoom:

        self\.ax1\.set\_ylim\(ymax = self\.localYMax\)

        self\.ax1\.set\_xlim\(xmin,  xmax\)



def save2CSV\(self\):

    path = self\.SFDialog\(\)

    if path \!= None:

        try:

            lines = self\.ax1\.get\_lines\(\)

            data2write = \[\]

            for line in lines:

                data2write\.append\(line\.get\_data\(\)\[0\]\)

                data2write\.append\(line\.get\_data\(\)\[1\]\)

            print data2write

            data2write = N\.array\(data2write\)

            data2write\.dtype = N\.float32

            N\.savetxt\(str\(path\), N\.transpose\(data2write\), delimiter = ',', 

fmt='%.4f')

        except:

            try:

                \#this is for the case where the data may not be in float 

format?

                N\.savetxt\(str\(path\), N\.transpose\(data2write\), delimiter = ','\)

            except:

                print 'Error saving figure data'

                errorMsg = "Sorry: %s\\n\\n:%s\\n"%\(sys\.exc\_type, 

sys.exc_value)

                print errorMsg



def SFDialog\(self\):

    fileName = QtGui\.QFileDialog\.getSaveFileName\(self,

                                     "Select File to Save",

                                     "",

                                     "csv Files \(\*\.csv\)"\)

    if not fileName\.isEmpty\(\):

        print fileName

        return fileName

    else:

        return None



def mpl2Clip\(self\):

    try:

        self\.canvas\.fig\.savefig\(self\.tempPath\)

        tempImg = QtGui\.QImage\(self\.tempPath\)

        self\.cb = QtGui\.QApplication\.clipboard\(\)

        self\.cb\.setImage\(tempImg\)

    except:

        print 'Error copying figure to clipboard'

        errorMsg = "Sorry: %s\\n\\n:%s\\n"%\(sys\.exc\_type, 

sys.exc_value)

        print errorMsg

# savefig(fname, dpi=None, facecolor='w', edgecolor='w',

# orientation='portrait', papertype=None, format=None,

# transparent=False):

####USED TO GET THE USERS HOME DIRECTORY FOR USE OF A TEMP

FILE

def valid(path):

if path and os\.path\.isdir\(path\):

    return True

return False

def env(name):

return os\.environ\.get\( name, '' \)

def getHomeDir():

if sys\.platform \!= 'win32':

    return os\.path\.expanduser\( '\~' \)


homeDir = env\( 'USERPROFILE' \)

if not valid\(homeDir\):

    homeDir = env\( 'HOME' \)

    if not valid\(homeDir\) :

        homeDir = '%s%s' % \(env\('HOMEDRIVE'\),env\('HOMEPATH'\)\)

        if not valid\(homeDir\) :

            homeDir = env\( 'SYSTEMDRIVE' \)

            if homeDir and \(not homeDir\.endswith\('\\\\'\)\) :

                homeDir \+= '\\\\'

            if not valid\(homeDir\) :

                homeDir = 'C:\\\\'

return homeDir

def main():

import sys

app = QtGui\.QApplication\(sys\.argv\)

w = MPL\_Widget\(\)

# w.canvas.setupSub(1)

ax1 = w\.canvas\.axDict\['ax1'\]

x = N\.arange\(0, 20\)

y = N\.sin\(x\)

y2 = N\.cos\(x\)

ax1\.plot\(x, y\)

ax1\.plot\(x, y2\)

w\.show\(\)

sys\.exit\(app\.exec\_\(\)\)

if __name__ == "__main__":

main\(\)

####################################

--- On Thu, 1/15/09, projetmbc@...748... <projetmbc@...2453... internet.fr> wrote:
From: projetmbc@...748... <projetmbc@...748...>
Subject: [Matplotlib-users] Figure with pyQt
To: matplotlib-users@lists.sourceforge.net
Date: Thursday, January 15, 2009, 9:56 AM

Hello,
I would like to see the following example
http://matplotlib.sourceforge.net/examples/pylab_examples/ellipse_demo

.ht

ml using the 2nd one
http://matplotlib.sourceforge.net/examples/user_interfaces/embedding_in

_qt

4.html .
In fact, I don't undrestand how to add the figure to the screen (I'm a
real
beginner with matplotlib but not with PyQt).

Thanks for any kind of help.

------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Take a look at the matplotlib widgets example referenced below. It
uses mpl widgets rather than qt widgets, but it should make clear the
logic of updating plot properties connected to callbacks

http://matplotlib.svn.sourceforge.net/viewvc/matplotlib/trunk/matplotlib/examples/widgets/radio_buttons.py?content-type=text%2Fplain

···

On Fri, Jan 16, 2009 at 9:40 AM, <projetmbc@...748...> wrote:

That's great. I'm a real newbie with mpl and I would like to know how to
change figure after a PyQt-Event.
That's must be simple but I don't see how to do this. My idea would be for
example to show different kinds of draw like for example the sin function
and another function. The users just have to click on some button. This is
only to understand the way mpl manage changes in the figure.

If someone could helpme that would be greater than great.