I am trying to implement a plot with interactive sliders in Matplotlib. I used the suggestions from Interactive matplotlib plot with two sliders to implement the sliders. Now I am trying to move an annotation of a point when the sliders change. There appears to be some strange behaviour that I can not figure out.
Below is a working example code. The code produces a point in the 3rd subplot and when the slider is changed the point moves. There is an annotation on the point that gets moved with the point. However in the current example old annotations are not removed, which is unwanted.
I tried some things to fix this. E.g. I would have expected the commented code marked with '!!' to do the job: remove the old annotation and then a new one is added afterwards. However if that is uncommented, nothing happens to the annotation at all when the slider is changed.
I have read Remove annotation while keeping plot matplotlib, Python and Remove annotation from figure and Remove and Re-Add Object in matplotlib | Toggle Object appearance matplotlib. I tried to implement the suggestions from there, i.e. to change the coordinates of the annotation or to add the annotation as an artist object. Non of the two did anything.
Is there something fundamental I'm getting wrong here? I feel like I don't understand how the object variables for annotations are handled in python.
One more comment: I would prefer to not change the structure of the code too much (especially the sympy use). I removed a lot of things to create this minimal example to reproduce the error, but I need the structure for my other plots.
import numpy as np
import sympy as sp
import matplotlib.pyplot as plt
import matplotlib
from matplotlib.widgets import Slider, Button, RadioButtons
## Define variable symbols ##
var1 = sp.Symbol('var1')
## Define initial value ##
var1_init = 5
## Marker position functions ##
def positionY(var1):
return var1
def positionX(var1):
return var1
## plot ##
axis_color = 'lightgoldenrodyellow'
fig = plt.figure()
ax = fig.add_subplot(131)
ax2 = fig.add_subplot(132)
ax3 = fig.add_subplot(133)
# Adjust the subplots region to leave some space for the slider
fig.subplots_adjust(left=0.25, bottom=0.3)
# Draw the initial plot
marker_coord = (positionX(var1_init),positionY(var1_init))
[qMarker1] = ax3.plot(marker_coord[0],marker_coord[1],'ro')
ax3.set_xlim([-1.0, 11.0])
ax3.set_ylim([-1.0, 11.0])
qAnnotation = ax3.annotate('(%.2f, %.2f)' % marker_coord, xy=marker_coord, textcoords='data')
## Add sliders ##
# Define an axes area and draw sliders in it
var1_slider_ax = fig.add_axes([0.25, 0.2, 0.65, 0.03], facecolor=axis_color)
var1_slider = Slider(var1_slider_ax, 'var1', 0, 10.0, valinit=var1_init)
# Define an action for modifying the plot1 when any slider's value changes
def sliders_on_changed(val):
qMarker1.set_ydata(positionY(var1_slider.val))
qMarker1.set_xdata(positionX(var1_slider.val))
#qAnnotation.remove() ## <--------------------------- !!
marker_coord = (positionX(var1_slider.val),positionY(var1_slider.val))
qAnnotation = ax3.annotate('(%.2f, %.2f)' % marker_coord, xy=marker_coord, textcoords='data')
fig.canvas.draw_idle()
var1_slider.on_changed(sliders_on_changed)
# Add a button for resetting the parameters
reset_button_ax = fig.add_axes([0.05, 0.1, 0.1, 0.04])
reset_button = Button(reset_button_ax, 'Reset', color=axis_color, hovercolor='0.975')
def reset_button_on_clicked(mouse_event):
var1_slider.reset()
reset_button.on_clicked(reset_button_on_clicked)
plt.show()