How to move figure window interactively in matplotlib?

I am trying to monitor real-time data using matplotlib.

I found that I can dynamically update the plot using interactive mode in Pyplot.

And it worked well, but one problem is that I cannot manipulate the graphics window at all. For example, move or resize the picture window.

Here is my code.

Is this a minus of the interactive mode? or am I using it wrong?

import matplotlib.pyplot as plt
import time
import math

# generate data
x = [0.1*_a for _a in range(1000)]
y = map(lambda x : math.sin(x), x)

# interactive mode
plt.ion() # identical plt.interactive(True)

fig, ax = plt.subplots()
# ax = plt.gca()
lines,  = ax.plot([], [])

# ax.set_ylim(-1, 1)
ax.grid()

MAX_N_DATA = 100
x_data = []
y_data = []
for i in range(len(x)):
    # New data received
    x_data.append(x[i])
    y_data.append(y[i])

    # limit data length
    if x_data.__len__() > MAX_N_DATA:
        x_data.pop(0)
        y_data.pop(0)

    # Set Data
    lines.set_xdata(x_data)
    lines.set_ydata(y_data)

    # The data limits are not updated automatically.
    ax.relim()
    # with tight True, graph flows smoothly.
    ax.autoscale_view(tight=True, scalex=True, scaley=True)

    # draw
    plt.draw()
    time.sleep(0.01)

      

Thank.

+3


source to share


2 answers


As shown in this answer to another question , replace plt.draw()

with plt.pause(0.05)

. This solved the problem for me.



+1


source


While I still think you should be using bokeh, I will show you how to do it using matplotlib.

The problem as to why it doesn't work is that the matplotlib loop is inactive and therefore cannot digest window events (like close or resize). Unfortunately, it is impossible to induce such digestion from the outside. What you need to do is use the matplotlib animation system.
Your code is actually pretty well prepared for this, so you can use FuncAnimation .



import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import math

# generate data
x = [0.1*_a for _a in range(1000)]
y = map(lambda x : math.sin(x), x)

# don't need ion, we're using block=True (see end of code)

fig, ax = plt.subplots()
fig.show()
# ax = plt.gca()
lines,  = ax.plot([], [])

# ax.set_ylim(-1, 1)
ax.grid()

MAX_N_DATA = 100
x_data = []
y_data = []

def showdata(i):

    # New data received
    x_data.append(x[i])
    y_data.append(y[i])

    # limit data length
    if x_data.__len__() > MAX_N_DATA:
        x_data.pop(0)
        y_data.pop(0)

    # Set Data
    lines.set_xdata(x_data)
    lines.set_ydata(y_data)

    # The data limits are not updated automatically.
    ax.relim()
    # with tight True, graph flows smoothly.
    ax.autoscale_view(tight=True, scalex=True, scaley=True)

    # draw will be called by the animation system

# instead of time.sleep(0.01) we use an update interval of 10ms
# which has the same effect
anim = FuncAnimation(fig, showdata, range(len(x)), interval=10, repeat=False)

# start eventloop
plt.show(block=True)

      

0


source







All Articles