I am using iPython notebook wo do some visualization. Figures are inline (the profile defaults to interactive, as this supports a number of users who prefer interactive more frequently):
%pylab inline
Using the inline plot, I often set the fig size manually:
figsize(10,5)
I find that I need to run cells twice to realize a change in the fig size. For example, if I define cell [1] as figsize(10,5) and run it, the output is the correct size. If I then run cell [2] with `fig size(5,10)1 I get output that is of size (10,5). A second run of cell [2] draws correctly.
Any insight into why this is occurring? Is it due to the inline backend and I just need to live with it?
Thanks.
Definition: figsize(sizex, sizey)
Docstring:
Set the default figure size to be [sizex, sizey].
This is just an easy to remember, convenience wrapper that sets::
matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
This seem correct to me, if you run the following, whatever value of X, Y I always get the right plot
figsize(10,5)
plot(range(10))
if you run it after your plot, then you set the default for next plot... but without exact example, hard to say..
Related
I would like to update a figure of matplotlib for every iteration in a loop. It works for about the first 30 iterations, but then the updates stop although there are more iterations.
Following you can find my code for the figure:
import numpy as np
import matplotlib.pyplot as plt
class SimpOutput:
fig = None
ax_l = None
ax_r = None
it_container = []
obj_container = []
def __init__(self):
self.fig, (self.ax_l, self.ax_r) = plt.subplots(nrows=1, ncols=2, figsize=(8, 4))
self.ax_l.set_title("Flexibility $c$")
self.ax_l.set_ylabel("obj. value $c$")
self.ax_l.set_xlabel("Iteration")
self.ax_r.set_title("Shape")
self.fig.show()
def update(self, iteration, obj, x):
self.it_container.append(iteration)
self.obj_container.append(obj)
self.ax_l.plot(self.it_container, self.obj_container, c="r")
x = x.reshape((4, 4))
x = x.T
x = np.flip(x, 0)
self.ax_r.imshow(x, cmap="binary")
plt.pause(0.1)
self.fig.show()
plt.pause(0.1)
if __name__ == "__main__":
out = SimpOutput()
for i in range(50):
out.update(i, 1000 * np.random.rand(), np.random.rand(16))
update is called in every loop.
Using fig.canvas.show() and different values for pause does not affect on the update. Furthermore, the methods set_array() and set_data() do not fix the problem either. While debugging, the figure is updated for every iteration. I write the code with PyCharm.
Does anyone had the same issue or rather does anyone has an idea how to solve this issue?
Thanks in advance!
Bests,
Sebastian
I tried to run the following simple code:
for i in range(50):
plt.clf()
pd.DataFrame([3,4,i]).plot.line(title=f'iteration {i}')
plt.show()
Not updating any figure, just clearing the old one and plotting a new figure.
It stops creating new figures after 30 iterations as well. Same problem as you.
I suspected the problem is in pycharm, so I tried one more thing.
I replaced plt.show() with plt.savefig(f'example_{i}.jpg'). It indeed saved all 50 figures in the folder (means it worked okay), and in addition, it gave me a warning:
envs\my_main_env\lib\site-packages\pandas\plotting\_matplotlib\core.py:337: 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_open_warning`).
fig = self.plt.figure(figsize=self.figsize)
indicating the problem is in the number of figures open at parallel. You can google the warning find some answers to it (e.g. warning about too many open figures).
I added the parameter at the beginning of the code: plt.rcParams.update({'figure.max_open_warning': 60})
now, running again. In pycharm in scientific mode, it didn't work. So I turned off scientific mode (opening a new figure for each plot) and now it works well! so I think that the limitation is a pycharm limitation for scientific mode - how many figures can be open at the same time.
turn off scientific mode for plotting by going to Settings->Tools->Python Scientific-> uncheck "Show plots in tool window" box.
That worked for me. I don't know how to change the limit in scientific mode (if possible at all). I believe it gives enough insights for you to solve your issue - whether by saving the figures or by plotting them without scientific mode.
When plotting with Python ggplot, every single plot command causes a GUI pane to be displayed and suspend execution ("interactive plotting"). But I want to:
avoid/ turn off this GUI and save the plot object some where in runtime (I will be displaying it in some other C# forms control).
find a Python equivalent to dev.off() command in R language which turns off the GUI for plotting.
Example:
print ggplot(data, aes('Age', 'Weight')) + geom_point(colour='steelblue')
When I execute this, it opens up a new GUI (like below) displaying the plot.
You can do the following, which returns a matplotlib figure:
g = ggplot(...) + geom_xxx(...)
fig = g.draw()
ggplots __repr__() method (what is called by print(g) is basically self.draw() then use matplotlibs plt.show() to show the plot...
You can also use ggsave(g) to save the plot somewhere.
Since plotting is triggered by __repr__ method the obvious approach is to avoid situations when it is called. Since you want to use this plot in some other place there is no reason to call print or even executing statements which will be discarded like this:
ggplot(data, aes('Age', 'Weight')) + geom_point(colour='steelblue')
Instead you can simply assign it to the variable
p = ggplot(data, aes('Age', 'Weight')) + geom_point(colour='steelblue')
what is exactly the same thing one would do in R. Using graphic device to redirect output and discarding it doesn't really make sense.
If for some reason that's not enough you switch to non-interactive matplotlib backend:
import matplotlib
matplotlib.use('Agg')
from ggplot import *
ggplot(aes(x='date', y='beef'), data=meat)
<ggplot: (...)>
if I work on a matplotlib inline plot in an ipython notebook like this:
figure = plt.figure()
ax = figure.gca(projection="3d")
graph = np.empty([len(thetaYield),3])
for g, tY in zip(graph, thetaYield):
sample = HWtoPS(xiYield, rhoYield, tY)
g[...] = sample[:]
ax.plot(graph[:,0],graph[:,1], graph[:,2])
plt.show()
the plot is drawn inline in my notebook as it intended.
Now I want to add to add some data to this plot:
principalStress, vectors = eig(sigma)
ax.scatter(principalStress[0], principalStress[1], principalStress[2])
plt.show()
no error, but also no plot is drawn.
I expected to get an "updated" version of my plot with the additional data.
How can this be done?
A: This can be done at a cost of changed matplotlib Renderer
Currently, this cannot be done for the IPython "inline" graphs, however, if you opt to change a Renderer part of the matplotlib framework, to another one, the limitation of a singleton call of the .show() method does not hurt and you can ex post modify the object's content and it gets re-processed by the Renderer.
Simply:
add a directive ( IPython magic) %matplotlib qt
&
use additional matplotlib calls as you expect 'em to modify/update the figure object
( I love using this both during prototyping phases & for interactive 3D-viewing of complex data visualisations (which I heavily miss in notebook's "inline"s) )
BTW: do you have about any methodology, which would allow to store a matplotlib 3D-view plot, as a complete, state-full container, that can be sent to some other user for her/his "load" and UI-interactive review? Would be great to hear about any such working :o)
How can I prevent a specific plot to be shown in Jupyter notebook? I have several plots in a notebook but I want a subset of them to be saved to a file and not shown on the notebook as this slows considerably.
A minimal working example for a Jupyter notebook is:
%matplotlib inline
from numpy.random import randn
from matplotlib.pyplot import plot, figure
a=randn(3)
b=randn(3)
for i in range(10):
fig=figure()
plot(b)
fname='s%03d.png'%i
fig.savefig(fname)
if(i%5==0):
figure()
plot(a)
As you can see I have two types of plots, a and b. I want a's to be plotted and shown and I don't want the b plots to be shown, I just want them them to be saved in a file. Hopefully this will speed things a bit and won't pollute my notebook with figures I don't need to see.
Thank you for your time
Perhaps just clear the axis, for example:
fig= plt.figure()
plt.plot(range(10))
fig.savefig("save_file_name.pdf")
plt.close()
will not plot the output in inline mode. I can't work out if is really clearing the data though.
I was able to prevent my figures from displaying by turning interactive mode off using the function
plt.ioff()
To prevent any output from a jupyter notebook cell you may start the cell with
%%capture
This might be usefull in cases all other methods shown here fail.
From IPython 6.0 on, there is another option to turn the inline output off (temporarily or persistently). This has been introduced in this pull request.
You would use the "agg" backend to not show any inline output.
%matplotlib agg
It seems though that if you had activated the inline backend first, this needs to be called twice to take effect.
%matplotlib agg
%matplotlib agg
Here is how it would look in action
I'm a beginner though,off the inline mode when you don't want to see the output in your notebook by:
%matplotlib auto
or:
%matplotlib
to use it back:
%matplotlib inline
more better solution would be to use:
plt.ioff()
which says inline mode off.
hope it helps.
On Jupyter 6.0, I use the following snippet to selectively not display the matplot lib figures.
import matplotlib as mpl
...
backend_ = mpl.get_backend()
mpl.use("Agg") # Prevent showing stuff
# Your code
mpl.use(backend_) # Reset backend
Building off #importanceofbeingernest's answer, one may call some function in a loop, and at each iteration, want to render a plot. However, between the each plot, you may want to render additional stuff.
Concretely:
Iterate a list of IDs
Call a function so a plot is rendered for each "ID"
Between each plot, render some markdown
# <cell begins>
def render(id):
fig, axes = plt.subplots(2, 1)
plt.suptitle(f'Metrics for {id}')
df.ColA.plot.bar(ax=axes[0])
df.ColB.plot.bar(ax=axes[1])
return fig
# <cell ends>
# -------------------------------------
# <cell begins>
%matplotlib agg
for id in df.ID.value_counts().index:
fig = render(id)
display(fig)
display(Markdown('---'))
# <cell ends>
I am using scipy-cluster to generate a hierarchical clustering on some data. As a final step of the application, I call the dendrogram function to plot the clustering. I am running on Mac OS X Snow Leopard using the built-in Python 2.6.1 and this matplotlib package. The program runs fine, but at the end the Rocket Ship icon (as I understand, this is the launcher for GUI applications in python) shows up and vanishes immediately without doing anything. Nothing is shown. If I add a 'raw_input' after the call, it just bounces up and down in the dock forever. If I run a simple sample application for matplotlib from the terminal it runs fine. Does anyone have any experiences on this?
I had the same issue on Ubuntu 10.04.
In order to get graphics to display from ipython interactive console, start it with "-pylab" switch, which enables the interactive use of matplotlib:
ipython -pylab
To get your graphics to display during the execution of a standalone script, use matplotlib.pyplot.show call. Here's an example from hcluster homepage, the first and last line are the significant bits here:
from matplotlib.pyplot import show
from hcluster import pdist, linkage, dendrogram
import numpy
from numpy.random import rand
X = rand(10,100)
X[0:5,:] *= 2
Y = pdist(X)
Z = linkage(Y)
dendrogram(Z)
show()
Invoking ipython with "-pylab" switch didn't make a difference for me.
(System: Fedora 13)
Though not ideal, my solution was to explicitly write the resulting figure as a file.
For example:
...
dendrogram(Z)
pylab.savefig( "temp.png" )
Hope this helps anyone who is running into the same issue.
Amendment: Be careful about simply using copy-and-paste with the hcluster package's brief tutorial, notably in that if you call pylab.savefig() after several types of dendrogram drawing shown in the tutorial, i.e.
distMat = # whatever distance matrix you have
dendrogram( linkage( distMat ) )
pylab.savefig( "exampleDendrogram.png" )
dendrogram( linkage( distMat, method="complete" ) ) #instead of default "single"
pylab.savefig( "exampleDendrogram.png" )
Then exampleDendrogram.png will contain both the single-linkage dendrogram and the complete-linkage dendrogram in the same figure, and they will likely cross-cross and look like a mess.
If you're as stupid as me, you'll spend 30-180 minutes in confusion about how to properly use hcluster, when it's actually just a matter of resetting matplotlib between dendrogram calls:
distMat = # whatever distance matrix you have
dendrogram( linkage( distMat ) )
pylab.savefig( "exampleDendrogram1.png" )
pylab.cla()
dendrogram( linkage( distMat, method="complete" ) ) #instead of default "single"
pylab.savefig( "exampleDendrogram2.png" )
Now, the resulting dendrogram image files will look like what you expected them to look like.
I have been facing the same problem. You can use one of the below methods
Use plt.show() :
use plt.show() after dedogram, this will show the plot
using plt.show
Use %matplotlib inline intially in jupyter notebook. this will show the plot after execution.
Using matplotlib inline