如何使用 python matplotlib 与另一个代码并行运行动画?

Posted

技术标签:

【中文标题】如何使用 python matplotlib 与另一个代码并行运行动画?【英文标题】:How to run animation in parallel with another code with python matplotlib? 【发布时间】:2022-01-14 19:30:09 【问题描述】:

接下来的代码是用ma​​tplotlib.FuncAnimation

制作动画
def animate(i):
    x_val = changing_list
    y_val = another_changing_list
    plt.cla()
    plt.scatter(x_val, y_val)

ani = animation.FuncAnimation(plt.gcf(), animate, interval =1000)
plt.show()

我想知道的是如何使用这样的循环同时运行该动画:

for value in values_list:
    changing_list.append(value)

结果是一个动画,立即显示 changeing_list 列表中的新值。

如果有任何帮助,我将不胜感激!

【问题讨论】:

对我来说太难了,看看:***.com/questions/18791722/… 只是为了澄清(我是新手)同时意味着你想在两个不同的线程中运行绘图和循环,并将数据从一个线程传输到另一个线程? pypi.org/project/stream-engine StreamEngine 是 matplotlib Animation 类的扩展,使用户能够轻松绘制实时流数据。 找到matplotlib.org/3.1.0/gallery/misc/multiprocess_sgskip.html 【参考方案1】:

不确定你的时代要求什么,很确定不是最好的方法:

尝试 1:

import time
from threading import Thread, Event, Lock

import matplotlib.pyplot as plt

import matplotlib.animation as animation



from random import randint





changing_list = []

another_changing_list = []

values_list = [randint(0,i) for i in range(1,99)]

a = list(zip(changing_list, another_changing_list))


leng_start = len(changing_list)

lock = Lock()

evt = Event()

def loop_thread(values_list, changing_list, another_changing_list):
    
    global a

    t = 2
    while True:
        
        for value in values_list:
            
            if not evt.is_set():
             
                # print('is not set')
                
                pass
             
             
            if evt.is_set():
             
                print('is set')
                
                break
            
            lock.acquire()
            
            changing_list.append(values_list[randint(0,len(values_list)-1)])
                
            another_changing_list.append(values_list[randint(0,len(values_list)-1)])
                
                
            a = list(zip(changing_list, another_changing_list))
                
            lock.release()    
                
            time.sleep((t))
                
            # print(a)
            # sys.stdout.flush() 
            
            
            
        break
                
    print('exit thread')
    
                
def init_animate():
    pass

cnt = 0        
pippo = None      
def animate(j):
    
    global pippo 
    global cnt
    global leng_start
    global a
    global changing_list
    global another_changing_list
    
    if len(changing_list) != leng_start:
        
        leng_start = len(changing_list)
        
        if pippo:
            pippo.remove()
        
        # print('leng_start : after ', leng_start, ' chan :' ,len(changing_list))
        
        if (cnt % 2) == 0:
            col = 'red'
        else:
            col = 'blue'
        
        cnt += 1
    
        pippo = axe.scatter(changing_list,another_changing_list, color = col)
     
        # print(a[-1][0], a[-1][1],'len a ; ', len(a), ' j : ',j)
    

fig = plt.figure()  
axe = fig.add_subplot(111)


thread_1 = Thread(target=loop_thread, args=(values_list, changing_list, another_changing_list))

thread_1.start()




animat = animation.FuncAnimation(fig, animate, init_func=init_animate,
                              interval=1000, repeat = False)
    
plt.show()

    



evt.set()

print('plt.show() closed')

尝试 2 尝试在不使用 animation.FuncAnimation 的情况下制作动画,每个散点都在一个循环中,但很容易不同步,只是在点数达到 4 或 5 后才计数:

import gc

import time
from threading import Thread, Event, Lock

import matplotlib.pyplot as plt

from random import randint



# changing_list = [1,2,3]
# another_changing_list = [8,7,99]


gc.collect()

changing_list = []

another_changing_list = []



values_list = [randint(0,i) for i in range(1,99)]

a = list(zip(changing_list, another_changing_list))


lock = Lock()

lock2 = Lock()

evt = Event()

evt2 = Event()


pippo = None

def plotting_thread(fig, axe):
    
    global a
    global pippo
    global changing_list
    global another_changing_list
    

    
    leng_start = len(changing_list)
    
    # print('leng_start :', leng_start)
    

    cnt = 0
    while True: 
        
        lock.acquire()
        time.sleep(0.5)
        
        if not evt.is_set():
            
            # print('is not set')

            # print('leng_start before if : ', leng_start)
            
            if len(changing_list) != leng_start:
                
                leng_start = len(changing_list)
                
                # print('leng_start : after ', leng_start, ' chan :' ,len(changing_list))
                
                if (cnt % 2) == 0:
                    col = 'red'
                else:
                    col = 'blue'
                    
                cnt += 1
                
                # print(col)
                

                
                axe.clear()
                
                for i in range(len(changing_list)-1):
                    
                    time.sleep(1)
                    
                    axe.scatter( changing_list[i], another_changing_list[i], color=col)
                
                    fig.canvas.draw_idle() 
                
                    # plt.draw()   ### works too ?

                 
        if evt.is_set():
                 
            print('is set plotting')
                    
            break

        
        
        lock.release()
     
    




def loop_thread(values_list):
    
    global a
    global changing_list
    global another_changing_list

    while True:
        t = 2
        time.sleep((t))
        lock2.acquire()
        
            
        if not evt2.is_set():
             
                # print('is not set')
                
                changing_list.append(values_list[randint(0,len(values_list)-1)])
                    
                another_changing_list.append(values_list[randint(0,len(values_list)-1)])
                
                a = list(zip(changing_list, another_changing_list))
             
             
        if evt2.is_set():
             
                print('is set loop_thread')
                
                break
            
                
            
                
        # print(a)
        # print(changing_list)
        # print(another_changing_list)
        lock2.release()
  
                
    print('exit thread')
    
                


fig = plt.figure()  # the figure will be reused later
axe = fig.add_subplot(111)

thread_1 = Thread(target=loop_thread, args=((values_list,)))

thread_2 = Thread(target=plotting_thread, args=(fig, axe))

thread_1.start()

thread_2.start()





plt.show()

evt.set()

evt2.set()

print('plt.show() closed')


已编辑:上面的代码可以正常使用:

t = 2
    while True:
        t +=1
        time.sleep((t))
        lock2.acquire()

loop_thread 中这样每次迭代动画有更多的时间来完成

在某处读到animation.FuncAnimation 必须在主线程中。无法使用 animation.FuncAnimation 将其置于 while 循环中以将每个系列从“add+1 element to serie”循环中动画化。

【讨论】:

以上是关于如何使用 python matplotlib 与另一个代码并行运行动画?的主要内容,如果未能解决你的问题,请参考以下文章

Python中使用matplotlib 如何绘制折线图?

如何在ubuntu上使用pip为python3升级matplotlib?

如何使用 python/matplotlib 为 3d 绘图设置“相机位置”?

将视频帧与另一个图像python进行比较? [关闭]

如何更改 matplotlib(python)中的字体?

请教如何自定义python的matplotlib中的X轴刻度的问题