在for循环中动态更新网格上的项目(python)

时间:2018-01-15 10:43:24

标签: python matplotlib simulation

我正在尝试在for循环中动态更新绘图,但我无法使其工作。我想知道是否有人可以提供帮助?

我在传递数字与轴以及如何更新之间有点困惑。我一直在尝试使用

display.clear_output(wait=True)
display.display(plt.gcf())
time.sleep(2)

但它并没有按我的意愿行事。

我正在尝试: 1.将对象添加到网格(setupGrid2) 2.在时间步长 - 随机方向移动每个对象(makeMove2) 3.在网格上直观地更新每个对象的位置(updateGrid2)

我的问题在于3.我想清除上一步,以便只显示每个对象的新位置。显示对象在网格中动态移动的目标。

我还想使用在setupGrid2中创建的ax对象,这样我就可以在一个地方设置绘图变量(标题,图例等)并更新该图表。

感谢任何帮助。

下面的示例代码(用于在jupyter笔记本中运行):

 %matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import time
import pylab as pl
from IPython import display


def setupGrid2(norows,nocols,noobjects):
    #each object needs current grid position (x and y coordinate)
    objects = np.zeros(noobjects)
    ObjectPos = np.zeros(shape=(noobjects,2))

    #put objects randomly on grid
    for i in range (noobjects):
        ObjectPos[i][0] = np.random.uniform(0,norows)
        ObjectPos[i][1] = np.random.uniform(0,nocols)

    #plot objects on grid
    fig = plt.figure(1,figsize=(15,5))
    ax = fig.add_subplot(1,1,1)
    x,y  = zip(*ObjectPos)
    ax.scatter(x, y,c="b", label='Initial positions')
    ax.grid()
    plt.show()

    return ax,ObjectPos

def updateGrid2(ax,ObjPos):
    x,y  = zip(*ObjPos)
    plt.scatter(x, y)
    display.clear_output(wait=True)
    display.display(plt.gcf())
    time.sleep(0.1)

#move object in a random direction
def makeMove2(object,xpos,ypos):
    #gets a number: 1,2,3 or 4
    direction = int(np.random.uniform(1,4))

    if (direction == 1):
        ypos = ypos+1
    if (direction == 2):
        ypos = ypos - 1
    if (direction == 3):
        xpos = xpos+1
    if (direction == 4):
        xpos = xpos-1
    return xpos,ypos

def Simulation2(rows,cols,objects,steps):

    ax,ObjPos = setupGrid2(rows,cols,objects)

    for i in range(steps):
        for j in range (objects):
            xpos = ObjPos[j][0]
            ypos = ObjPos[j][1]
            newxpos,newypos = makeMove2(j,xpos,ypos)
            ObjPos[j][0] = newxpos
            ObjPos[j][1] = newypos
            updateGrid2(ax,ObjPos)

Simulation2(20,20,2,20) 

1 个答案:

答案 0 :(得分:1)

您似乎想要更新散点图,而不是为每个帧生成新的散点图。这将在这个问题中显示出来。当然,你可以在jupyter中使用display而不是使用ion或FuncAnimation显示的解决方案。

保留问题中的代码大致完整,这可能如下所示。

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import time
import pylab as pl
from IPython import display


def setupGrid2(norows,nocols,noobjects):
    #each object needs current grid position (x and y coordinate)
    objects = np.zeros(noobjects)
    ObjectPos = np.zeros(shape=(noobjects,2))

    #put objects randomly on grid
    for i in range (noobjects):
        ObjectPos[i,0] = np.random.uniform(0,norows)
        ObjectPos[i,1] = np.random.uniform(0,nocols)

    #plot objects on grid
    fig = plt.figure(1,figsize=(15,5))
    ax = fig.add_subplot(1,1,1)
    ax.axis([0,nocols+1,0,norows+1])
    x,y  = zip(*ObjectPos)
    scatter = ax.scatter(x, y,c="b", label='Initial positions')
    ax.grid()

    return ax,scatter,ObjectPos

def updateGrid2(ax,sc,ObjPos):
    sc.set_offsets(ObjPos)
    display.clear_output(wait=True)
    display.display(plt.gcf())
    time.sleep(0.1)

#move object in a random direction
def makeMove2(object,xpos,ypos):
    #gets a number: 1,2,3 or 4
    direction = int(np.random.uniform(1,4))

    if (direction == 1):
        ypos = ypos+1
    if (direction == 2):
        ypos = ypos - 1
    if (direction == 3):
        xpos = xpos+1
    if (direction == 4):
        xpos = xpos-1
    return xpos,ypos

def Simulation2(rows,cols,objects,steps):

    ax,scatter,ObjPos = setupGrid2(rows,cols,objects)

    for i in range(steps):
        for j in range (objects):
            xpos = ObjPos[j,0]
            ypos = ObjPos[j,1]
            newxpos,newypos = makeMove2(j,xpos,ypos)
            ObjPos[j,0] = newxpos
            ObjPos[j,1] = newypos
        updateGrid2(ax,scatter,ObjPos)

Simulation2(20,20,3,20)