0

i try to make a dynamical plot in a method of a class. here is more or less the method

def plot():
    axes = plt.gca(bock=False)
    ydata = []
    xdata = []

    axes.set_xlim(0, 200)
    axes.set_ylim(-1,1)
    line, = axes.plot(ydata, 'r-')

    i=0

    while True:

        xdata.append(i/10)
        ydata.append(np.sin(i/10))
        line.set_ydata(ydata)
        line.set_xdata(xdata)
        plt.draw()
        plt.pause(1e-17)
        i+=1
        plt.show()

The problem is the fact that it's an infinity loop and during this loop function, i can do nothing. i can't use my Ipython console. I would like make run this method without block the console. i arrived to do something like that using just print and threading but matplotlib dont support threading. I tried using multiprocessing but that still block the console. any options?

antoine
  • 3
  • 5

1 Answers1

0

So there were many problems with this code. First: that bock argument you passed to plt.gca() threw errors. Second: plt.show() stops execution so the animation will not start. To go around this problem you must trigger the animation after plt.show() was called. One way to do it is making use of events. You can read more about them here: https://matplotlib.org/3.2.1/users/event_handling.html Lastly, you can use a conditional and break to make sure the loop is not infinite. Here is an example:

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
def plot(lim=100):
    """
    Parameters
    ----------
    lim -> int: Iteration where you want to stop
    """
    axes = plt.gca()#bock=False Was removed because it threw errors
    fig = plt.gcf()
    canvas = fig.canvas
    ydata = []
    xdata = []

    axes.set_xlim(0, 200)
    axes.set_ylim(-1,1)
    line, = axes.plot(xdata, ydata,'r-')

    #Now, we can't just start the loop because plt.show() will
    #Stop execcution. Instead we can make a trigger that starts
    #the loop. I will use a mouse event.
    def start_loop():
        i=0
        while True:
            xdata.append(i/10)
            ydata.append(np.sin(i/10))
            line.set_ydata(ydata)
            line.set_xdata(xdata)
            canvas.draw()
            canvas.flush_events()#This makes the updating less laggy
            plt.pause(1e-17)#Removable
            i+=1
            if i==lim:
                break
    canvas.mpl_connect("button_press_event",
                       lambda click: start_loop())
    #Click the plot to start the animation
    plt.show()
plot()

Furthermore, if you want faster execution, make use of blit or animation functions from matplotlib like FuncAnimation.

p479h
  • 169
  • 1
  • 8
  • What i try to do is to execute it without disturbing console. When you run a code, you can't write anything in the console until your code finish to run. What i want to do is to lauch this function but without block the console like that the code can do dynamical plot and in the same time i could write and execute something in the console. – antoine Jun 18 '20 at 22:21
  • Then you simply use python from the terminal or idle. Then before making the plot, use `plt.ion()`. This will make the graph change in real time as you write code. – p479h Jun 18 '20 at 22:25
  • but that still block the console. during the plot i can write nothing in the console. – antoine Jun 18 '20 at 22:38
  • According to https://stackoverflow.com/questions/33696861/how-to-manipulate-figures-while-a-script-is-running-in-python using `FuncAnimation` is the solution for you. – p479h Jun 19 '20 at 06:31