Updating Realtime subplots

Hi,

This is my first post here. I just noticed that all indentation has been removed when I inserted my code. Sorry about that. I will try to fix that in a future post.

I use the following code to update 2 sets of data to one chart:

import matplotlib.pyplot as plt
import random
import time
fig = plt.gcf()
fig.set_size_inches(12, 6)  # width and height in inches
fig.show()
i=1
x, y1, y2 = [], [],[]
x_scale = 30
plt.ylabel('random')
plt.xlabel('Sample')
plt.ylim(top = 100, bottom = 0)
while True:
    if len(x) > x_scale:
        x.pop(0)
        y1.pop(0)
        y2.pop(0)
    x.append(i)
    y1.append(round(100*random.random()))
    y2.append(round(10*random.random()))
    plt.plot(x,y1, color = 'b')
    plt.plot(x,y2, color = 'r')
    plt.xlim(left=i-x_scale, right=i)
    fig.canvas.draw()
    if plt.waitforbuttonpress(0.1): break # this will wait 0.1 seconds for your keypress
    i += 1

I need to be able to separate the data into 2 separate subplots but the following is not working for me:

import matplotlib.pyplot as plt
import random

x, y1, y2 =[],[],[]
x_scale=30
i=0

fig, (ax1, ax2) = plt.subplots(2,sharex=True)
ax1.set_title("top chart")
ax2.set_title("bottom chart")
    
plt.show()


while i<40:
    if len(x) > x_scale:
        x.pop(0)
        y1.pop(0)
        y2.pop(0)
    x.append(i)
    plt.xlim(left=i-x_scale, right=i)

    y1.append(round(100*random.random()))
    y2.append(round(10*random.random()))
    ax1.plot(x,y1)
    ax2.plot(x,y2)

    plt.draw()
    i+=2

Any suggestions please?

Hi @xuraax what do you mean by “not working”? Can you please describe both what is happening and how that’s different from what you want to happen?

This is my first post here. I just noticed that all indentation has
been removed when I inserted my code. Sorry about that. I will try to
fix that in a future post.

Put code between triple backtick characters like this:

```
your code
goes here
```

I use the following code to update 2 sets of data to one chart:
[…]

First you plot the graph while it is empty. Maybe that’s intentional.

In the loop you only call plt.draw(), not plt.show().

I seem to recall that plt.show() scrubs the current plot. You might
need to make it from scratch in each loop iteration.

I stuck some print() calls in various places, and a plt.show() below
the plt.draw().

Cheers,
Cameron Simpson cs@cskk.id.au

···

On 17Jul2022 09:51, xuraax via Matplotlib nobody@discourse.matplotlib.org wrote:

When you run the second piece of code you get 2 empty subplots on the screen with no data. Then you need to close this window to move ahead after which you get a SINGLE plot with no data. Then you need to repeatedly close this page each time with the same result until the while loop goes through all its iterations to exit.

Anyway, thanks to a suggestion. the following changes solved these issues:

import matplotlib.pyplot as plt
import random

x, y1, y2 =[],[],[]
x_scale=30
i=0

fig, (ax1, ax2) = plt.subplots(2,sharex=True)
fig.set_size_inches(15, 8)  # width and height in inches
ax1.set_title("top chart")
ax2.set_title("bottom chart")
ax2.set_xlabel("TIME")
ax1.set_ylabel("RND_1")
ax2.set_ylabel("RND_2")
    

while True:

    if len(x) > x_scale:
        x.pop(0)
        y1.pop(0)
        y2.pop(0)
    x.append(i)
    ax1.set_xlim(i-x_scale, i)
    ax2.set_xlim(i-x_scale, i)
    ax1.set_ylim(0, 150)
    ax2.set_ylim(0, 20)

    y1.append(round(100*random.random()))
    y2.append(round(10*random.random()))
    ax1.plot(x,y1, color = 'b')
    ax2.plot(x,y2, color = 'r')

    plt.draw()
#    plt.pause(0.01)
    if plt.waitforbuttonpress(0.01): break # this will wait 0.1 seconds for your keypress

    i+=1

The important change is to include a pause after the plt.draw() command. I still don’t understand why but it works.

cheers

plt.draw()

plt.pause(0.01)

if plt.waitforbuttonpress(0.01): break # this will wait 0.1 seconds for your keypress
[…]
The important change is to include a pause after the plt.draw()
command. I still don’t understand why but it works.

Possibly because showing a plot requires running a GUI. What follows is
speculation; I haven’t looked at matplotlib’s GUI innards.

Most GUIs have an event loop which runs in your main program, so a
typical application looks like:

  • create a bunch of widgets
  • add callbacks (functions to run when things (events) happen)
  • start a main loop

The main loop:

  • performs pending actions, which might involve rendering the widgets
    (drawing on the display itself)
  • processes queued events, and running any associated callbacks

So it is plauible to me that plt.draw() updates the graph contents,
but that nothing visible happens until the GUI main loop runs. And that
may not happen until some user interaction is requested. A pause()
probably implies a short run of the main loop, as in a regular GUI it
tends to mean “make the display up to date (by running the main loop
until all pending events have been dealt with) and then pause
briefly”.

I’m basicly suggesting that .draw() may just updtae the graph, but
not update the GUI (because it can be more efficient to do a bunch of
updates to the graph image, but then update the display of the image
just once when all those are done).

So nothing changes on the screen until you call something which activaes
the GUI side of things. draw() is not such a thing but pause() is.

Cheers,
Cameron Simpson cs@cskk.id.au

···

On 19Jul2022 04:38, xuraax via Matplotlib nobody@discourse.matplotlib.org wrote: