今天把 MATPLOTLIB的动态散点图代码 读懂了

代码如下:

心得后附。

今天把 MATPLOTLIB的动态散点图代码 读懂了_第1张图片

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


class AnimatedScatter(object):
    """An animated scatter plot using matplotlib.animations.FuncAnimation."""
    def __init__(self, numpoints=50):
        self.numpoints = numpoints
        self.stream = self.data_stream()


        # Setup the figure and axes...
        self.fig, self.ax = plt.subplots()
        # Then setup FuncAnimation.
        self.ani = animation.FuncAnimation(self.fig, self.update, interval=5, 
                                           init_func=self.setup_plot, blit=True)


    def setup_plot(self):
        """Initial drawing of the scatter plot."""
        x, y, s, c = next(self.stream)
        self.scat = self.ax.scatter(x, y, c=c, s=s, animated=True)
        self.ax.axis([-10, 10, -10, 10])


        # For FuncAnimation's sake, we need to return the artist we'll be using
        # Note that it expects a sequence of artists, thus the trailing comma.
        return self.scat,


    def data_stream(self):
        """Generate a random walk (brownian motion). Data is scaled to produce
        a soft "flickering" effect."""
        data = np.random.random((4, self.numpoints))
        xy = data[:2, :]
        s, c = data[2:, :]
        xy -= 0.5
        xy *= 10
        while True:
            xy += 0.03 * (np.random.random((2, self.numpoints)) - 0.5)
            s += 0.05 * (np.random.random(self.numpoints) - 0.5)
            c += 0.02 * (np.random.random(self.numpoints) - 0.5)
            yield data


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


        # Set x and y data...
        self.scat.set_offsets(data[:2, :])
        # Set sizes...
        self.scat._sizes = 300 * abs(data[2])**1.5 + 100
        # Set colors..
        self.scat.set_array(data[3])


        # We need to return the updated artist for FuncAnimation to draw..
        # Note that it expects a sequence of artists, thus the trailing comma.
    
        return self.scat,


    def show(self):
        plt.show()


if __name__ == '__main__':
    a = AnimatedScatter()
    a.show()



简单解释一下程序,我的理解
1. 程序定义了一个动态散点类

然后在主程序中实例化了这个类并调用了类的show()函数

class AnimatedScatter(object):

...

if __name__ == '__main__':
    a = AnimatedScatter()

    a.show()


2. 下面看看这个类都实现的功能


class AnimatedScatter(object):
    
    def __init__(self, numpoints=50):

    def setup_plot(self):

    def data_stream(self):

    def update(self, i):

    def show(self):

上述函数,其实都是为了这句服务的:self.ani = animation.FuncAnimation(self.fig, self.update, interval=5, init_func=self.setup_plot, blit=True)


3. 下面对程序进行注释

import matplotlib.pyplot as plt                     #引入pyplot绘图函数
import matplotlib.animation as animation   #引入动画函数
import numpy as np


class AnimatedScatter(object):              #定义类


    def __init__(self, numpoints=50):     #定义类初始函数 请与 绘图的初始化函数区分开
        self.numpoints = numpoints         #散点数为50
        self.stream = self.data_stream()   #调用类的数据流函数,此函数提供了无尽的数据流,给50个散点的X,Y坐标,s是直径,c是颜色这4个值进行赋值。相当于每次迭代提供(4,50)的一个数据块。
        self.fig, self.ax = plt.subplots()  #设置绘图画布及绘图区域
        self.ani = animation.FuncAnimation(self.fig, self.update, interval=5, 
                                           init_func=self.setup_plot, blit=True)    #进入此句后,程序进入迭代状态,直到退出。此FuncAnimation()函数先调用init_func对画面初始化,然后以5ms一帧的速率用update函数进行迭代。blit是指动态图进行位块输送的优化。


    def setup_plot(self):  #设置绘画,相当于绘图的初始化函数
        x, y, s, c = next(self.stream)  #迭代,用stream对x,y,s,c进行一次赋值,注意stream指向data_stream()
        self.scat = self.ax.scatter(x, y, c=c, s=s, animated=True) # 利用上述值绘制散点图
        self.ax.axis([-10, 10, -10, 10]) #设立X,Y坐标轴的起始与终止点
        return self.scat, # 初始化函数返回散点图的句柄


    def data_stream(self):  #数据流函数,注意此函数在绘图的初始化函数和迭代函数中均被调用
        data = np.random.random((4, self.numpoints))#初始化一个(4,50)数组,数组中数为【0,1)的随机数
        xy = data[:2, :]  #取数组的前2行,为50个点 的XY坐标赋值,注意xy是指向data数组前两行的指针
        s, c = data[2:, :] #取数组的后两行,分别为50个点的S和C赋值,同上,S和C指向data数组后两行
        xy -= 0.5   #对XY的值做调整
        xy *= 10   #对XY的值做调整,以便匹配-10:10的坐标
        while True:  #进入迭代,每次上个函数setup_pl
            xy += 0.03 * (np.random.random((2, self.numpoints)) - 0.5)  #迭代直接修改了data的值
            s += 0.05 * (np.random.random(self.numpoints) - 0.5)
            c += 0.02 * (np.random.random(self.numpoints) - 0.5)
            yield data    #返回data值,注意data是个(4,50)的数组


    def update(self, i): #此函数每次迭代都会被调用,此函数在绘制动态图中已经被定义为迭代函数,此迭代函数的作用是利用data的值,给散点函数的50个点重新赋值,此i有何作用还请大牛指点。
        data = next(self.stream)   #更新data值
        self.scat.set_offsets(data[:2, :])  #设置散点的XY
        self.scat._sizes = 300 * abs(data[2])**1.5 + 100#设置散点直径
        self.scat.set_array(data[3])  #设置散点颜色


        # We need to return the updated artist for FuncAnimation to draw..
        # Note that it expects a sequence of artists, thus the trailing comma.
    
        return self.scat,  #为何返回散点绘图函数句柄,不明白?是因为动画函数需要么?


    def show(self):  #开始绘制函数
        plt.show()


if __name__ == '__main__':  #主函数
    a = AnimatedScatter()   #定义类,注意定义类会调用类的初始化函数,从而启动整个流程

    a.show()  # 开始绘制,这步只是将上一步的绘制显示到屏幕上,具体为什么能从上面的迭代过程跳出来开始绘制动画,这个我也不懂啥机制。




你可能感兴趣的:(今天把 MATPLOTLIB的动态散点图代码 读懂了)