欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-13 09:14:29
...

代码如下:

心得后附。

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

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




相关标签: python 动画