Chaco Plots in PySide

I’ve been working on learning how to use the QT4 framework in python with the PySide bindings.  I’m trying to move into more app-centered development as opposed to just doing all of my work from a command line.  I work in an environment with very few actual programmers, and if I can develop real apps to do analysis, then it’s much easier for me to share my tools than if I develop command-line programs.  GUIs are just much more accessible to non-programmers, and I like being useful to my coworkers.

About a year ago I picked up the Enthought Tool Suite and gave it a try.  Traits itself is extremely useful, and I’ve switched to using chaco and Mayavi for 2d and 3d plotting in applications.  My feelings are mixed on TraitsUI, however.  The goal was to make a graphical interface to Traits-using classes, and it does that quite well.  It’s a good extension to command line work.  But it falls short of a full UI.  It’s not something that I can easily code and wrap up as a self-contained app to hand off to one of my coworkers.

So I’ve been looking for alternatives.  In the last edition of the Enthought Python Distribution, they included QT4 and the PySide python bindings, so I’ve been learning how to use PySide to create my interfaces.  I’ve been having a blast.  It’s much easier to lay out elements; QTDesigner is free, and you can export layouts to python code for easy use.  The major problem I’ve been having is with information passing between QT code and my workhorse code.  In particular, getting chaco image plots to work.

So here’s a short sample of how to pass data back and forth.

import sys
from numpy import arange, sin, array
from PySide.QtCore import *
from PySide.QtGui import *

app = QApplication(sys.argv)

from enthought.etsconfig.etsconfig import ETSConfig
ETSConfig.toolkit = "qt4"
from enthought.enable.api import Window
from enthought.chaco.api import ArrayPlotData, Plot

class Viewer(QMainWindow):
    def __init__(self):
        self.plotview = Plotter(self)
        x = arange(10)
        y = sin(x)
        self.plotview.update_data(x, y)

class Plotter():
    def __init__(self, parent):
        self.plotdata = ArrayPlotData(x=array([]),  y=array([]))
        self.window = self.create_plot(parent)
        self.widget = self.window.control

    def update_data(self, x, y):
        self.plotdata.set_data("x", x)
        self.plotdata.set_data("y", y)

    def create_plot(self, parent):
        plot = Plot(self.plotdata, padding=50, border_visible=True)
        plot.plot(("x", "y"), name="data plot", color="green")
        return Window(parent, -1, component=plot)

if __name__ == "__main__":
    plot = Viewer()
    plot.resize(600, 400)

There’s a couple of things to keep an eye on.  Note that I create the QApplication up in the header region before my Enthought imports.  That’s because the Enthought imports will try to create one themselves, and you can’t have two active at once.  It’s also important to set the Enthought toolkit to qt4 or it will use the wxpython bindings and you won’t be able to pass data around properly.

The central part of the link is the Enable Window object that gets created by Plotter.create_plot().  The Window.control attribute subclasses from QWidget, so we can use it like any other widget in our QT framework.  Here I’m just setting it as the central widget of the main window, but you can put it in layouts just like anything else.  Data actually moves back and forth by updating the ArrayPlotData instance that the chaco plots take their data from.  Any time we change the data there, the chaco plot will automatically update.


2 thoughts on “Chaco Plots in PySide

  1. For the sake of others who may come this way, I had to change the imports with the newer versions:

    from traits.etsconfig.etsconfig import ETSConfig
    ETSConfig.toolkit = “qt4”
    from enable.api import Window
    from chaco.api import ArrayPlotData, Plot

    The versions I have are: traits & enable at version 4.0.0; chaco at 4.2.0

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s