Plotting in Python: matplotlib vs. PyQwt

June 5th, 2009 at 2:06 pm

When it comes to plotting and drawing graphs, Python has quite a few options. In this post I want to focus on the two I’ve had experience with, so far. After a short presentation of the libraries, I will compare them on various criteria which I found important.

The contestants

matplotlib

matplotlib is arguably the most popular and best known Python plotting package out there. Armed with NumPy, SciPy and matplotlib, Python programmers aim at the domain currently occupied by the uncontested heavyweight of numeric computing – Matlab. And quite frankly, Python doesn’t fare too badly in this contest.

So matplotlib has been designed from the ground up to support a huge range of plots, and be particularly suitable for scientific plotting. It provides publication-quality plotting, generating high-resolution anti-aliased images that can (and have been) incorporated in real reports and scientific articles.

PyQwt

PyQwt is a different beast. It provides Python bindings to the C++ Qwt library, which is a set of classes extending the Qt framework with plotting and other widgets for scientific and engineering applications.

While not aimed at scientific publication, PyQwt is relatively light-weight, integrates very well with PyQt and provides additional widgets that can be useful for some applications that require plotting.

Visual appeal

Without question, matplotlib produces prettier plots. It uses the Agg 2D rendering engine as its backend and produces the best looking plots I’ve seen from any tool or library.

PyQwt’s plots are homelier, but still look pretty good. There’s an option to render the plots in an anti-aliased manner as well (using the RenderAntialiased option), which makes the plots look much better (at the price of performance), though still not quite like matplotlib.

Plot options

matplotlib has built-in support for much more plot types than PyQwt. Although when you have a good framework (and PyQwt is one) it’s not difficult to program any type of plot, matplotlib delivers most types you could (and couldn’t) think of out-of-the-box.

Also, if math is your thing, you’ll be happy to discover that matplotlib can render LaTeX-typed equations onto the plots.

Integration with GUIs

Since plotting is an inherently visual activity, integration with a GUI is important for a plotting library.

matplotlib knows how to play with Tk, wxPython and PyQt quite well. But it’s a separate library, with its own types, conventions and needs.

PyQwt is seamlessly integrated into the PyQt model. The pens you use to plot in it are PyQt pens, the events and slots of the plot are the same events and slots of the GUI, and everything fits together just perfectly. This is very useful if integration with PyQt is what your application needs the most.

Interaction

For some plots, interaction is important: you want to allow the user to navigate the plot – zoom in and out of areas, have a cursor with a known location, and so on. matplotlib provides built-in interaction with its toolbar that can be easily attached to a plot. Just a few lines of code, and you have a pretty good means of interaction.

PyQwt is different in this aspect. Though it doesn’t have a built-in toolbar widget, here its great integration with PyQt shows its strength. Since PyQwt is so tightly tied into the Qt GUI and event system, it’s possible to create very complex interactions with it. While matplotlib also has an event capability that can be tied to the host GUI’s, it’s much less natural and less convenient to work with.

So if you need just the basic integration, matplotlib has it built-in, and in PyQwt you will have to spend a bit more effort. But if you need a complex interaction, PyQwt is better.

Documentation

matplotlib is much better documented than PyQwt. For PyQwt you just have the examples and the class reference of Qwt (the C++ library) to look at. For matplotlib you have a whole handbook almost 500 pages long, and several other helpful documents.

But this is mostly because matplotlib is much more complex. As I’ve mentioned before, PyQwt is so integrated with PyQt that you don’t need that much documentation to use it. It’s basically another PyQt widget you can use in your application – the learning curve is much gentler.

Performance

Here, in my experience, PyQwt wins big. matplotlib is a large and heavy library, and adding it to an application considerably increases its load time. PyQwt is much lighter and faster as well. If distributing applications is important, keep in mind that the executables produced (say, with py2exe or PyInstaller) with PyQwt will be much smaller, and will load more quickly.

If you build PyQwt on your own, you can also keep numpy support out, which will make the library even smaller. Unfortunately, the pre-built binaries for Windows come with numpy support obligatory.

Extra capabilities

matplotlib is a library for plotting, period. It contains a huge variety of different plot types that will satisfy ultimately all of your plotting needs.

PyQwt, on the other hand, aims at other goals as well. It contains other widgets useful for scientific and engineering apps, such as dials, knobs, wheels and sliders. These can be very useful for some applications, especially in the domain of test&measurement software (as a competition to LabView or Matlab).

Conclusion

I think that there’s place for both libraries in the toolkit of a Python programmer, especially if PyQt is his GUI of choice.

If you need to incorporate a plot into a complex GUI, and provide interesting interaction between the plot and the rest of the widgets (especially dynamic updating), PyQwt is very suitable for the task. It’s lightweight (which helps speed up large applications), very well integrated with PyQt and has a set of additional widgets you can find useful.

On the other hand, whenever you need to crunch some numbers with Python, matplotlib is indispensable. Armed with a good interactive terminal (such as Pydee or IPython) and matplotlib, mathematical explorations are as easy as with Matlab, and the produced plots can be saved to images and incorporated into reports and documents.

Also, if you don’t use PyQt but prefer wx or Tk instead, then matplotlib is perhaps your best option for GUI-integrated plots as well.

Related posts:

  1. matplotlib – plotting with Python
  2. Book review: “Matplotlib for Python developers” by Sandro Tosi
  3. More PyQt plotting demos
  4. matplotlib with PyQt GUIs
  5. matplotlib with wxPython GUIs

21 Responses to “Plotting in Python: matplotlib vs. PyQwt”

  1. pachiNo Gravatar Says:

    I suppose the author of this blog doesn’t use GTK+, but matplotlib has great support for the GTK+ toolkit and using it with PyGTK is very easy. In fact, most of the rendering backends are supported through cairo, which is the underlying rendering engine for GTK+ (Qt uses its own technology).

    There are some more GTK+ plotting widgets that have PyGTK bindings and may be best suited for special needs.

  2. BCNo Gravatar Says:

    Good comparison. For scientific application development, you should also consider Chaco, part of the Enthought Tool Suite. We are, right now, putting together a new application for use with a spectrometer using this toolset and it’s proving excellent. Chaco is targeted more at application development, like PyQwt, rather than script-based data visualisation, which is matplotlib’s forte. Chaco integrates with both Qt and wxPython.

  3. Joshua KuglerNo Gravatar Says:

    I will second Chaco. Very nice, very OO. And it does work in scripts quite nicely.

  4. elibenNo Gravatar Says:

    I’ve heard of Chaco, but it appears to require the whole Enthought suite to be installed. This isn’t always an option, especially given that Enthought isn’t free for commercial use.

  5. BCNo Gravatar Says:

    Chaco does not require the whole of ETS. It requires Traits (Traits was born out of Chaco development). You can easy_install Chaco from PyPI and (hopefully) it will only pull the bits it needs.

    Chaco (and indeed the whole of ETS) IS free for commercial use. You are confusing ETS (the enthought tool suite) with EPD (the Enthought Python Distribution). EPD is not free for commercial use, but every component included in it is BSD-style licensed, so if you compile it yourself you can do what you like with it. On linux, building ETS poses no problems. On windows, paying for EPD is the easiest way to get ETS, if you don’t want to install a compiler.

  6. elibenNo Gravatar Says:

    @BC,

    I’ve downloaded the Chaco .egg and tried to install it and it began to pull a whole lot of stuff from ETS, so it indeed requires a lot of dependencies. It also isn’t clear what the license status of these dependencies are, since they’re precompiled eggs for Windows. Does it count as ETS or EPD?

  7. Gael VaroquauxNo Gravatar Says:

    Chaco, and the complete ETS, is BSD licensed. Enthought, and the various non-Enthought developers that contribute to ETS (including me), really believe in free software and in the BSD license. ETS is a set of open source tools that you can use as building blocks to build an application. EPD is a product built on top of these tools and many others.

  8. Gael VaroquauxNo Gravatar Says:

    Oh, I realize that I haven’t fully answered your question about the compiled eggs. Yes, the are open source. Enthought is trying to promote the ETS (to see wider use of it), and publishes the ETS binary eggs under open source licenses.

  9. FredrikNo Gravatar Says:

    Which of the above mentioned libraries is “best” for real-time display?
    ie updating the graph with new logging points. I have tried this with matplotlib but I found it hard to do, it felt like the model for matplotlib is to draw the graph once…

  10. elibenNo Gravatar Says:

    @Fredrik,

    PyQwt comes with a few examples installed – a couple display dynamic plotting. Doing dynamic plotting in matplotlib is possible indeed, but since PyQwt is faster and lighter, it should be much easier to rise to higher frame-rates with it.

  11. hasanNo Gravatar Says:

    I am trying to animate a 2D fluid dynamics simulation which shows the voricity as a contour plot, and the velocity as a vector plot.

    PyQwt seems to have a very good contour support, whereas matplotlib supports animating vector plots (using blit), but does not do so for contour plots.

    I am split between which one to use.

  12. DrazickNo Gravatar Says:

    Is there a way to use Matplotlib within Matlab?

  13. elibenNo Gravatar Says:

    @Drazick, I have no idea. Why would you want to do that? I’m really curious.

  14. LukeNo Gravatar Says:

    Shameless plug:
    I’ve been working on a pure-python graphics library that combines PyQt and numpy. I use this library for displaying live video streams and plots that update very rapidly. I was previously using PyQwt, but found it difficult to support on various platforms since it is not pure python.
    My library is hosted at launchpad.net/pyqtgraph. Have a look, might suit your needs. There is no documentation at present, but it does have a bunch of examples demonstrating its capabilities.

  15. elibenNo Gravatar Says:

    @Luke,

    Looks interesting, thanks for sharing.

  16. JamesNo Gravatar Says:

    Thanks for a nice & well written article. I use PyQt & matplotlib extensively but will investigate PyQwt. The LabView type dials and gauges are of particular interest.

  17. fppNo Gravatar Says:

    Eli,

    As I am just getting started with 2D-plotting in PyQt I was really glad to find your very informative articles on this subject (and the examples you posted earlier), thank you !

    From your conclusion here I was eager to try out PyQwt first, which sounds like the easiest path for simple things. However, PyQwt has one drawback that you didn’t mention, probably because it only concerns Windows users who are not proficient in the Linux “compile-it-yourself” way…

    The roadblock is that currently PyQwt is only available as a Windows binary installer for very old versions of Python, Qt and PyQt. For people using more recent versions, trying it out means setting up an entire new environment, and a lot of unnecessary work.

    On the other hand, I just had to locate and install the relevant binaries for Numpy and matplotlib, and the other demo ran right away in my current setup. So I guess that’s what I’m going to tinker with… :-)

  18. elibenNo Gravatar Says:

    fpp

    Well, this article is from more than 2 years ago and I haven’t really touched PyQwt for a long time now, so thanks for this additional information – it’s definitely important for Windows users. I hope someone can create installers for newer versions of Python.

  19. StefanNo Gravatar Says:

    @fpp: The Python(x,y) distribution was recently updated to Python 2.7.2, and it includes PyQwt5.

  20. subhacomNo Gravatar Says:

    This is still a very useful article and one of the major starting points for comparing the two. Just thought I’ll add my two pence worth. I have been using both matplotlib and PyQwt: matplotlib for quick interactive plotting for testing purpose and PyQwt for a GUI application I coded to facilitate the frequently used functionalities.

    In short, I find matplotlib documentation is much more complete. PyQwt docs just lists the Qwt classes that have been ported and you have to refer to Qwt docs for details. But Qwt docs are often lacking information. Also, for simple plots PyQwt works fine, but for slightly advanced functionality it is often hard to twist into action. For example, the line and scatter plots are fine in both systems, but I hit a performance bottleneck when using spectrogram in PyQwt. It turns out that PyQwt5 does not implement QwtMatrixRasterData and one has to subclass QwtRasterData in Python for using in spectrogram. However, the problem is Qwt calls the value(x, y) function in your subclass (which is written in Python) for each pixel and this is very inefficient (for example when you resize the window).

  21. VladNo Gravatar Says:

    I had troubles working with MatplotlibWidget in PyQt4 (my class inherited from FigureCanvasQTAgg) which was extremely slow when resizing by dragging with a mouse. Finally I found a trick that solved my problem completely: do not rely on QWidget.update() being called automatically when resizing and write your own resize event with QWidget.repaint() in it! This will force immediate repainting and resizing will be smooth as you move the mouse.

    Snippet:
    import matplotlib
    import numpy
    matplotlib.use('Qt4Agg')
    from matplotlib.figure import Figure
    from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas

    class MatplotlibWidget(FigureCanvas):

    def __init__(self, parent=None, xlabel='x', ylabel='y', title='Title'):
    super(MatplotlibWidget, self).__init__(Figure())

    self.setParent(parent)
    self.figure = Figure(facecolor="w")
    self.figure.set_dpi(60)
    self.canvas = FigureCanvas(self.figure)
    self.axes = self.figure.add_subplot(111)
    x = numpy.linspace(-10, 10)
    self.axes.plot(x, sin(x**2))

    def resizeEvent(self, e):
    self.repaint() #!!!is necessary to resize matplotlib chart smoothly!!!
    super(MatplotlibWidget, self).resizeEvent(e)