Animated graph of points connected by edges

I have a question similar to this question , but instead of building a very large number of points, I have fewer points and edges (coefficient of at least 10), but want to revive them. To be more specific, this is a visualization of the Kohonen network with a 2D map that evolves and looks like a deformed square of the lattice, see this image from Wikipedia:

image

I took the code from this by editing a little, the minimum example is as follows:

import numpy as np import matplotlib.pyplot as plt def getXY(points, edges): """Return x and y arrays to pass to the plot function""" return [points.T[i][edges.T] for i in np.arange(points.shape[1])] points = numpy.array([[1,2],[4,5],[2,7],[3,9],[9,2]]) edges = numpy.array([[0,1],[3,4],[3,2],[2,4]]) lines = plt.plot(*getXY(points, edges), linestyle='-', color='y', markerfacecolor='red', marker='o') plt.show() 

Then there is an update that changes the coordinates of the points:

 points += 1 # simplified version of a real update 

I would like to avoid the β€œstupid” way to change everything, because there are other data in the chart window that do not change, and this is very slow:

 # repeat after each update all the calculation plt.cla() x, y = [points.T[i][edges.T] for i in np.arange(points.shape[1])] lines = plt.plot(x, y, linestyle='-', color='y', markerfacecolor='red', marker='o') plt.show() 

As a first step, I saved the created Line2D data from the initial graph in the lines variable. The problem I'm facing right now is that if I just want to update the line data, the only solution I could come up with requires me to iterate over all the lines, which is not very elegant for me:

 x, y = getXY(points, edges) if len(lines) > 1: for i, d in enumerate(zip(xT, yT)): lines[i].set_data(d) else: # has to be treated seperately, since the format of x and y is different lines[0].set_data(x, y) plt.show() 

I am looking for offers like ...

  • Come up with a better solution than my for-loop
  • Ideas on how to solve the initial problem (building points with the indicated connections) in a more elegant way
+4
source share
1 answer

Here is one possible way. You can use the fact that if there are NaNs or None in the line coordinates, this is considered to be essentially the end of the line segment. The next point, other than None, is seen as the beginning of a new segment.

 import numpy as np, matplotlib.pyplot as plt x,y = np.array([1, 4,2, 3, 9]), np.array([2, 5, 7, 9, 2]) edges = np.array([[0, 1], [3, 4], [3, 2], [2, 4], [2, 1]]) ys=np.vstack((y[edges[:,0]],y[edges[:,1]],y[edges[:,0]]+np.nan)).T.flatten() xs=np.vstack((x[edges[:,0]],x[edges[:,1]],x[edges[:,0]]+np.nan)).T.flatten() lines2d = plt.plot(xs,ys,marker='o') 

Now, to update the coordinates (for example, shift the x axis by .1 and the y axis by .2, you can only do:

 oldx,oldy=lines2d[0].get_data() lines2d[0].set_data(oldx+.1,oldy+.2) plt.draw() 

PS I'm not quite sure that my way of inserting Nans into xs, ys arrays is the fastest, but it probably doesn't matter much.

0
source

Source: https://habr.com/ru/post/1398066/


All Articles