1

The next code is to animate with matplotlib.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()

What I want to know is how to run that animation simultaneously with a loop like this:

for value in values_list:
    changing_list.append(value)

Such that the result is an animation that shows, immediately, the new values in the changing_list list.

I'd appreciate any help!

Rami Ma
  • 966
  • 1
  • 7
  • 13
  • 1
    too difficuly to me, have a look at: https://stackoverflow.com/questions/18791722/can-you-plot-live-data-in-matplotlib – pippo1980 Dec 11 '21 at 13:18
  • just to clarify (I am newbie to this) simultaneusly means you want to run plotting and loop in two different threads and strem data from one to the other ? – pippo1980 Dec 11 '21 at 13:33
  • https://pypi.org/project/stream-engine/ StreamEngine is an extention of the matplotlib Animation class which enables the user to easily plot real time streaming data. – pippo1980 Dec 11 '21 at 13:38
  • FOUND https://matplotlib.org/3.1.0/gallery/misc/multiprocess_sgskip.html – pippo1980 Dec 11 '21 at 14:51

1 Answers1

0

not sure its what you era asking for, pretty sure is not the best way :

attempt 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')

attempt 2 tries to animate without using animation.FuncAnimation, each scatter in a loop , but goes easily out of synchro, just counts the dots after they get to 4 or 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')


EDITED: code above works fine using:

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

in loop_thread so that at each iteration animation as more time to complete

Read somewhere that animation.FuncAnimation has to be in main thread. Wasnt able to put it in a while loop to animate each series out of the 'add+1 element to serie' loop using animation.FuncAnimation.

pippo1980
  • 2,181
  • 3
  • 14
  • 30