komodovaran_
komodovaran_

Reputation: 2012

Specifying exactly which line to remove from matplotlib plot

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?

enter image description here

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

Answers (1)

DrM
DrM

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

Related Questions