0

I'm trying to call a function like in the example below, and plot while running the code. The real values that I get as y-data are not really random numbers, but the point is that I would like it to get updated real-time. The plot in my example code below is just empty though and isn't getting updated.

import numpy as np
import matplotlib.pyplot as plt
import random as rnd
import time

initial_time = time.time()

def multiple_runs(number_of_runs):
    x_data, y_data = [], []
    fig, ax = plt.subplots()
    sc = ax.scatter(x_data, y_data)
    plt.draw()

    for i in range(0, number_of_runs):
        x_data.append(i+1)
        y_data.append(rnd.randint(0,100))
        sc.set_offsets(np.c_[x_data, y_data])
        fig.canvas.draw_idle()
        plt.pause(0.1)

        print ('Total time after run number ' + str(i+1) + ': ' + str(time.time() - initial_time))

multiple_runs(100)

UPDATE: Thanks @ImportanceOfBeingErnest , I got the code to work. However my problem right now is that the figure closes down as soon as it's finished, is there anyway to keep it open? I tried using plt.waitforbuttonpress() but I get a strange error from QTimer, not sure how or why. This is my working example code;

import numpy as np
import matplotlib.pyplot as plt
import random as rnd
import time

initial_time = time.time()

def multiple_runs(number_of_runs):
    x_data, y_data = [], []
    x_data2, y_data2 = [], []
    fig, ax = plt.subplots(2, sharex = True)
    sc = ax[0].scatter(x_data, y_data)
    sc2 = ax[1].scatter(x_data2, y_data2)
    ax[0].set(xlim=(0,100), ylim=(0,100))
    ax[1].set(xlim=(0,100), ylim=(0,100))
    plt.draw()

    for i in range(0, number_of_runs):
        x_data.append(i+1)
        y_data.append(rnd.randint(0,100))
        x_data2.append(i+1)
        y_data2.append(rnd.randint(0,100))
        sc.set_offsets(np.c_[x_data, y_data])
        sc2.set_offsets(np.c_[x_data2, y_data2])
        fig.canvas.draw_idle()
        plt.pause(0.1)

        print ('Total time after run number ' + str(i+1) + ': ' + str(time.time() - initial_time))

multiple_runs(100)

UPDATE2: I tried using FuncAnimation, but getting the error TypeError: update() missing 2 required positional arguments: 'y' and 'y2'. I still need to use the for-loop because in my real code I'm using the previous values of y, to calculate the next values of y. This is my example code which is giving me the error;

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import random as rnd
import time

initial_time = time.time()

def multiple_runs(number_of_runs):
    x_data, y_data = [], []
    x_data2, y_data2 = [], []
    fig, ax = plt.subplots(2, sharex = True)
    sc = ax[0].scatter(x_data, y_data)
    sc2 = ax[1].scatter(x_data2, y_data2)
    ax[0].set(xlim=(0,100), ylim=(0,100))
    ax[1].set(xlim=(0,100), ylim=(0,100))

    def update(i, y, y2):
        x_data.append(i+1)
        y_data.append(y)
        x_data2.append(i+1)
        y_data2.append(y2)
        sc.set_offsets(np.c_[x_data, y_data])
        sc2.set_offsets(np.c_[x_data2, y_data2])
        print ('Total time after run number ' + str(i+1) + ': ' + str(time.time() - initial_time))


    for i in range(0, number_of_runs):
        y = rnd.randint(0,100)
        y2 = rnd.randint(0,100)
        update(i,y,y2)

    ani = FuncAnimation(fig, update, frames=number_of_runs, interval=100, repeat=False)
    plt.show()

multiple_runs(100)
4
  • 1
    I suspect that you forgot to update the limits, i.e. all the points are much larger than 1, yet the axes limits go from 0 to 1, hence the points are shown outside of the visible range. Something like ax.set(xlim=(0,100), ylim=(0,100)) will sure show them. Commented Jan 29, 2019 at 23:21
  • Thanks, that solved it. If you put it as answer I will accept it with the green thing. If you have any solution for this, I just noticed that I can't use plt.waitforbuttonpress() to make the plot stay open after code is run, I get a strange error saying QTimer::singleShot: Timers cannot have negative timeouts python error. If you have any solution for this I would be very greatful, but not needed since the real problem is dealt with, I'll go with what I've got for now :) Commented Jan 29, 2019 at 23:48
  • I never used waitforbuttonpress. What is the purpose of this? Is it to show an animation? Did you consider using FuncAnimation? Commented Jan 29, 2019 at 23:55
  • I tried using FuncAnimation, but couldn't get it to work. I have updated my question. Commented Jan 30, 2019 at 0:01

1 Answer 1

1

As commented, I would recommend to use FuncAnimation. This would look as follows in your case. Note that in order to close the window, one would need to press q or close it with the mouse.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import random as rnd
import time

initial_time = time.time()

def multiple_runs(number_of_runs):
    x_data, y_data = [], []
    x_data2, y_data2 = [], []
    fig, ax = plt.subplots(2, sharex = True)
    sc = ax[0].scatter(x_data, y_data)
    sc2 = ax[1].scatter(x_data2, y_data2)
    ax[0].set(xlim=(0,100), ylim=(0,100))
    ax[1].set(xlim=(0,100), ylim=(0,100))

    def get_ydata(i):
        y = rnd.randint(0,100)
        y2 = rnd.randint(0,100)
        return y, y2

    def update(i):
        y, y2 = get_ydata(i)
        x_data.append(i+1)
        y_data.append(y)
        x_data2.append(i+1)
        y_data2.append(y2)
        sc.set_offsets(np.c_[x_data, y_data])
        sc2.set_offsets(np.c_[x_data2, y_data2])

    ani = FuncAnimation(fig, update, frames=number_of_runs, interval=100, repeat=False)
    plt.show()

multiple_runs(100)
Sign up to request clarification or add additional context in comments.

2 Comments

Huge thanks for helping out, but this didn't work in my case. See update2 in my question.
I updated the code. You shouldn't try to use any loop, because FuncAnimation is the loop.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.