I am trying to create a function that will accept a figure handle from a closed matplotlib figure and use that handle to reshow the figure. The below code will do this however the navigation toolbar is still linked to the old (destroyed) figure so plot interactivity is lost. Is there a way of linking the navigation toolbar to the new window so the plot is interactive?
For reference, I have consulted similar questions:
Matplotlib: how to show a figure that has been closed
Re-opening closed figure matplotlib
Matplotlib: re-open a closed figure?
The solution (if it exists) should not require use of a bespoke backend. I am hoping this is possible with whatever backend is default (which changes with different OS). I'm also looking to do this without relying on iPython.
My partially complete solution (which lacks navigation bar interactivity in the reshown figure) is:
import matplotlib.pyplot as plt
def reshow_figure(handle):
figsize = handle.get_size_inches() # get the size of the old figure
fig_new = plt.figure() # make a new figure
new_manager = fig_new.canvas.manager # get the figure manager from the new figure
new_manager.canvas.figure = handle # assign the old figure to the new figure manager
handle.set_canvas(new_manager.canvas) # assign the new canvas to the old figure
handle.set_size_inches(figsize) # restore the figsize
plt.show() # show the resurrected figure
plt.plot([1,2,3,4,5],[1,5,3,4,2])
fig = plt.gcf() # get the figure handle to resurrect the figure later
plt.title('My Figure') # just to check the title copies across
plt.gcf().set_size_inches((10,5)) # set a custom size to test recovery of the figsize
plt.show()
# manually close the figure window
reshow_figure(fig)
Related
I have two issues with my python plot that would be grateful if anyone could help me with:
1- I wonder if it is possible in python to have the option for the plots after display to add horizontal or vertical lines, so that these new lines could be added, moved or deleted without the need to run the code again.
to say it more clearly, I am looking for additional features that adding them does not need to change the code and they only enable me to manually draw on the already plotted image.
2- I want to plot a very large image in the real size, So that I need to add the horizontal and vertical slide bars to be able to scroll up/down or left/right in the plot?
I need to combine these two ability for my project, can someone help me with that?
1- You can't physically draw on it, but you can make a plot in matplotlib interactive as follows:
import matplotlib.pyplot as plt
plt.ion() # turns on interactive mode
fig = plt.figure()
ax = fig.add_subplot()
plt.ylim(-10, 10)
plt.xlim(0, 10)
while True:
plt.axhline(float(input("number")))
fig.canvas.draw()
fig.canvas.flush_events() # draws
This program allows you to create horizontal lines based on user input.
I think you can solve 2 with tkinter, but that would be pretty difficult. There might also an easier way. See this stack overflow question for an example of an interactive plot in tkinter. I believe this plot can be made bigger and scrollable, but I am not sure.
I am facing couple of issues. First, I wanted all the plots in a separate window. For this, I successfully changed the settings and I got the separate window. The problem is, I got all the plots in same figures, which is bad. Second issue is, how do I inscribe window pan to the Ipconsole? I donot want a separate window. I want this window inside the console?
For the first issue, you can have your plots in different figures by using figure this way:
import matplotlib.pyplot as plt
plt.figure()
# Plot your first graph(s)
plt.figure()
# Plot your other graph(s)
plt.show()
Each time you call figure, a new window is created. For more information on figure, you can check the doc
I have begun using matplotlib and I am somewhat confused as to why figures exist. Sometimes I see code where a figure is declared and then a plot is made, and sometimes I see things like this:
import numpy as np
import matplotlib.pyplot as plt
data = np.loadtxt('initial.dat','float')
plt.plot(data[:,0], data[:,1])
plt.xlabel("x (Angstroms)")
plt.ylabel("V (eV)")
plt.savefig('v.png',bbox_inches='tight')
plt.clf()
I read the documentation on figure and plot, but I don't get it. Why do figures exist?
A figure will always exist once you create some plot with matplotlib.
The introductory matplotlib page may help here:
The whole figure. The figure keeps track of all the child Axes, a smattering of ‘special’ artists (titles, figure legends, etc), and the canvas. (Don’t worry too much about the canvas, it is crucial as it is the object that actually does the drawing to get you your plot, but as the user it is more-or-less invisible to you). A figure can have any number of Axes, but to be useful should have at least one.
You can imagine the figure to be the white sheet of paper you draw a plot on. A figure has some size, maybe a background and most importantly it is the container for everything you draw into it. In most cases this will be one or more axes. If there wasn't any figure, there wouldn't be any sheet of paper to draw your plot to (you cannot draw a line in the air).
Even if you haven't explicitely created the figure, it is automatically created in the background.
import matplotlib.pyplot as plt
plt.plot([1,2,3])
# at this point we already have a figure, because the plot needs to live somewhere
# we can get a handle to the figure via
figure = plt.gcf()
Examples of when you explicitely need a figure:
If you want to create a second figure.
plt.plot([1,2,3])
plt.figure(2)
plt.plot([2,4,6])
If you want to set the figure size or other figure parameters.
plt.figure(figsize=(5,4), dpi=72)
If you want to change the padding of the subplot(s).
fig, ax=plt.subplots()
fig.subplots_adjust(bottom=0.2)
This question already has answers here:
warning about too many open figures
(7 answers)
Closed 5 years ago.
I am using Matplotlib and MPLD3 to create graphs that can be displayed in html plages (using django). Currently my graphs are being generated dynamically from data being pulled from csv files. Every so often I get this message in my Terminal:
RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (matplotlib.pyplot.figure) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam figure.max_num_figures).
max_open_warning, RuntimeWarning)
I am not really sure what it means, but I am assuming it means I should have some way of closing graphs that are not in use. Is there anyway to do this or am I completely off base? Thanks.
I preferred the answer of tacaswell in the comments, but had to search for it.
Clean up your plots after you are done with them:
plt.close(fig)
or
plt.close('all')
Figures will automatically be closed (by garbage collection) if you don't create them through the pyplot interface. For example you can create figures using:
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
def new_fig():
"""Create a new matplotlib figure containing one axis"""
fig = Figure()
FigureCanvas(fig)
ax = fig.add_subplot(111)
return fig, ax
(Based on this answer)
So I'm trying to understand how a figure is structured. My understanding is the following:
you have a canvas (if you've got a gui or something similar), a figure, and axes
you add the axes to the figure, and the figure to the canvas.
The plot is held by the axes, so for example:
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([1, 2], [1, 4])
fig.show()
I would expect would create a figure however I just get a blank window... Also, it seems canvas is not needed at all?
any help appreciated thank you!
here it says the above code should work... or has a similar example
https://github.com/thehackerwithin/PyTrieste/wiki/Python7-MatPlotLib
You shouldn't be poking at the canvas unless you really know what you are doing (and are embedding mpl into another program). pyplot has a bunch of nice tools that takes care of most of the set up for you.
There is a separation between the user layer (figures, axes, artists, and such) and the rendering layer (canvas, renderer, and such). The first layer is user facing and should be machine independent. The second layer is machine specific, but should expose none of that to
the user.
There are a varity of 'backends' that take care of the translation between the two layers (by providing sub-classes of canvas and such). There are interactive backends (QtAgg, GtkAgg, TkAgg,...) which include all the hooks into a gui toolkit to provide nice windows and non-interactive backend (PS, pdf, ...) that only save files.
figures hold axes which hold artists (and axis). Those classes will talk to the rendering layer, but you (for the most part) do not need to worry about exactly how.