In a project I am currently working on, I need to draw a figure using matplotlib and let the user interact with said figure to define some cutoff values at the start and end of a signal. These cutoff values are then supposed to be kept in memory for a later usage.
Having never done it before, I looked up the documentation and the examples proposed here as well as some answers found on StackOverflow (here). From them, I was able to more or less obtain a satisfactory result and let the user interact with the figure to select the cutoff values.
Now my question is: How do I exit the event loop when the figure is closed?
My environment uses Python 3.9.16 and Matplotlib 3.7.0. I am working on Windows 10.
Based on the previous links, I wrote the following example:
import matplotlib.pyplot as plt
import numpy as np
close_flag = 0
# Creating a random dataset
x = np.arange(0, np.pi * 2 * 5, 0.1)
y = np.sin(x)
# Shamelessly stolen from Matplotlib documentation
def tellme(s):
plt.title(s, fontsize=16)
plt.draw()
def close_event(event):
global close_flag
close_flag = 1
# Creating the figure
fig, axs = plt.subplots()
fig.canvas.mpl_connect('close_event', close_event)
plt.plot(x, y)
plt.grid()
while close_flag == 0:
pts = [] # Empty list to keep my cutoff values in memory
_vlines = []
# Updating the plot title
tellme('Select the first cutoff value with the mouse')
# First cutoff value
pt = plt.ginput(1, timeout=-1)[0][0] # We only need the value along the x axis
pts.append(pt)
# Ploting the first cutoff value as a vertical line
tmp = plt.vlines(pt, ymin=y.min(), ymax=y.max(), colors='k', linestyles='-.')
_vlines.append(tmp)
# Updating the plot title a second time
tellme('Select the second cutoff dates with the mouse')
# Second cutoff value
pt = plt.ginput(1, timeout=-1)[0][0]
pts.append(pt)
# Ploting the second cutoff value as a vertical line
tmp = plt.vlines(pt, ymin=y.min(), ymax=y.max(), colors='k', linestyles='-.')
_vlines.append(tmp)
# Updating the title a third time to inform the user both cutoff values are set
tellme('Happy? Key click for yes, mouse click for no')
# First control to let the user escape the loop
if plt.waitforbuttonpress():
break
# First control returned False, we remove the vertical lines and let the user select new values
for v in _vlines:
v.remove()
# Second control used to check if the Figure was closed, if so we should exit the loop
if close_flag == 1:
break
# Rest of the script where I am using the selected values
From the example, we can see that script is interacting with the user as expected: the values can be defined by clicking on the figure, it can be done until the user is happy about the result, and the script correctly exits the loop if a key is pressed once the values are defined. However, when I close the Figure, the script keeps on running as if stuck in endless loop.
Using the print() function, I could confirm the script enters the close_event() function but nothing else seems to happen and I have to abort the script using ctrl + C.
How should I proceed to exit the loop when the figure is closed and let the script continue running?
print('I am out of the loop'). It shouldn't be an issue. And yes the script works but I am not able to escape the loop when the figure is closed manually (i.e., by clicking on the close button on the upper right corner)ginputorwaitforbuttonpressso thebreakatclose_flagnever gets run. You can check this by addingprintstatements. You probably should wrap your user inputs in timeout loops that periodically check if the figure has been closedplt.ginput(). I still need some time to work out a proper solution but I am now able to close the figure and keep the script running. I'll edit my question once I am satisfied