Search code examples
pythonanimationmatplotlibimshowrandom-walk

Animated matplotlib imshow


Let me first clarify that I'm not trying to generate random walk lines like in this and many other questions. I'm trying to make a random walk heat map that changes color as points are revisted, like this.

I've been able to create still-lifes like this:results of random walk but I want to see the process.

I can get the figure to show up, and if I print the array at each step I can see that the walk is working. But the figure itself doesn't animate. My code:

import matplotlib as mpl
from matplotlib import pyplot as plt
from matplotlib import animation as anim
import numpy as np
import sys
import random

length = int(sys.argv[1])

fig = plt.figure()
ax = plt.axes(xlim=(0, length-1), ylim=(0, length-1))
arr = np.zeros((length, length), dtype = int)

cmap = mpl.colors.LinearSegmentedColormap.from_list('my_colormap',
                                                    ['black','green','white'],
                                                    256)
bounds=[0,0,10,10]
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)

im=plt.imshow(arr, interpolation='nearest',
              cmap = cmap,
              origin='lower')

x = int(np.random.random_sample() * length)
y = int(np.random.random_sample() * length)

def walk():
    global x, y
        rand = np.random.random_sample()
        if rand < 0.25 :
            if x == length - 1:
                x = 0
            else: x = x + 1
        elif rand < 0.5 :
            if x == 0:
                x = length - 1
            else: x = x - 1
        elif rand < 0.75 :
            if y == length - 1:
                y = 0
            else: y = y + 1
        else:
            if y == 0:
                y = length - 1
            else: y = y - 1
    return

def stand(arr):
    global x,y
    arr[x][y] = arr[x][y] + 1
    return arr

def animate(i):
    arr=im.get_array()
    walk()
    #print(a)
    arr = stand(arr)
    im.set_array(arr)
    return [im]

anim = anim.FuncAnimation(fig, animate, frames=200, interval=20, blit=True)
plt.show()

Running Python 3.6, as you can see by the print.

There are so many videos with these animated grids and I can't find any answers! Somebody must know how to do it. Thanks!


Solution

  • I added animated=True and vmin=0, vmax=255, in the imshow() function below. I also changed the stand() line to arr[x][y] = arr[x][y] + 10.

    #!/usr/bin/env python3
    import matplotlib as mpl
    from matplotlib import pyplot as plt
    from matplotlib import animation as anim
    import numpy as np
    import sys
    import random
    
    length = int(sys.argv[1])
    
    fig = plt.figure()
    ax = plt.axes(xlim=(0, length-1), ylim=(0, length-1))
    arr = np.zeros((length, length), dtype = int)
    
    cmap = mpl.colors.LinearSegmentedColormap.from_list('my_colormap',
                                                        ['black','green','white'],
                                                        256)
    bounds=[0,0,10,10]
    norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
    
    im=plt.imshow(arr, interpolation='nearest',
            cmap = cmap, vmin=0, vmax=255,
                  origin='lower', animated=True) # small changes here
    
    x = int(np.random.random_sample() * length)
    y = int(np.random.random_sample() * length)
    
    def walk():
        global x, y
        rand = np.random.random_sample()
        if rand < 0.25 :
            if x == length - 1:
                x = 0
            else: x = x + 1
        elif rand < 0.5 :
            if x == 0:
                x = length - 1
            else: x = x - 1
        elif rand < 0.75 :
            if y == length - 1:
                y = 0
            else: y = y + 1
        else:
            if y == 0:
                y = length - 1
            else: y = y - 1
        return
    
    def stand(arr):
        global x,y
        arr[x][y] = arr[x][y] + 1000
        return arr
    
    def animate(i):
        global x,y
        arr=im.get_array()
        walk()
        #print(a)
        arr = stand(arr)
        im.set_array(arr)
        return [im]
    
    anim = anim.FuncAnimation(fig, animate, frames=200, interval=20, blit=True)
    plt.show()
    

    And I ran it with length = 50 and I get an animation. See it here. So you may have to play around with your color choices a bit.