I have made a program that plots data from a network analyzer live. The plotting of the graph is inside a while
loop. The program does not stop plotting unless the program is closed. I want a program that closes the graphs (break
s the while
loop) when I press a button on my keyboard. I do not want to use input
because then the code would wait for the input. The code should run smoothly until the button is pressed. I am running the program in Thonny on a raspberry pi.
import matplotlib.pyplot as plt
plt.ion()
x_data= []
y_data= []
graph= plt.plot(x_data,y_data)
while True:
do something
graph.set_ydata(y_data)
graph.set_xdata(x_data)
plt.draw()
plt.pause(0.01)
Note this is not the code, just a small example; the problem does not lie in the plotting but in trying to break
the loop.
Considering that this code needs to run on a Raspberry...
Using the keyboard module may not be a good idea, since on Linux, the execution of your program may suddenly demand root access in order to interact with the device drivers and listen for keyboard events.
To make the command "sudo python my_script.py" works, further adjustment might be necessary.
Therefore, here is my simple solution that exploits threading and the std input() function, to avoid using the keyboard library and closing the python program.
As suggested by @jared, it is better to choose an arbitrary key to achieve the desired result, not whatever key.
import matplotlib.pyplot as plt
import threading
# Empty data for now
x_data = []
y_data = []
############## Plotting
# Enable the interactive mode for plotting
plt.ion()
# The comma after "graph" is fundamental to unpack the first element of the returned tuple
# and assigning it to the variable graph.
# (Without the comma, graph would be assigned to the entire tuple)
graph, = plt.plot(x_data, y_data)
def keyboard_input():
""" It is not necessary to specify the 'q' key,
since input() waits for the user to enter a value and press enter,
but if the value entered is "q", the function return and then the subsequent code is executed.
"""
input()
plt.close()
# Start the thread that execute the keyboard input method
thread = threading.Thread(target=keyboard_input)
thread.start()
# Display the plot. It is constantly updated in real-time as new data can be, someway, added to x_data and y_data
while True:
graph.set_ydata(y_data)
graph.set_xdata(x_data)
plt.draw()
plt.pause(0.01)
# Check if the plot window (with the specified figure number 1, the default value) has been closed,
# Otherwise, waits for the thread object to complete the join() method and exit
if not plt.fignum_exists(1):
thread.join()
break