I'm trying to find the neatest way to make an animation similar to this one, with the difference that I need to update the graph topology and the vertices' properties synchronously (it's a graph analog of the game of life). I have been doing so far by simply constructing a graph sequence by copying the graph on the (i-1)-th iteration, computing alterations based on the original graph, and returning the updated copy.
As it seems to me, the problem with this approach is that when using GraphWindow
, like in the linked example, I need to modify the graph in-place, instead of making copies. So the best I could do was to iterate twice over the graph, at each call of the update_state
function. The first iteration is to compute the new states, the second to assign them. A batch assignment would work for properties with scalar values, but I couldn't manage to do it for properties with string values.
Summing it up, I want to, at each call of update_state
, update synchronously two properties, a scalar one, corresponding to the state of a vertex, vp.state
, and a string-valued one, corresponding to its color, vp.color
;
This is an excerpt of the full code (the update_state
function -- which I named run_simulation
)
def run_simulation():
global count, g
to_remove = []
alterations = []
r = 0
for v in g.get_vertices():
if len(g.get_all_edges(v)) == 0:
print(r)
r+=1
to_remove.append(v)
else:
Nv = g.get_all_neighbors(v)
sum_nbstates = sum([g.vp.state[u] for u in Nv])
nb_size = len(Nv)
acoef = sum_nbstates / nb_size
if g.vp.state[v] == 1:
if 2 / nb_size <= acoef <= 3 / nb_size:
state = 1
color = "white"
else:
state = 0
color = "black"
elif g.vp.state[v] == 0:
# if (acoef == 3/nb_size):
if 2 / nb_size <= acoef <= 4 / nb_size:
state = 1
color = "white"
else:
state = 0
color = "black"
alterations.append([v, state, color])
states.append(state)
colors.append(color)
###some checks
#print(vertices)
diff = len(to_remove)
if diff >= 1:
print(f"diff {diff}, count {count}") #this eventually results in something ≠ 0, I still haven't find out why
###
for (v, new_state, new_color) in alterations:
g.vp.state[v] = new_state
g.vp.color[v] = new_color
gt.sfdp_layout(
g, pos=g.vp.pos, eweight=g.ep.weight, max_iter=1, init_step=0.01, K=0.5
)
g.remove_vertex(to_remove)
count += 1
win.graph.regenerate_surface()
win.graph.queue_draw()
if OFFSCREEN:
pixbuf = win.get_pixbuf()
pixbuf.savev(r'./frames/graphol%06d.png' % count, 'png', [], [])
if count >= max_count:
sys.exit(0)
return True