Using MPLD3 to add graphs into Django projects. - python

I'm working on a Django project where I'd like to get data from CSV's and plot them to pages built using Django's views/ templates. Heres the code I have thus far:
import matplotlib.pyplot as plt, mpld3
graph = plt.plot([1,2,3,4])
g = mpld3.fig_to_html(graph)
return HttpResponse(g)
However when I run this I get the error:
AttributeError: 'list' object has no attribute 'savefig'
Anyone know where I went wrong, or how I can create graphs I can add into pages I already have, and not the page MPLD3 renders for you.

plt.plot returns a list of Line2D objects, not a figure object.
What you want to do is this:
import matplotlib.pyplot as plt, mpld3
fig = plt.figure()
fid=plt.plot([3,1,4,1,5])
mpld3.save_html(fig,"test.html")
mpld3.fig_to_html(fig,template_type="simple")
mpld3.show()

Like write #hck3r, plt.plot returns a list of Line2D objects, not a figure object. You need little modifications of your code:
import matplotlib.pyplot as plt, mpld3
fig = plt.figure()
plt.plot([1,2,3,4])
g = mpld3.fig_to_html(fig)
return HttpResponse(g)

Related

Suppress display of final frame in matplotlib animation in jupyter

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

Python: Why does this command work when I didn't import command

I'm writing a Python GUI for the first time to plot some data, and have imported the following modules/commands to do so
from tkinter import *
from tkinter.filedialog import askopenfilename
from tkinter.ttk import *
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.cm import get_cmap
from matplotlib.pyplot import figure
from scipy.interpolate import griddata
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
Searching the internet, I found some code that worked to get my plot embedded in the GUI:
fig = figure()
fig.add_subplot(111).pcolormesh(X, Y, Z, cmap = get_cmap('BuPu'))
canvas = FigureCanvasTkAgg(fig, master = window) # A tk.DrawingArea.
canvas.draw()
canvas.get_tk_widget().pack(side = TOP, fill = BOTH, expand = 1)
My question is why does pcolormesh work in the second line above when I didn't import that command from matplotlib.pyplot? I'm new to Python, and I'm sure I'm missing something, but if I wanted to use the pcolormesh command in the past, I had to import it. Thanks.
Your function calls created objects and those objects have methods. You don't need to import those methods as they are attached directly to the object. They are different from importing a function as you don't have direct access to those methods: they can only be accessed from the object.
when you set fig = figure(), you created an object. If you print(repr(fig)) you'll see something like this.
'<matplotlib.figure.Figure object at 0x000000000784F208>'
so fig is a Figure object. This objects comes with some methods and properties attached to it. You can get a list of all the methods using dir(fig) (it's a long list, so I won't print it here).
fig.subplot(111) calls the subplot method attached to your fig object. It returns a new object (an AxesSubplot). That object has a method attached to it called pcolormesh. If you want to play around with that object, you can do this.
ax = fig.subplot(111)
ax.pcolormesh(X, Y, Z, cmap = get_cmap('BuPu'))
print(repr(ax))
In addition to doing your stuff, this will print <matplotlib.axes._subplots.AxesSubplot at 0x8996f28>.
I remember being similarly confused by matplot.pyplot when I first started out because you can often do nearly identical things with a function (matplotlib.pyplot.pcolomesh) and as a method of an object (in the above example, ax.pcolormesh). They mention it in the API explanation here and here.

Using Matplotlib for plotting 3D data - warning/error importing module [duplicate]

When using the typical 3D plot like so:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.gca(projection='3d')
flake8 reports the expected error:
./tools.py:62:9: F401 'mpl_toolkits.mplot3d.Axes3D' imported but unused
I know it can be avoided using the # NOQA comment. But is there a different way to formulate the projection in the figure so that the Axes3D object is used?
If this is only about actually using the import at least once, you can do
ax = fig.gca(projection=Axes3D.name)
as "3d" is the name of the Axes3D class by which it is registered to the projection list.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure()
ax = Axes3D(fig)
However, if I understand the documentation well, it is not the preferred way anymore since version 1.0.0. I still mention it for completeness.

How to directly use Axes3D from matplotlib in standard plot to avoid flake8 error

When using the typical 3D plot like so:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.gca(projection='3d')
flake8 reports the expected error:
./tools.py:62:9: F401 'mpl_toolkits.mplot3d.Axes3D' imported but unused
I know it can be avoided using the # NOQA comment. But is there a different way to formulate the projection in the figure so that the Axes3D object is used?
If this is only about actually using the import at least once, you can do
ax = fig.gca(projection=Axes3D.name)
as "3d" is the name of the Axes3D class by which it is registered to the projection list.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure()
ax = Axes3D(fig)
However, if I understand the documentation well, it is not the preferred way anymore since version 1.0.0. I still mention it for completeness.

How to show matplotlib plot from a figure object

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.

Categories