Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait user input in Matplotlib Figure on specific keyboard press

I want a user input and then stop the loop with a specific keyboard press.

from __future__ import print_function
import sys
import numpy as np
import matplotlib.pyplot as plt


def press(event):
    print('press', event.key)
    sys.stdout.flush()
    if event.key == 'x':
       visible = xl.get_visible()
       xl.set_visible(not visible)
       fig.canvas.draw()
    if event.key == 'enter':
       cnt.append(1)

cnt=[]
List=[]
fig, ax = plt.subplots()

fig.canvas.mpl_connect('key_press_event', press)

ax.plot(np.random.rand(12), np.random.rand(12), 'go')
xl = ax.set_xlabel('easy come, easy go')
ax.set_title('Press a key')
plt.show()
plt.waitforbuttonpress() #non specific key press!!!

result=cnt[0]+cnt[1]

I want to stop the loop, wait for the user to press enter and then continue the code using the cnt after. But if I do not put plt.waitforbuttonpress(), the code runs and finishes, but if I put plt.waitforbuttonpress() any keyboard or mouse press will run and end the entire code.

like image 996
user5960525 Avatar asked Mar 06 '26 11:03

user5960525


1 Answers

The code is working as expected for me (matplotlib version 2.0.0 and TkAgg backend) You create a figure which should block at the plt.show command.

If not, try matplotlib.use("TkAgg") to change backend (see order here)

You then have a few options,

1) Include the code you want to run in the event handling loop, either after the event you have or maybe under a special key.

import numpy as np
import matplotlib.pyplot as plt

def press(event):
    print('press', event.key)
    if event.key == 'enter':
        cnt.append(1)
    if event.key == 'a':
        result = sum(cnt)
        print(result, cnt)

cnt=[]
fig, ax = plt.subplots()
fig.canvas.mpl_connect('key_press_event', press)
ax.plot(np.random.rand(12), np.random.rand(12), 'go')
plt.show()

when you press a you get assuming enter has been pressed 8 times when you press a. (8, [1, 1, 1, 1, 1, 1, 1])

2) Add an escape command to exit the figure (you may need to work out the best way to exit gracefully)

import numpy as np
import matplotlib.pyplot as plt

def press(event):
    print('press', event.key)
    if event.key == 'enter':
        cnt.append(1)
    if event.key == "escape":
        plt.close()

cnt=[]
fig, ax = plt.subplots()
fig.canvas.mpl_connect('key_press_event', press)
ax.plot(np.random.rand(12), np.random.rand(12), 'go')
plt.show()
result = sum(cnt)
print(result, cnt)

the command after plt.show() should then be run.

3) Set a timeout for the event loop and your code will be run after this time.

import numpy as np
import matplotlib.pyplot as plt

def press(event):
    print('press', event.key)
    if event.key == 'enter':
        cnt.append(1)

cnt=[]
fig, ax = plt.subplots()
fig.canvas.mpl_connect('key_press_event', press)
ax.plot(np.random.rand(12), np.random.rand(12), 'go')
plt.show(block=False)
plt.waitforbuttonpress()
plt.pause(5.)
result = sum(cnt)
print(result, cnt)

It looks like plt.waitforbuttonpress(time=5.) should do something similar but I could not get this to work.

like image 192
Ed Smith Avatar answered Mar 08 '26 01:03

Ed Smith