3
votes

I read a lot of stack overflow questions regarding this topics but after a lot of experiment I can't figure out my problem.

I use PyCharm 2016.3.2 on Windows 7 (but I have the same issue on OSX), my interpreter is the last version of Anaconda with Python 3.6 and matplotlib 2.0.0.

Here is what I try to achieve (and maybe I am not using the right approach because I am trying to recreate the behavior I am use to in Octave/Matlab) :

  1. Plot one figure in a popup windows
  2. Pause my script (input("press a key to continue"))
  3. Observe the figure, then press a key to continue the script
  4. Compute something else
  5. Plot new data on the same figure
  6. Pause my script (input("press a key to continue"))
  7. Observe the figure, then press a key to continue the script

Here is my test code :

import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt

print('Plotting Data...')

plt.ion()
plt.figure(1)
plt.plot([1, 5, 10, 20], [1, 5, 10, 20])
plt.xlabel('x label')
plt.ylabel('y label')
plt.show()
plt.pause(0.0001)

input('Plotting Data done..., Press a key to continue')

plt.figure(1)
plt.plot([1, 5, 10, 20], [2, 10, 20, 40])
plt.show()
plt.pause(0.0001)

input('Program paused. Press enter to end.\n')

This is the closest version of what I want, the plots are correct but not responsive when I mouse over them (plt.pause(0.0001) generates a warning but code works).

I played a lot with parameters (plt.ion() ; plt.pause() ; plt.show(block=False)). Most of the time, this led to empty plot windows or I needed to close the window to continue the execution.

Thanks for your help !

1
You cannot work in two different event loops at once. Why can't you just plot everything the normal way and use the closure of the window as the trigger for continuation of the program? - ImportanceOfBeingErnest
The normal way ? If I use the closure of the windows as the trigger to continue, even when I recall figure(1), I can't find a way to plot a second element on top of the 1st one (without redo a plt.plot with the first dataset). But sometimes I just want to do multiple plots and let them all open until the end of the execution. Thanks! - Capy
@ImportanceOfBeingErnest This post is looking at the same issue Similar question and it basically uses the same workaround with a pause (figures are plotted correctly but unresponsive) - Capy
So does the accepted answer from the linked question work for you? In my case it does the same as here: the input blocks the window event loop, which thereby becomes unresponsive. - ImportanceOfBeingErnest
@ImportanceOfBeingErnest You are right, I have the behavior, plots are correct but in an unresponsive windows. I think trying to mimic what Matlab does is not the right approach. So I can either do it in non-interactive mode and wait for all the data before plotting everything in one figure (then close it) or save figures in files if I want to review all of them at the end of the execution. Thanks a lot for your help! - Capy

1 Answers

0
votes

Once plt.show() is called the main loop is taken over by the Window. Therefore, as soon as input get's called, the main loop becomes unresponsive.

You could try to stay in the GUI loop and handle the key press there.

import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt

print('Plotting Data...')

fig, ax = plt.subplots()
ax.set_xlabel('x label')
ax.set_ylabel('y label')
i=[0]

def f1():
    ax.plot([1, 5, 10, 20], [1, 5, 10, 20])

def f2():
    ax.plot([1, 5, 10, 20], [2, 10, 20, 40])

def f3():
    ax.plot([1, 5, 10, 20], [5, 9, 17, 28])


def update(event=None):
    if i[0]==0: f1()
    if i[0]==1: f2()
    if i[0]==2: f3()
    fig.canvas.draw_idle()
    i[0]+=1
    print('Step {} done..., Press a key to continue'.format(i[0]))

fig.canvas.mpl_connect("key_press_event", update)    

update()
plt.show()