networkx, matplotlib and pyqt4

1,055 views
Skip to first unread message

Hamed

unread,
Jul 19, 2009, 6:18:18 PM7/19/09
to networkx-discuss
Hello everyone,

I'm wondering if anyone knows of (or has done) a small example of
embedding a networkx drawn graph (through matplotlib) into a pyqt4
gui?

Thank you.

Aric Hagberg

unread,
Jul 19, 2009, 8:20:18 PM7/19/09
to networkx...@googlegroups.com
There is an example on the Matplotlib web page
http://matplotlib.sourceforge.net/examples/user_interfaces/embedding_in_qt4.py

Here is a slightly modified version that draws a graph with NetworkX.

Aric

#!/usr/bin/env python

# embedding_in_qt4.py --- Simple Qt4 application embedding matplotlib canvases
#
# Copyright (C) 2005 Florent Rougon
# 2006 Darren Dale
#
# This file is an example program for matplotlib. It may be used and
# modified with no restriction; raw copies as well as modified versions
# may be distributed without limitation.

import sys, os, random
from PyQt4 import QtGui, QtCore

from numpy import arange, sin, pi
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import networkx as nx

progname = os.path.basename(sys.argv[0])
progversion = "0.1"


class MyMplCanvas(FigureCanvas):
"""Ultimately, this is a QWidget (as well as a FigureCanvasAgg, etc.)."""
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
# We want the axes cleared every time plot() is called
self.axes.hold(False)

self.compute_initial_figure()

#
FigureCanvas.__init__(self, fig)
self.setParent(parent)

FigureCanvas.setSizePolicy(self,
QtGui.QSizePolicy.Expanding,
QtGui.QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)

def compute_initial_figure(self):
pass


class MyStaticMplCanvas(MyMplCanvas):
"""Simple canvas with a sine plot."""
def compute_initial_figure(self):
G=nx.path_graph(10)
pos=nx.spring_layout(G)
nx.draw(G,pos,ax=self.axes)


class ApplicationWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.setWindowTitle("application main window")

self.file_menu = QtGui.QMenu('&File', self)
self.file_menu.addAction('&Quit', self.fileQuit,
QtCore.Qt.CTRL + QtCore.Qt.Key_Q)
self.menuBar().addMenu(self.file_menu)

self.help_menu = QtGui.QMenu('&Help', self)
self.menuBar().addSeparator()
self.menuBar().addMenu(self.help_menu)

self.help_menu.addAction('&About', self.about)

self.main_widget = QtGui.QWidget(self)

l = QtGui.QVBoxLayout(self.main_widget)
sc = MyStaticMplCanvas(self.main_widget, width=5, height=4, dpi=100)
l.addWidget(sc)

self.main_widget.setFocus()
self.setCentralWidget(self.main_widget)

self.statusBar().showMessage("All hail matplotlib!", 2000)

def fileQuit(self):
self.close()

def closeEvent(self, ce):
self.fileQuit()

def about(self):
QtGui.QMessageBox.about(self, "About %s" % progname,
u"""%(prog)s version %(version)s
Copyright \N{COPYRIGHT SIGN} 2005 Florent Rougon, 2006 Darren Dale

This program is a simple example of a Qt4 application embedding matplotlib
canvases.

It may be used and modified with no restriction; raw copies as well as
modified versions may be distributed without limitation."""
% {"prog": progname, "version": progversion})


qApp = QtGui.QApplication(sys.argv)

aw = ApplicationWindow()
aw.setWindowTitle("%s" % progname)
aw.show()
sys.exit(qApp.exec_())
#qApp.exec_()

Ala Al-Shaibani

unread,
Jul 20, 2009, 9:09:36 AM7/20/09
to networkx...@googlegroups.com
Hello, thank you very much for the reply and the example!

One question though, why is it that two plots appear instead of one? (one with only x and y axis with nothing plotter, and the other appears on another window with the graph)


From: Aric Hagberg <aric.h...@gmail.com>
To: networkx...@googlegroups.com
Sent: Monday, 20 July, 2009 1:20:18
Subject: [networkx-discuss] Re: networkx, matplotlib and pyqt4

Aric Hagberg

unread,
Jul 20, 2009, 9:31:59 AM7/20/09
to networkx...@googlegroups.com
On Mon, Jul 20, 2009 at 7:09 AM, Ala Al-Shaibani<shai...@ymail.com> wrote:
> Hello, thank you very much for the reply and the example!
> One question though, why is it that two plots appear instead of one? (one
> with only x and y axis with nothing plotter, and the other appears on
> another window with the graph)

Not sure, I only get one plot when I run that code.
If you can't figure it out you might try
asking on the matplotlib users mailing list.

Aric

Ala Al-Shaibani

unread,
Jul 20, 2009, 1:48:12 PM7/20/09
to networkx...@googlegroups.com
I am trying to enable object picking on matplotlib. For example if I am plotting a network graph, I would want to set it so that if the user clicks on a node, a PyQt dialogue box will pop up telling the user details regarding that node.

Reading on matplotlib's user guide, it seems I need to set a picker tolerance when I plot:
line, = ax.plot(np.random.rand(100), 'o', picker=5)  # 5 points tolerance

Is it possible to do that when plotting networkx graphs using networkx.draw ? Or are there any suggestions on how I can go about implementing that?

Sent: Monday, 20 July, 2009 14:31:59

Subject: [networkx-discuss] Re: networkx, matplotlib and pyqt4

Christopher Ellison

unread,
Jul 20, 2009, 2:13:33 PM7/20/09
to networkx...@googlegroups.com
Ala Al-Shaibani wrote the following on 07/20/2009 10:48 AM:
> line, = ax.plot(np.random.rand(100), 'o', picker=5) # 5 points tolerance
>
> /
> /

> Is it possible to do that when plotting networkx graphs using
> networkx.draw ? Or are there any suggestions on how I can go about
> implementing that?
>

Matplotlib provides this functionality:

>>> line, = ax.plot(np.random.rand(100), 'o')
>>> line.set_picker(5)

Chris

Christopher Ellison

unread,
Jul 20, 2009, 2:39:40 PM7/20/09
to networkx...@googlegroups.com

Apologies for the cryptic response. The following (or something
similar) is what I had in mind:

>>> import matplotlib.pyplot as plt
>>> import networkx as nx
>>> g = nx.generators.bull_graph()
>>> nx.draw(g)
>>> ax = plt.gca()
>>> ax.set_picker(5)

> Chris

Ala Al-Shaibani

unread,
Jul 20, 2009, 8:22:21 PM7/20/09
to networkx...@googlegroups.com
Thank you for your reply.

For some reason, it still seems complicated for me on how I can achieve what I want.

Hence below is a small program with all what i know so far (a bit simplified). In the example below, I have made a graph of 3 connected nodes numbered 0 1 and 2. In this example, I want to either print the number of the node clicked, or locs[i] for demonstration purpose. What should the code in the onpick method be?

Thanks very much for any input, hopefully I'll be able to grasp the integration of networkx and matplotib (and finally integrate them with pyqt).

Code:

from pylab import figure, show
import networkx as nx
fig = figure()
ax1 = fig.add_subplot(111)

g = nx.Graph()
g.add_path([0, 1, 2])
pos = nx.spring_layout(g)
nx.draw(g, pos, ax= ax1)
ax1.set_picker(5)
locs = ['uk', 'france', 'usa']

def onpick(event):
# print locs[i], where i is the number of the node clicked

fig.canvas.mpl_connect('pick_event', onpick)
show()


From: Christopher Ellison <cell...@cse.ucdavis.edu>
To: networkx...@googlegroups.com
Sent: Monday, 20 July, 2009 19:39:40

Subject: [networkx-discuss] Re: networkx, matplotlib and pyqt4

Christopher Ellison

unread,
Jul 20, 2009, 9:55:01 PM7/20/09
to networkx...@googlegroups.com
Ala Al-Shaibani wrote the following on 07/20/2009 05:22 PM:
>
> Hence below is a small program with all what i know so far (a bit
> simplified). In the example below, I have made a graph of 3 connected
> nodes numbered 0 1 and 2. In this example, I want to either print the
> number of the node clicked, or locs[i] for demonstration purpose. What
> should the code in the onpick method be?
>

I found the following page quite useful:

http://matplotlib.sourceforge.net/users/event_handling.html

To do what you seek, we need access to the matplotlib artist that is
created when networkx draws your graph. Once you have that, everything
else can be found in the matplotlib documentation.

I've attached an example,
Chris

testing.py

Aric Hagberg

unread,
Jul 20, 2009, 11:09:22 PM7/20/09
to networkx...@googlegroups.com
On Mon, Jul 20, 2009 at 6:22 PM, Ala Al-Shaibani<shai...@ymail.com> wrote:
> Thank you for your reply.
> For some reason, it still seems complicated for me on how I can achieve what
> I want.
> Hence below is a small program with all what i know so far (a bit
> simplified). In the example below, I have made a graph of 3 connected nodes
> numbered 0 1 and 2. In this example, I want to either print the number of
> the node clicked, or locs[i] for demonstration purpose. What should the code
> in the onpick method be?
> Thanks very much for any input, hopefully I'll be able to grasp the
> integration of networkx and matplotib (and finally integrate them with
> pyqt).

Well "integration" is is probably not the word I would use
to descibe how networkx interacts with matplotlib :-/.
It is a hack that could be improved a lot.

Nevertheless matplotlib is great and you can do what you want like this.
You have to draw the nodes, edges, and labels separately so you
can get access to the matplotlib patch collection to set the picker.

Aric


from pylab import figure, show
import networkx as nx
fig = figure()
ax1 = fig.add_subplot(111)

g = nx.Graph()
g.add_path([0, 1, 2])
pos = nx.spring_layout(g)

nodes=nx.draw_networkx_nodes(g, pos, ax= ax1)
nodes.set_picker(True)

edges=nx.draw_networkx_edges(g, pos, ax= ax1)

locs = ['uk', 'france', 'usa']

labels=dict(zip(range(3),locs))
nx.draw_networkx_labels(g, pos, ax= ax1,labels=labels)


def onpick(event):
ind=event.ind[0]
print labels[ind]
return True

Xinfeng Li

unread,
May 10, 2015, 11:19:31 PM5/10/15
to networkx...@googlegroups.com, ala.als...@gmail.com
Hi, I currently encount this problem, too

I have embed a canvas in CentralWidget of the mainWindow, but when a call nx.draw(G, ax = my_axes), it still have nothing to draw out.

any one can enlight me ?

Adolfo Núñez

unread,
Sep 1, 2015, 7:33:26 AM9/1/15
to networkx-discuss, ala.als...@gmail.com
Hi,

after nx.draw(G, ax = my_axes) try self.your_widget.draw() or just your_widget.draw() 

Hope this helps
Reply all
Reply to author
Forward
0 new messages