Анимация matplotlib не работает на Jupyter Notebook - PullRequest
0 голосов
/ 21 июня 2020

Я пытаюсь воссоздать игру жизни Комвея с этого веб-сайта: https://www.geeksforgeeks.org/conways-game-life-python-implementation/

И у меня возникла проблема со следующим разделом кода:

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() 

Я уже внес некоторые изменения в код, так как работаю над Jupyter Notebook, и аргументы парсера не работали, как было первоначально заявлено.

Идея этого упражнения состоит в создании анимации. Тем не менее, анимация не работает, а просто показывает своего рода изображение .png, которое не анимировано.

Согласно этот ответ , я должен добавить следующую строку (что я и сделал) :

%matplotlib tk

И он создает интерактивный бэкэнд со следующими параметрами: домой , назад , вперед, панорамирование , масштаб и загрузка кнопки. Однако они тоже не работают. Все доступные кадры показывают одно и то же изображение, а кнопка загрузки показывает пустую вкладку.

Итак, мой вопрос следующий: как можно улучшить этот код, чтобы анимация работала? Я думаю, что %matplotlib tk может go где-нибудь еще (например, перед строкой c), но я пробовал несколько комбинаций, и то, что я получил, было наиболее близким к тому, что я ищу.

Pd: Я также смотрел этот ответ , но этот подход не сработал.

1 Ответ

0 голосов
/ 21 июня 2020

Я пробую это и запускаю:

%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()

Я только очищаю код, удаляя argparse, и добавляю '% matplotlib tk', как вы говорите, в одну ячейку и запускаю.

Редактировать # 1

Чтобы помочь вам с вашим вопросом в комментариях, я напишу эту функцию.

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

Попробуйте это:

%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

Мне это нравится, и я обновляю, как изменить сетку ...

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

Используйте как:

%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()
...