4

アニメーション化された散布図の例をこのような方法で適応させようとしたので、開発したエージェント ベースのモデルの結果がリアルタイムで表示されます。ただし、グラフに示されている結果は、私がそれらを除いてそうであるとは限りません。値を更新するとうまくいかず、エージェントが対角線上に集まる傾向がある場所に奇妙なパターンが現れます。この問題を説明する簡単なコードをいくつか追加しました。誰が何がうまくいかないのか考えていますか?

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
import os

n = 25 ## nr of agents
x,y = 10, 10 ## matrix of x by y dimension
dataX, dataY, binaryRaster = [],[],[]

class AnimatedScatter(object):
    """An animated scatter plot using matplotlib.animations.FuncAnimation."""
    def __init__(self):
        global n
        self.numpoints = n
        self.stream = self.data_stream()
        self.fig, self.ax = plt.subplots()
        self.ax.set_title("My first Agent Based Model (ABM)",fontsize=14)
        self.ax.grid(True,linestyle='-',color='0.75')
        self.ani = animation.FuncAnimation(self.fig, self.update, interval=100, 
                                           init_func=self.setup_plot, blit=True,
                                           repeat=False)

    def setup_plot(self):
        """Initial drawing of the scatter plot."""
        global x,y
        dataX,dataY = next(self.stream)
        self.scat = self.ax.scatter(dataY, dataX, c="tomato", s=20, animated=True)
        self.ax.axis([0, y, x, 0])
        return self.scat,

    def data_stream(self):
        """Generate a random walk (brownian motion). Data is scaled to produce
        a soft "flickering" effect."""
        global x,y, n

        dataX,dataY = self.createRandomData()

        #printing results to ascii for validation
        lines = []
        binaryData = np.zeros((x,y), dtype=np.int)
        for i in range(n):
            binaryData[dataX,dataY] =1
        for i in range(x):
            line = ""
            for j in range(y):
                line += str(binaryData[i,j])+ ","
            line= line[:-1]+ "\n"
            lines.append(line)
        lines.append("\n")

        yx = np.array([dataY,dataX])
        cnt = 0
        while cnt < 10:
            dataX,dataY = self.createRandomData()
            yx = np.array([dataY,dataX])

            #printing results to ascii for validation
            binaryData = np.zeros((x,y), dtype=np.int)
            for i in range(n):
                binaryData[dataX,dataY] =1
            for i in range(x):
                line = ""
                for j in range(y):
                    line += str(binaryData[i,j])+ ","
                line= line[:-1]+ "\n"
                lines.append(line)
            lines.append("\n")

            cnt+=1
            yield yx

        #printing results to ascii for validation

        outNm = os.getcwd()+"\\ScatterValidation.txt"
        outfile = open(outNm, "w")
        outfile.writelines(lines)
        outfile.close()
        return

    def update(self, i):
        """Update the scatter plot."""
        data = next(self.stream)
        self.scat.set_offsets(data[:2, :])
        return self.scat,

    def show(self):
        plt.show()

    def createRandomData(self):
        """Positions n agents randomly on a raster of x by y cells.
        Each cell can only hold a single agent."""

        global x,y,n
        binaryData = np.zeros((x,y), dtype=np.int)
        newAgents = 0
        dataX,dataY = [],[]
        while newAgents < n:
            row = np.random.randint(0,x,1)[0]
            col = np.random.randint(0,y,1)[0]
            if binaryData[row][col] != 1:
                binaryData[row][col] = 1
                newAgents+=1

        for row in range(x):
            for col in range(y):
                if binaryData[row][col] == 1:
                    dataX.append(row)
                    dataY.append(col)
        return dataX, dataY

def main():
    global n, x, y, dataX, dataY, binaryRaster
    a = AnimatedScatter()
    a.show()
    return

if __name__ ==  "__main__":
    main()
4

1 に答える 1

5

スクリプトは 2 つの方法で修正できます。どちらもupdate関数を変更する必要があります。

  1. 更新関数でスキャッター呼び出しを使用すると、より明確になると思います
  2. update で set_offsets を呼び出す前にデータ配列を転置する

スキャッター コールを使用するのが最も明確な修正方法であり、実行中にエージェントを増やすことができます。

def update(self, i):
    """Update the scatter plot."""
    dataX, dataY = next(self.stream)
    self.scat = self.ax.scatter(dataX, dataY, c="tomato", s=20, animated=True)
    return self.scat,

オフセット配列の転置も機能します。

def update(self, i):
    """Update the scatter plot."""
    data = next(self.stream)
    self.scat.set_offsets(data.transpose())
    return self.scat,

オフセットはそれぞれ 2 項目の N タプルとして与えられますが、データ配列はそれぞれ N 項目を持つ 2 つのタプルとして与えられます。データ配列を転置すると問題が解決します。

注: グローバル変数を変更しない場合は、global ステートメントでグローバルを指定する必要がないためsetup_plot__init__などで行を削除できますglobal n,x,y。とをクラスのインスタンス変数として配置しnます。さらに、スクリプトの先頭で を定義する必要はありません。xydataXdataYbinaryRasted

于 2012-10-15T10:37:06.927 に答える