February 28, 2010

Visualizing the Lorenz attractor in 3D with VTK

I just finished my nth reading of the James Gleick’s classic Chaos: Making a New Science and I realized that the famous Lorenz attractor should be much more exciting to explore in 3D. So here is a very simple Python code that resolve the nonlinear differential equation describing Lorenz oscillator and show the solution in a 3D phase space with VTK.

\frac{dx}{dt} = \sigma (y - x)
\frac{dy}{dt} = x (\rho - z) - y
\frac{dz}{dt} = x y - \beta z

The coolest think about the Lorenz attractor is the simplicity of it. You can retrieve it simply by resolving those three coupled equations which can be done in 10 line of code ! The rest is just the VTK kitchen sink.

Required packages: python-vtk, python-scipy, python-matplotlib

#!/usr/bin/env python
 
import vtk
from scipy import *
from scipy import integrate
from pylab import *
from vtk.util.colors import tomato, banana
 
nbrPoints = 5000
 
def Lorenz(w, t, S, R, B):
    x, y, z = w
    return array([S*(y-x), R*x-y-x*z, x*y-B*z])
 
w0 = array([0.0, 1.0, 0.0])
time = linspace(0.0, 100.0, nbrPoints)
S = 10.0; R = 28.0; B = 8.0/3.0
 
# Conditions initiales
y0=array([-7.5, -3.6, 30.0])
 
# On resous le tout avec odeint de scipy qui est
# lui-meme un wrap de ODEPACK en fortran
trajectory = integrate.odeint(Lorenz, w0, time, args=(S, R, B))
 
# This will be used later to get random numbers.
math = vtk.vtkMath()
 
# Total number of points.
numberOfInputPoints = nbrPoints
 
# One spline for each direction.
aSplineX = vtk.vtkCardinalSpline()
aSplineY = vtk.vtkCardinalSpline()
aSplineZ = vtk.vtkCardinalSpline()
 
inputPoints = vtk.vtkPoints()
for i in range(0, numberOfInputPoints):
    x = trajectory[i,0]
    y = trajectory[i,1]
    z = trajectory[i,2]
    aSplineX.AddPoint(i, trajectory[i,0])
    aSplineY.AddPoint(i, trajectory[i,1])
    aSplineZ.AddPoint(i, trajectory[i,2])
    inputPoints.InsertPoint(i, x, y, z)
 
# The following section will create glyphs for the pivot points
# in order to make the effect of the spline more clear.
 
# Create a polydata to be glyphed.
inputData = vtk.vtkPolyData()
inputData.SetPoints(inputPoints)
 
# Use sphere as glyph source.
balls = vtk.vtkSphereSource()
balls.SetRadius(.01)
balls.SetPhiResolution(10)
balls.SetThetaResolution(10)
 
glyphPoints = vtk.vtkGlyph3D()
glyphPoints.SetInput(inputData)
glyphPoints.SetSource(balls.GetOutput())
 
glyphMapper = vtk.vtkPolyDataMapper()
glyphMapper.SetInputConnection(glyphPoints.GetOutputPort())
 
glyph = vtk.vtkActor()
glyph.SetMapper(glyphMapper)
glyph.GetProperty().SetDiffuseColor(tomato)
glyph.GetProperty().SetSpecular(.3)
glyph.GetProperty().SetSpecularPower(30)
 
# Generate the polyline for the spline.
points = vtk.vtkPoints()
profileData = vtk.vtkPolyData()
 
# Number of points on the spline
numberOfOutputPoints = nbrPoints*10
 
# Interpolate x, y and z by using the three spline filters and
# create new points
for i in range(0, numberOfOutputPoints):
    t = (numberOfInputPoints-1.0)/(numberOfOutputPoints-1.0)*i
    points.InsertPoint(i, aSplineX.Evaluate(t), aSplineY.Evaluate(t),
                       aSplineZ.Evaluate(t))
 
# Create the polyline.
lines = vtk.vtkCellArray()
lines.InsertNextCell(numberOfOutputPoints)
for i in range(0, numberOfOutputPoints):
    lines.InsertCellPoint(i)
 
profileData.SetPoints(points)
profileData.SetLines(lines)
 
# Add thickness to the resulting line.
profileTubes = vtk.vtkTubeFilter()
profileTubes.SetNumberOfSides(8)
profileTubes.SetInput(profileData)
profileTubes.SetRadius(.05)
 
profileMapper = vtk.vtkPolyDataMapper()
profileMapper.SetInputConnection(profileTubes.GetOutputPort())
 
profile = vtk.vtkActor()
profile.SetMapper(profileMapper)
profile.GetProperty().SetDiffuseColor(banana)
profile.GetProperty().SetSpecular(.3)
profile.GetProperty().SetSpecularPower(30)
 
# Now create the RenderWindow, Renderer and Interactor
ren = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
 
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
 
# Add the actors
ren.AddActor(glyph)
ren.AddActor(profile)
 
renWin.SetSize(500, 500)
 
iren.Initialize()
renWin.Render()
iren.Start()


February 22, 2010

GitHub Social Graph – Part II

Here is a little Python class I made to retrieve a social graph from github. The ffDigraph() method generate a directed graph of a user by examining his followers list and his following list. The ffGraph() method is the most interesting one since it generate a undirected graph by adding only the nodes which mutually follow each other. This most restricted definition of the social graph is more significant then the the first one which often contains an overwhelming number of nodes following very popular project/user (like rails).

February 15, 2010

Visualize your own twitter graph – Part 2

Here is real (less shameful) version of my twitter graph generator. In fact, the last one was just a little test. This version actually generate a real graph with all the nodes adjacents to the twitter user. The final graph containt around 6200+ nodes. You can get a sample (4597 × 4699) of the image here. The real botteneck of the script are in the memory consumption of the PyGraphviz package used to draw the image of the graph, which is is a Python interface to the Graphviz graph layout and visualization package.

# Import pygraph
from pygraph.classes.graph import graph
from pygraph.classes.digraph import digraph
from pygraph.algorithms.searching import breadth_first_search
from pygraph.algorithms.traversal import traversal
from pygraph.readwrite.dot import write
 
# Import pygraphviz
from pygraphviz import *
 
# Import twython
import twython.core as twython
 
 
def getUserData(userID):
	'''
	Retrieve the social graph info from the user
	'''
	followingList = twitter.getFriendsIDs(id=userID)['ids']
	followersList = twitter.getFollowersIDs(id=userID)['ids']
	return [followingList, followersList]
 
 
def addUserToGraph(twGraph, userID):
	'''
	Add the user to the digraph
	'''	
	[followingList, followersList] = getUserData(userID)
 
	for twitterUser in followingList:
		if twitterUser not in twGraph.nodes():
			twGraph.add_node(twitterUser)
		if (userID, twitterUser) not in twGraph.edges():
			twGraph.add_edge([userID, twitterUser])
 
	for twitterUser in followersList:
		if twitterUser not in twGraph.nodes():
			twGraph.add_node(twitterUser)
		if (twitterUser, userID) not in twGraph.edges():
			twGraph.add_edge([twitterUser, userID])
 
	print str(len(twGraph)) + ' nodes'
 
 
# Some Parameters
useScreenName = False
Depth = 1
twitter = twython.setup(username="YOURUSERNAME", password="YOURPASSWORD")
 
# List of users to graph
myName = 'mlaprise'
myID = twitter.showUser(screen_name=myName)['id']
[followingList, followersList] = getUserData(myID)
 
# Graph creation
twitterGraph = digraph()
twitterGraph.add_node(myID)
addUserToGraph(twitterGraph, myID)
 
# Graph traversal
for d in range(Depth):
	retrievalItr = traversal(twitterGraph, myID, 'post')
	try:	
		while 1:
			userID=retrievalItr.next()
			addUserToGraph(twitterGraph, userID)
	except StopIteration:
		print 'Depth ' +str(d) ' Done !'
 
# Construct the image of the graph
dot = write(twitterGraph)
twitterGraphViz = AGraph(string=dot)
twitterGraphViz.graph_attr['label']='Twitter Graph of ' + myName
twitterGraphViz.graph_attr['dpi'] = '2'
twitterGraphViz.graph_attr['overlap'] = 'scale'
twitterGraphViz.node_attr['shape']='circle'
twitterGraphViz.node_attr['label']= ''
twitterGraphViz.node_attr['color']= 'blue'
twitterGraphViz.node_attr['style']= 'filled'
twitterGraphViz.edge_attr['color']='black'
twitterGraphViz.layout()
 
# Draw as PNG
twitterGraphViz.draw(myName + '_graph.png')
February 11, 2010

Now, let’s take a look at your GitHub neighborhood.

The GitHub social graph is an other cool thing to look at. The graph are made exactly the same way as the twitter one. I suspect the “commit” graph to be much more interesting.

import time
# Import pygraph
from pygraph.classes.graph import graph
from pygraph.classes.digraph import digraph
from pygraph.algorithms.searching import breadth_first_search
from pygraph.algorithms.traversal import traversal
from pygraph.readwrite.dot import write
 
# Import pygraphviz
from pygraphviz import *
 
# Import github2 api client
from github2.client import Github
 
def getUserData(userID):
	'''
	Retrieve the social graph info from the user
	'''
	followingList = github.users.following(userID)
	followersList = github.users.followers(userID)
 
	return [followingList, followersList]
 
def addUserToGraph(Graph, userID):
	'''
	Add the user to the digraph
	'''
	[followingList, followersList] = getUserData(userID)
 
	for snUser in followingList:
		if snUser not in Graph.nodes():
			Graph.add_node(snUser)
		if (userID, snUser) not in Graph.edges():
			Graph.add_edge([userID, snUser])
 
	for snUser in followersList:
		if snUser not in Graph.nodes():
			Graph.add_node(snUser)
		if (snUser, userID) not in Graph.edges():
			Graph.add_edge([snUser, userID])
	print str(len(Graph)) + ' nodes'
 
# Some Parameters
useScreenName = False
Depth = 2
github = Github(username='YOURUSERNAME',
			    api_token='YOURAPITOKEN')
 
# List of users to graph
myName = 'mlaprise'
myID = 'mlaprise'
[followingList, followersList] = getUserData(myID)
 
# Graph creation
githubGraph = digraph()
githubGraph.add_node(myID)
addUserToGraph(githubGraph, myID)
 
# Graph traversal
for d in range(Depth):
	retrievalItr = traversal(githubGraph, myID, 'post')
	try:
		while 1:
			userID=retrievalItr.next()
			'''
			Add a user to the graph
			Waiting 60 sec if we go beyond the
                        API limitation (60 requests/min)
			'''
			try:
				addUserToGraph(githubGraph, userID)
			except RuntimeError:
				time.sleep(60)
				addUserToGraph(githubGraph, userID)
	except StopIteration:
		print 'Depth ' + str(d+1) + ' Done !'
 
# Construct the image of the graph
dot = write(githubGraph)
githubGraphViz = AGraph(string=dot)
githubGraphViz.graph_attr['label']='Twitter Graph of ' + myName
githubGraphViz.graph_attr['dpi'] = '5'
githubGraphViz.graph_attr['overlap'] = 'scale'
githubGraphViz.node_attr['shape']='circle'
githubGraphViz.node_attr['label']= ''
githubGraphViz.node_attr['color']= 'blue'
githubGraphViz.node_attr['style']= 'filled'
githubGraphViz.edge_attr['color']='black'
githubGraphViz.layout()
 
# Draw as PNG
githubGraphViz.draw(myName + '_graph.png')
February 9, 2010

Visualize your own twitter graph

Are you wondering how your twitter neighborhood looks like ? Here is a simple way to construct a “following” graph with python-graph, pygraphviz and twython. Don”t try this at home with a 10000+ nodes graph … this is a bad idea ! Also, the Twitter API clients only allow users to make a limited number of calls in a given hour. You can check your rate limit status with the following command: twitter.getRateLimitStatus().

UPDATE: This version  is better

# Import pygraph
from pygraph.classes.graph import graph
from pygraph.classes.digraph import digraph
from pygraph.algorithms.searching import breadth_first_search
from pygraph.readwrite.dot import write
 
# Import pygraphviz
from pygraphviz import *
 
# Import twython
import twython.core as twython
 
showFollowing = True
 
twitter = twython.setup(username="youraccount", password="yourpassword")
 
# List of users to graph
twitterUserListName = ['mlaprise', 'nside', 'annicklaprise', 'irina_sorokina']
 
# Get the list of followers/friends
if len(twitterUserListName) > 1:
	twitterUserList = []
	for i in range(len(twitterUserListName)):
		twitterUserList.append(
			twitter.showUser(screen_name=twitterUserListName[i])['id'])
else:
	twitterUser = twitter.showUser(screen_name=twitterUserListName[0])['id']
	twitterUserList = twitter.getFriendsIDs(id=twitterUser)
 
# Graph creation
twitterGraph = digraph()
 
for twitterUser in twitterUserList:
	if twitterUser not in twitterGraph.nodes():
		twitterGraph.add_node(twitterUser)
 
for twitterUser in twitterUserList:
 
	friendsList = twitter.getFriendsIDs(id=twitterUser)
	# Add Friends nodes from the user
	for friends in friendsList['ids']:
		if friends not in twitterGraph.nodes():
			twitterGraph.add_node(friends)
		if (friends, twitterUser) not in twitterGraph.edges():
			twitterGraph.add_edge([friends, twitterUser])
 
	if showFollowing:
		followersList = twitter.getFollowersIDs(id=twitterUser)
		# Add Following nodes from the user
		for followers in followersList:
			if followers not in twitterGraph.nodes():
				twitterGraph.add_node(followers)
			if (twitterUser, followers) not in twitterGraph.edges():
				twitterGraph.add_edge([twitterUser, followers])
 
# Construct the image of the graph
dot = write(twitterGraph)
twitterGraphViz = AGraph(string=dot)
 
twitterGraphViz.graph_attr['label']='Twitter Graph of mlaprise'
twitterGraphViz.graph_attr['dpi'] = '10'
twitterGraphViz.graph_attr['overlap'] = 'scale'
twitterGraphViz.node_attr['shape']='circle'
twitterGraphViz.node_attr['label']= ''
twitterGraphViz.node_attr['color']= 'blue'
twitterGraphViz.node_attr['style']= 'filled'
twitterGraphViz.edge_attr['color']='black'
twitterGraphViz.layout()
 
# Draw as PNG
twitterGraphViz.draw(str(twitterUserListName[0]) + '_graph.png')