Reputation: 2012
I'm making an interface, where I have have some "clear this" and "clear that" buttons to remove various elements of a plot.
The problem with matplotlib is that I have to know the exact order the objects were plotted in to remove the correct one with ax.lines.pop()
. For example, a plot could contain raw data, then a smoothed version, and then a fit on top, but depending on the order these were called, ax.lines.pop(2)
would remove either the blue or the red line.
But how can I consistently remove e.g. the red line in a multi-layered scenario?
import matplotlib.pyplot as plt
import numpy as np
from scipy.signal import medfilt
a = np.random.normal(0, 1, 100)
b = medfilt(a, 17)
fig1, axes = plt.subplots(ncols = 2)
ax1, ax2 = axes
ax1.set_title("Figure 1")
ax1.plot(a, color = "darkgrey") # 0
ax1.plot(b, color = "firebrick") # 1
ax1.axhline(0.5, color = "blue") # 2
ax1.lines.pop(2)
ax2.set_title("Figure 2")
ax2.plot(a, color = "darkgrey") # 0
ax2.axhline(0.5, color = "blue") # 2
ax2.plot(b, color = "firebrick") # 1
ax2.lines.pop(2)
plt.show()
Upvotes: 0
Views: 1199
Reputation: 2515
For clarity and simplicity of exposition, the following example draws a single graph, and rather than delete the line, it toggles its visibility. Notice that two of the lines are labelled explicitly, the third has a label assigned to it by default. We use those labels to index our way to the line.
If you really want to delete the line, just replace the call to set_visible() with your call to pop(), c.f. ax.lines.pop(n).
import matplotlib.pyplot as plt
from matplotlib.widgets import CheckButtons
import numpy as np
from scipy.signal import medfilt
a = np.random.normal(0, 1, 100)
b = medfilt(a, 17)
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
# Create a graph with two curves, and save the lines
ax.set_title("Figure 1")
ax.plot(a, label='a', color = "darkgrey") # 0
ax.plot(b, label='b', color = "firebrick") # 1
ax.axhline(0.5, color = "blue") # 2
# Show the labels
plt.legend()
# Labels and initial states for buttons
labels = []
states = []
for l in ax.lines:
labels.append( l.get_label() )
states.append( l.get_visible() )
# Add a box with checkbuttons
plt.subplots_adjust(right=0.8)
bx = plt.axes( [0.85,0.4,0.1,0.15] )
cb = CheckButtons( bx, labels, states )
# Function to toggle visibility of each line
def toggle( label ):
n = labels.index(label)
ax.lines[ n ].set_visible( not ax.lines[ n ].get_visible() )
plt.draw()
# Connect the function to the buttons
cb.on_clicked( toggle )
# And start the show
plt.show()
Upvotes: 1