Here's how to create a "stateful" plot in matplotlib and show it in non-interactive mode:
import matplotlib.pyplot as plt
plt.plot([1,2,8])
plt.show()
I am more interested in the "stateless" approach as I wish to embed matplotlib in my own python library. The same plot can be constructed "statelessly" as follows:
from matplotlib.figure import Figure
fig = Figure()
ax = fig.subplots()
lines = ax.plot([1,2,8])
However I don't know how to show it without resorting to pyplot , which I don't want to do as I would like to build up my own display mechanism.
How do I show the figure without resorting to pyplot?
Related
I am working on a project that involves generating a matplotlib animation using pyplot.imshow for the frames. I am doing this in a jupyter notebook. I have managed to get it working, but there is one annoying bug (or feature?) left. After the animation is created, Jupyter shows the last frame of the animation in the output cell. I would like the output to include the animation, captured as html, but not this final frame. Here is a simple example:
import numpy as np
from matplotlib import animation
from IPython.display import HTML
grid = np.zeros((10,10),dtype=int)
fig1 = plt.figure(figsize=(8,8))
ax1 = fig1.add_subplot(1,1,1)
def animate(i):
grid[i,i]=1
ax1.imshow(grid)
return
ani = animation.FuncAnimation(fig1, animate,frames=10);
html = HTML(ani.to_jshtml())
display(html)
I can use the capture magic, but that suppresses everything. This would be OK, but my final goal is to make this public, via binder, and make it as simple as possible for students to use.
I have seen matplotlib animations on the web that don't seem to have this problems, but those used plot, rather than imshow, which might be an issue.
Any suggestions would be greatly appreciated.
Thanks,
David
That's the answer I got from the same thing I was looking for in 'jupyter lab'. Just add plt.close().
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
from IPython.display import HTML
grid = np.zeros((10,10),dtype=int)
fig1 = plt.figure(figsize=(8,8))
ax1 = fig1.add_subplot(1,1,1)
def animate(i):
grid[i,i]=1
ax1.imshow(grid)
return
ani = animation.FuncAnimation(fig1, animate,frames=10);
html = HTML(ani.to_jshtml())
display(html)
plt.close() # update
Simple matplotlib plot. Here is my code
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
from itertools import count
import random
x = []
y = []
index=count()
def animate(i):
x.append(next(index))
y.append(random.randint(0,10))
plt.plot(x,y)
a = FuncAnimation(plt.gcf(),animate,interval=1000)
plt.tight_layout()
plt.show()
Running the code above I get
<Figure size 576x396 with 0 Axes>
but no chart appears.
Are you using Jupyter notebooks to run it? I tried with native libraries and it works just fine. The plots are visible.
Checking here i see the same situation. Could you try to use %matplotlib inline before importing matplotlib as:
%matplotlib inline # this line before importing matplotlib
from matplotlib import pyplot as plt
That said, the animation can be displayed using JavaScript. This is similar to the ani.to_html5() solution, except that it does not require any video codecs.
from IPython.display import HTML
HTML(a.to_jshtml())
this answer brings a more complete overview...
I have the code below, which works great with a single plot, but I'm trying to create a new plot with 1x2 subplots. The second plot will be identical to the first, just in another subplot.
# This code works fine as a single plot
%matplotlib inline
import time
import pylab as pl
from IPython import display
for i in range(10):
pl.clf()
pl.plot(pl.randn(100))
display.display(pl.gcf())
display.clear_output(wait=True)
time.sleep(1.0)
I'm not familar with pylab, but the above plot runs so smoothly compared to the pyplot code I found on the nex, that I'm trying to figure out how to implement this code with subplots.
#can't implement it to a plot with subplots
%matplotlib inline
import time
import pylab as pl
from IPython import display
f, (ax1, ax2) = plt.subplots(1, 2, sharey=True, sharex = True, figsize = (10,5))
for i in range(10):
pl.clf()
ax1.plot(pl.randn(100),)
ax2.plot(pl.randn(50))
display.display(pl.show())
display.clear_output(wait=True)
time.sleep(1.0)
However, no graph is being outputted with my attempt.
I'm played around with this code, but I can't seem to make it work cleanly.
thank you.
To visualize the plot with subplots, you should know the differences between Figure and Axes in matplotlib. Basically, axes belong to the figure, and you want to plot your data in the axes, but display the figure. Both Figure and Axes instances can be obtained with a single call to pl.subplots(nrow, ncol). See if the code below does what you want:
%matplotlib inline
import time
import pylab as pl
from IPython import display
for i in range(10):
pl.clf()
f, ax = pl.subplots(1, 2)
ax[0].plot(pl.randn(100))
ax[1].plot(pl.randn(100))
display.display(f)
display.clear_output(wait=True)
time.sleep(1.0)
My code contains the following lines:
from matplotlib.figure import Figure
figure = Figure(figsize=(10, 5), dpi=dpi)
How can I get matplotlib to show this figure? I also show it embedded in tkinter, which workes fine. However I would also be able to show it in the standard matplotlib window. But I can't for the life of me get it to work.
According to AttributeError while trying to load the pickled matplotlib figure, a simple workaround is:
fig = plt.Figure(...)
......
managed_fig = plt.figure(...)
canvas_manager = managed_fig.canvas.manager
canvas_manager.canvas.figure = fig
fig.set_canvas(canvas_manager.canvas)
Note that I encountered "'Figure' object has no attribute '_original_dpi'" in my environment. Not sure if it's some compatibility issue between my PyPlot and the PyQt5. Just did a hack:
fig._original_dpi = 60
to get around this. Not sure if there are any better solutions.
I usually use matplotlib's pyplot for immediate generation (or produce images in jupyter notebooks). This would look like the following:
import matplotlib.pyplot as plt
figure = plt.figure(figsize=(10, 5), dpi=dpi)
plt.show()
This shows the (blank) figure as desired.
This question already has answers here:
How can I use seaborn without changing the matplotlib defaults?
(2 answers)
Closed 3 years ago.
Seaborn provides of a handful of graphics which are very interesting for scientifical data representation.
Thus I started using these Seaborn graphics interspersed with other customized matplotlib plots.
The problem is that once I do:
import seaborn as sb
This import seems to set the graphic parameters for seaborn globally and then all matplotlib graphics below the import get the seaborn parameters (they get a grey background, linewithd changes, etc, etc).
In SO there is an answer explaining how to produce seaborn plots with matplotlib configuration, but what I want is to keep the matplotlib configuration parameters unaltered when using both libraries together and at the same time be able to produce, when needed, original seaborn plots.
If you never want to use the seaborn style, but do want some of the seaborn functions, you can import seaborn using this following line (documentation):
import seaborn.apionly as sns
If you want to produce some plots with the seaborn style and some without, in the same script, you can turn the seaborn style off using the seaborn.reset_orig function.
It seems that doing the apionly import essentially sets reset_orig automatically on import, so its up to you which is most useful in your use case.
Here's an example of switching between matplotlib defaults and seaborn:
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
# a simple plot function we can reuse (taken from the seaborn tutorial)
def sinplot(flip=1):
x = np.linspace(0, 14, 100)
for i in range(1, 7):
plt.plot(x, np.sin(x + i * .5) * (7 - i) * flip)
sinplot()
# this will have the matplotlib defaults
plt.savefig('seaborn-off.png')
plt.clf()
# now import seaborn
import seaborn as sns
sinplot()
# this will have the seaborn style
plt.savefig('seaborn-on.png')
plt.clf()
# reset rc params to defaults
sns.reset_orig()
sinplot()
# this should look the same as the first plot (seaborn-off.png)
plt.savefig('seaborn-offagain.png')
which produces the following three plots:
seaborn-off.png:
seaborn-on.png:
seaborn-offagain.png:
As of seaborn version 0.8 (July 2017) the graph style is not altered anymore on import:
The default [seaborn] style is no longer applied when seaborn is imported. It is now necessary to explicitly call set() or one or more of set_style(), set_context(), and set_palette(). Correspondingly, the seaborn.apionly module has been deprecated.
You can choose the style of any plot with plt.style.use().
import matplotlib.pyplot as plt
import seaborn as sns
plt.style.use('seaborn') # switch to seaborn style
# plot code
# ...
plt.style.use('default') # switches back to matplotlib style
# plot code
# ...
# to see all available styles
print(plt.style.available)
Read more about plt.style().
You may use the matplotlib.style.context functionality as described in the style guide.
#%matplotlib inline #if used in jupyter notebook
import matplotlib.pyplot as plt
import seaborn as sns
# 1st plot
with plt.style.context("seaborn-dark"):
fig, ax = plt.subplots()
ax.plot([1,2,3], label="First plot (seaborn-dark)")
# 2nd plot
with plt.style.context("default"):
fig, ax = plt.subplots()
ax.plot([3,2,1], label="Second plot (matplotlib default)")
# 3rd plot
with plt.style.context("seaborn-darkgrid"):
fig, ax = plt.subplots()
ax.plot([2,3,1], label="Third plot (seaborn-darkgrid)")
Restore all RC params to original settings (respects custom rc) is allowed by seaborn.reset_orig() function
As explained in this other question you can import seaborn with:
import seaborn.apionly as sns
And the matplotlib styles will not be modified.