let say I have this code:
num_rows = 10 num_cols = 1 fig, axs = plt.subplots(num_rows, num_cols, sharex=True) for i in xrange(num_rows): ax = axs[i] ax.plot(np.arange(10), np.arange(10)**i) plt.show()
the result figure has too much info and now I want to pick 1 of the axes and draw it alone in a new figure
I tried doing something like this
def on_click(event): axes = event.inaxes.get_axes() fig2 = plt.figure(15) fig2.axes.append(axes) fig2.show() fig.canvas.mpl_connect('button_press_event', on_click)
but it didn't quite work. what would be the correct way to do it? searching through the docs and throw SE gave hardly any useful result
edit:
I don't mind redrawing the chosen axes, but I'm not sure how can I tell which of the axes was chosen so if that information is available somehow then it is a valid solution for me
edit #2:
so I've managed to do something like this:
def on_click(event): fig2 = plt.figure(15) fig2.clf() for line in event.inaxes.axes.get_lines(): xydata = line.get_xydata() plt.plot(xydata[:, 0], xydata[:, 1]) fig2.show()
which seems to be "working" (all the other information is lost - labels, lines colors, lines style, lines width, xlim, ylim, etc...) but I feel like there must be a nicer way to do it
thanks
An axes object can only belong to one figure.
The clf() function in pyplot module of matplotlib library is used to clear the current figure.
To show an axes subplot in Python, we can use show() method. When multiple figures are created, then those images are displayed using show() method.
The tight_layout() function in pyplot module of matplotlib library is used to automatically adjust subplot parameters to give specified padding.
The inital answer here does not work, we keep it for future reference and also to see why a more sophisticated approach is needed.
#There are some pitfalls on the way with the initial approach. #Adding an `axes` to a figure can be done via `fig.add_axes(axes)`. However, at this point, #the axes' figure needs to be the figure the axes should be added to. #This may sound a bit like running in circles but we can actually set the axes' #figure as `axes.figure = fig2` and hence break out of this. #One might then also position the axes in the new figure to take the usual dimensions. #For this a dummy axes can be added first, the axes can change its position to the position #of the dummy axes and then the dummy axes is removed again. In total, this would look as follows. import matplotlib.pyplot as plt import numpy as np num_rows = 10 num_cols = 1 fig, axs = plt.subplots(num_rows, num_cols, sharex=True) for i in xrange(num_rows): ax = axs[i] ax.plot(np.arange(10), np.arange(10)**i) def on_click(event): axes = event.inaxes if not axes: return fig2 = plt.figure() axes.figure=fig2 fig2.axes.append(axes) fig2.add_axes(axes) dummy = fig2.add_subplot(111) axes.set_position(dummy.get_position()) dummy.remove() fig2.show() fig.canvas.mpl_connect('button_press_event', on_click) plt.show() #So far so good, however, be aware that now after a click the axes is somehow #residing in both figures, which can cause all sorts of problems, e.g. if you # want to resize or save the initial figure.
Instead, the following will work:
The problem is that axes cannot be copied (even deepcopy
will fail). Hence to obtain a true copy of an axes, you may need to use pickle. The following will work. It pickles the complete figure and removes all but the one axes to show.
import matplotlib.pyplot as plt import numpy as np import pickle import io num_rows = 10 num_cols = 1 fig, axs = plt.subplots(num_rows, num_cols, sharex=True) for i in range(num_rows): ax = axs[i] ax.plot(np.arange(10), np.arange(10)**i) def on_click(event): if not event.inaxes: return inx = list(fig.axes).index(event.inaxes) buf = io.BytesIO() pickle.dump(fig, buf) buf.seek(0) fig2 = pickle.load(buf) for i, ax in enumerate(fig2.axes): if i != inx: fig2.delaxes(ax) else: axes=ax axes.change_geometry(1,1,1) fig2.show() fig.canvas.mpl_connect('button_press_event', on_click) plt.show()
The alternative to the above is of course to recreate the plot in a new figure each time the axes is clicked. To this end one may use a function that creates a plot on a specified axes and with a specified index as input. Using this function during figure creation as well as later for replicating the plot in another figure ensures to have the same plot in all cases.
import matplotlib.pyplot as plt import numpy as np num_rows = 10 num_cols = 1 colors = plt.rcParams["axes.prop_cycle"].by_key()["color"] labels = ["Label {}".format(i+1) for i in range(num_rows)] def myplot(i, ax): ax.plot(np.arange(10), np.arange(10)**i, color=colors[i]) ax.set_ylabel(labels[i]) fig, axs = plt.subplots(num_rows, num_cols, sharex=True) for i in xrange(num_rows): myplot(i, axs[i]) def on_click(event): axes = event.inaxes if not axes: return inx = list(fig.axes).index(axes) fig2 = plt.figure() ax = fig2.add_subplot(111) myplot(inx, ax) fig2.show() fig.canvas.mpl_connect('button_press_event', on_click) plt.show()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With