1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
|
"""
.. _tutorials-ring-animation:
====================
Ring Graph Animation
====================
This example demonstrates how to use :doc:`matplotlib:api/animation_api` in
order to animate a ring graph sequentially being revealed.
"""
import igraph as ig
import matplotlib.pyplot as plt
import matplotlib.animation as animation
# sphinx_gallery_thumbnail_path = '_static/gallery_thumbnails/ring_animation.gif'
# %%
# Create a ring graph, which we will then animate
g = ig.Graph.Ring(10, directed=True)
# %%
# Compute a 2D ring layout that looks like an actual ring
layout = g.layout_circle()
# %%
# Prepare an update function. This "callback" function will be run at every
# frame and takes as a single argument the frame number. For simplicity, at
# each frame we compute a subgraph with only a fraction of the vertices and
# edges. As time passes, the graph becomes more and more complete until the
# whole ring is closed.
#
# .. note::
# The beginning and end of the animation are a little tricky because only
# a vertex or edge is added, not both. Don't worry if you cannot understand
# all details immediately.
def _update_graph(frame):
# Remove plot elements from the previous frame
ax.clear()
# Fix limits (unless you want a zoom-out effect)
ax.set_xlim(-1.5, 1.5)
ax.set_ylim(-1.5, 1.5)
if frame < 10:
# Plot subgraph
gd = g.subgraph(range(frame))
elif frame == 10:
# In the second-to-last frame, plot all vertices but skip the last
# edge, which will only be shown in the last frame
gd = g.copy()
gd.delete_edges(9)
else:
# Last frame
gd = g
ig.plot(gd, target=ax, layout=layout[:frame], vertex_color="yellow")
# Capture handles for blitting
if frame == 0:
nhandles = 0
elif frame == 1:
nhandles = 1
elif frame < 11:
# vertex, 2 for each edge
nhandles = 3 * frame
else:
# The final edge closing the circle
nhandles = 3 * (frame - 1) + 2
handles = ax.get_children()[:nhandles]
return handles
# %%
# Run the animation
fig, ax = plt.subplots()
ani = animation.FuncAnimation(fig, _update_graph, 12, interval=500, blit=True)
plt.ion()
plt.show()
# %%
# .. note::
#
# We use *igraph*'s :meth:`Graph.subgraph()` (see
# :meth:`igraph.GraphBase.induced_subgraph`) in order to obtain a section of
# the ring graph at a time for each frame. While sufficient for an easy
# example, this approach is not very efficient. Thinking of more efficient
# approaches, e.g. vertices with zero radius, is a useful exercise to learn
# the combination of igraph and matplotlib.
|