I'm trying to add a frame number to a simulation visualization modified from here. Is there any simple way to add a frame number to this animation so that it displays as a part of the plot title?
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from netgraph import Graph
# Simulate a dynamic network with
total_frames = 10
total_nodes = 5
NODE_LABELS = {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E'}
NODE_POS = {0: (0.0, 0.5), 1: (0.65, 0.25), 2: (0.7, 0.5), 3: (0.5, 0.75), 4: (0.25, 0.25)}
adjacency_matrix = np.random.rand(total_nodes, total_nodes) < 0.25
weight_matrix = np.random.randn(total_frames, total_nodes, total_nodes)
# Normalise the weights, such that they are on the interval [0, 1].
# They can then be passed directly to matplotlib colormaps (which expect floats on that interval).
vmin, vmax = -2, 2
weight_matrix[weight_matrix<vmin] = vmin
weight_matrix[weight_matrix>vmax] = vmax
weight_matrix -= vmin
weight_matrix /= vmax - vmin
cmap = plt.cm.RdGy
fig, ax = plt.subplots()
fig.suptitle('Simulation viz @ t=', x= 0.15, y=0.95)
g = Graph(adjacency_matrix, node_labels=NODE_LABELS,
node_layout = NODE_POS, edge_cmap=cmap, arrows=True, ax=ax)
def update(ii):
artists = []
for jj, kk in zip(*np.where(adjacency_matrix)):
w = weight_matrix[ii, jj, kk]
artist = g.edge_artists[(jj, kk)]
artist.set_facecolor(cmap(w))
artist.update_width(0.03 * np.abs(w-0.5))
artists.append(artist)
return artists
animation = FuncAnimation(fig, update, frames=total_frames, interval=200, blit=True, repeat=False)
plt.show()
Thank you. I would appreciate any help/suggestions.
When animating while using blit (blit=True
), figure level titles cannot be changed, as blit caches everything outside of the axis being animated.
The simplest change is to set blit to false, and then update the figure title within the animation update function.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from netgraph import Graph
# Simulate a dynamic network with
total_frames = 10
total_nodes = 5
NODE_LABELS = {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E'}
NODE_POS = {0: (0.0, 0.5), 1: (0.65, 0.25), 2: (0.7, 0.5), 3: (0.5, 0.75), 4: (0.25, 0.25)}
adjacency_matrix = np.random.rand(total_nodes, total_nodes) < 0.25
weight_matrix = np.random.randn(total_frames, total_nodes, total_nodes)
# Normalise the weights, such that they are on the interval [0, 1].
# They can then be passed directly to matplotlib colormaps (which expect floats on that interval).
vmin, vmax = -2, 2
weight_matrix[weight_matrix<vmin] = vmin
weight_matrix[weight_matrix>vmax] = vmax
weight_matrix -= vmin
weight_matrix /= vmax - vmin
cmap = plt.cm.RdGy
fig, ax = plt.subplots()
title = fig.suptitle('Simulation viz @ t=', x= 0.15, y=0.95) # <----
g = Graph(adjacency_matrix, node_labels=NODE_LABELS,
node_layout = NODE_POS, edge_cmap=cmap, arrows=True, ax=ax)
def update(ii):
artists = []
for jj, kk in zip(*np.where(adjacency_matrix)):
w = weight_matrix[ii, jj, kk]
artist = g.edge_artists[(jj, kk)]
artist.set_facecolor(cmap(w))
artist.update_width(0.03 * np.abs(w-0.5))
artists.append(artist)
title.set_text(f"Simulation viz @ t={ii}") # <----
return artists
animation = FuncAnimation(fig, update, frames=total_frames, interval=200, blit=False, repeat=False)
plt.show()