简体   繁体   中英

Matplotlib animation not working on Jupyter Notebook

I'm trying to recreate Comway's game of life from this website: https://www.geeksforgeeks.org/conways-game-life-python-implementation/

And I'm facing an issue with the next section of the code:

def main(): 
  
    # Command line args are in sys.argv[1], sys.argv[2] .. 
    # sys.argv[0] is the script name itself and can be ignored 
    # parse arguments 
    parser = argparse.ArgumentParser(description="Runs Conway's Game of Life simulation.") 
  
    # add arguments 
    parser.add_argument('--grid-size', dest='N', required=False) 
    parser.add_argument('--mov-file', dest='movfile', required=False) 
    parser.add_argument('--interval', dest='interval', required=False) 
    parser.add_argument('--glider', action='store_true', required=False) 
    parser.add_argument('--gosper', action='store_true', required=False) 
    args, unknown = parser.parse_known_args()
    # args = parser.parse_args()
         
    # set grid size 
    N = 100
    if args.N and int(args.N) > 8: 
        N = int(args.N) 
          
    # set animation update interval 
    updateInterval = 50
    if args.interval: 
        updateInterval = int(args.interval) 
  
    # declare grid 
    grid = np.array([]) 
  
    # check if "glider" demo flag is specified 
    if args.glider: 
        grid = np.zeros(N*N).reshape(N, N) 
        addGlider(1, 1, grid) 
    elif args.gosper: 
        grid = np.zeros(N*N).reshape(N, N) 
        addGosperGliderGun(10, 10, grid) 
  
    else:   # populate grid with random on/off - 
            # more off than on 
        grid = randomGrid(N) 
        
    %matplotlib notebook
  
    # set up animation 
    fig, ax = plt.subplots() 
    img = ax.imshow(grid, interpolation='nearest') 
    ani = animation.FuncAnimation(fig, update, fargs=(img, grid, N, ), 
                                  frames = 10, 
                                  interval=updateInterval, 
                                  save_count=50) 

    # # of frames?  
    # set output file 
    if args.movfile: 
        ani.save(args.movfile, fps=30, extra_args=['-vcodec', 'libx264']) 
  
    plt.show() 
  
    # call main 
if __name__ == '__main__': 
    main() 

I already did some changes to the code since I'm working on Jupyter Notebook and parser arguments were not working as initially stated.

The idea of this exercise is to generate an animation. Nonetheless, the animation is not working and it just shows a sort of.png image which is not animated.

As per this response , I should add the next line (which I did):

%matplotlib tk

And it generates an interactive backend with the following options: home , back , forward , pan , zoom and download buttons. However, they are not working either. All the available frames show the same image and download button shows an empty tab.

So, my question is the following: How can this code be improved in order to get the animation working? I think that %matplotlib tk may go anywhere else (like before an specific line) but I have tried some combinations and what I got has been the closest to what I'm looking for.

Pd: I also looked at this response , but this approach didn't work.

I try this, and run:

%matplotlib tk
N = 100
updateInterval = 50
grid = randomGrid(N)
fig, ax = plt.subplots()
img = ax.imshow(grid, interpolation='nearest')

ani = animation.FuncAnimation(
    fig,
    update,
    fargs=(img, grid, N, ),
    frames=10,
    interval=updateInterval,
    save_count=50
)

plt.show()

I only clean the code removing argparse and add '%matplotlib tk' as you say, in one cell and run.

Edit #1

To help you with your question in comments I write this function.

def makeGrid(grid, text):
    for i, line in enumerate(text.splitlines()[1:]):
        print(line)
        for j, point in enumerate(line):
            if point != " ":
                grid[i][j] = 255
    return grid

Try this:

%matplotlib tk
N = 50
updateInterval = 50
grid = randomGrid(N)
grid.fill(0)
grid = makeGrid(grid, '''

       

                         x
                       x x
             xx      xx            xx
            x   x    xx            xx
 xx        x     x   xx
 xx        x   x xx    x x
           x     x       x
            x   x
             xx 
''')
fig, ax = plt.subplots()
img = ax.imshow(grid, interpolation='nearest')

ani = animation.FuncAnimation(
    fig,
    update,
    fargs=(img, grid, N, ),
    frames=10,
    interval=updateInterval,
    save_count=50
)

plt.show()

Edit #2

I like this, and I update how to modify the grid...

gliderstr = '''
--x
x-x
-xx
'''
gunstr = '''
------------------------x
----------------------x-x
------------xx------xx------------xx
-----------x---x----xx------------xx
xx--------x-----x---xx
xx--------x---x-xx----x-x
----------x-----x-------x
-----------x---x
------------xx
'''
def fill_grid(grid, iterable, value=255):
    for x, y in iterable:
        grid[x][y] = value
    return grid

def iter_text(text, accept='x', x=0, y=0):
    for i, line in enumerate(text.splitlines()):
        for j, ch in enumerate(line):
            if ch == accept:
                yield i + x, j + y

Use like:

%matplotlib tk
N = 100
update_interval = 50
grid = make_grid(N)
fill_grid(grid, iter_text(gunstr, 20, 20))
fill_grid(grid, iter_text(gliderstr, 0, 0))
fig, ax = plt.subplots()
img = ax.imshow(grid, interpolation='nearest')

ani = animation.FuncAnimation(
    fig,
    update,
    fargs=(img, grid, N, ),
    frames=10,
    interval=update_interval,
    save_count=50
)

plt.show()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM