I'm trying to draw some charts generated by Matplotlib but I am finding that whilst it works correctly the first time, if I refresh my page, Matplotlib will just hang on _tkinter.create deep within its inner workings (Tkinter.py) when creating the figure (plt.figure). I've managed to narrow down the issue with the following small example..
Template (Only needs this one line)
<img src="data:image/png;base64,{{ graph }}"/>
Chart creation
class PolarChart(object):
#staticmethod
def example_chart():
from math import pi, radians
import cStringIO
import base64
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
axis = fig.gca(polar=True)
n = 20
theta = np.linspace(0.0, 2 * pi, n, endpoint=False)
radii = 10 * np.random.rand(n)
axis.plot(theta, radii, marker='.', alpha=0.5, linewidth=1)
jpg_image_buffer = cStringIO.StringIO()
fig.savefig(jpg_image_buffer)
plt.close(fig)
base_array = base64.b64encode(jpg_image_buffer.getvalue())
jpg_image_buffer.close()
return base_array
View
graph = PolarChart.example_chart()
return render(request, "test.html", {'graph': graph})
Other stackoverflow questions have suggested using fig.clear() but this also results in the page not rendering (the same hanging effect)
The issue turned out to be an issue with using the wrong backend... The issue was resolved with jenshnielsen's suggestion to change the backend that is being used before importing pyplot
import matplotlib
matplotlib.use('agg')
If your reading this, Jens, please post your own answer and I'll gladly delete this one!
Related
Im really new in programming with Python and in my final project I need to create this animation where 10 points are randomly moving in space (Brownian motion).
My teacher gave me some examples but I just cant figure out why my program is not working correctly. The error says:
"_included_frames frame_dir=os.path.dirname(frame_list[0]),
IndexError: list index out of range"
Sorry if I didnĀ“t express myself correctly but also English is not my native language.
from math import *
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
import matplotlib.animation as animation
fig = plt.figure()
ax = plt.axes(projection='3d')
N=10
x=500*np.random.random(N)
y=500*np.random.random(N)
z=500*np.random.random(N)
def frame(w):
ax.clear()
x=x+np.random.normal(0.0,50.0,10)
y=y+np.random.normal(0.0,50.0,10)
z=z+np.random.normal(0.0,50.0,10)
mensaje="Movimiento Browniano"
plt.title(mensaje)
ax.set_xlim3d(-500.0,500.0)
ax.set_ylim3d(-500.0,500.0)
ax.set_zlim3d(-500.0,500.0)
plot=ax.scatter3D(x, y, z, c='r')
return plot
anim = animation.FuncAnimation(fig, frame, frames=100, blit=False)
anim.save( 'MovimientoBrowniano.html', fps=5 )
There are two main problems with your code.
x,y and z are attempted to be changed locally in your function. However you really want to change the variables defined outside of the function scope. You may easily do that by declaring them globally: Add global x,y,z in your function.
You are trying to save the animation to an html file. That is no valid video format. I don't know which format you are targeting here, but a common option would be an animated gif, which could be produced by
anim.save('MovimientoBrowniano.gif', writer = "pillow", fps=5 )
I am trying to plot live data on a bloch sphere using Qutip's function bloch().
So far, the code always interrupts, when I have a b.show() in there.
I found a lot of solutions online to similar problems, but most of them make use of direct matplotlib commands like matplotlib.draw() which doesn't seem to work with the bloch class.
Then, there are other solutions which make use of for example Tk or GTKagg (e.g. https://stackoverflow.com/a/15742183/3276735 or real-time plotting in while loop with matplotlib)
Can somebody please help me how to deal with the same problem in the bloch class?
Edit:
Here's a minimal example:
Basically, I want to update my plot with one point at a time, preferably in a loop. My goal is to display live data in the plot that has to be read from a file.
import qutip as qt
import numpy as np
b = qt.Bloch()
theta = np.arange(0,np.pi,0.1)
for ii in range(len(theta)):
b.add_points([np.sin(theta[ii]),0,np.cos(theta[ii])])
b.show()
I think you are breaking your plot because you are calling show for every point. Try calling show outside the loop (in the end).
import qutip as qt
import numpy as np
b = qt.Bloch()
theta = np.arange(0,np.pi,0.1)
for ii in range(len(theta)):
b.add_points([np.sin(theta[ii]),0,np.cos(theta[ii])])
b.show() # Changed here
EDIT: Animated plot
Consider show as an absolute command to call the plot into view. It's not a draw command (or redraw). If you do want to show an image every "n" seconds or so you'll need to clear the plot before calling it again. You may try this:
import qutip as qt
import numpy as np
b = qt.Bloch()
theta = np.arange(0,np.pi,0.1)
for ii in range(len(theta)):
b.clear()
b.add_points([np.sin(theta[ii]),0,np.cos(theta[ii])])
b.show()
# wait time step and load new value from file.
, I don't have QuTip in my current distribution so I can't really test it but I'm betting its heavily based in matplotlib. My best advise however is for you to use the formulation give for animation in the QuTiP docs. By following this recipe:
from pylab import *
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import Axes3D
fig = figure()
ax = Axes3D(fig,azim=-40,elev=30)
sphere=Bloch(axes=ax)
def animate(i):
sphere.clear()
sphere.add_vectors([sin(theta),0,cos(theta)])
sphere.add_points([sx[:i+1],sy[:i+1],sz[:i+1]])
sphere.make_sphere()
return ax
def init():
sphere.vector_color = ['r']
return ax
ani = animation.FuncAnimation(fig, animate, np.arange(len(sx)),
init_func=init, blit=True, repeat=False)
ani.save('bloch_sphere.mp4', fps=20, clear_temp=True)
, you should be able to modify the animate function to perform all operations you need.
New to matplotlib and trying to explore existing data by iterating through a DataFrame via animation, but it seems very slow, can anyone see what I'm doing wrong or suggest improvements, have tried playing with frame speed but has little effect so I think its my code, would like to view this 2000 row object in 15 sec give or take. box is 8gb linex so should be fine, using ipython pop out figure to plot.
from pandas import *
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
coef_mean = DataFrame(np.random.rand(2000,50))
def animate(f_frame):
plt.cla()
plt.plot(coef_mean.columns.values, coef_mean.ix[f_frame])
plt.ylim(f_coef_min,f_coef_max)
fig = plt.figure(figsize=(9,5))
f_coef_min, f_coef_max = coef_mean.min().min()-.02, coef_mean.max().max()+.02
anim = animation.FuncAnimation(fig, animate, frames=150)
plt.show()
any ideas out there what I have done wrong ? many thanks, LW
also to get the popout figure try using
%matplotlib qt
You don't need to replot inside the animation function. Instead, you should just update the data of the plot. In your case something like this should work:
fig, ax = plt.subplots()
custom_plot, = ax.plot(coef_mean.columns.values, coef_mean.ix[0])
ax.set_ylim(f_coef_min,f_coef_max)
def animate(f_frame):
custom_plot.set_ydata(coef_mean.ix[f_frame])
return custom_plot,
Look at some animation examples for more information. E.g:
http://matplotlib.org/examples/animation/simple_anim.html
I'm trying to run a little program that should save my 3D scatterplot instead of opening it in a GUI. The problem is that it does both! This is the piece of code I'm talking about:
from matplotlib import pyplot
from scipy import math
from mpl_toolkits.mplot3d import Axes3D
fig = pyplot.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(xPosition, yPosition, zPosition, c = velocity, s = mass)
ax.set_xlim3d(-plotSize, plotSize)
ax.set_ylim3d(-plotSize, plotSize)
ax.set_zlim3d(-plotSize, plotSize)
pyplot.savefig('plot.png')
I would very much like to know how I can get a saved image of my plot without the plot being opened in a gui.
You should use pylab.ioff() as hilghlight by Saullo Castro, and each time you want to save a figure use pylab.savefig('file.png'). When you don't need the figure just do a pylab.close() to close the current figure (and free memory).
from matplotlib import pyplot
from mpl_toolkits.mplot3d import Axes3D
pyplot.ioff()
fig = pyplot.figure()
# HERE your code to add things in the figure
pyplot.savefig('file.png')
pyplot.close()
I need to get a plot that fits the data automatically using matplotlib. This is the code I was given:
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
....
lines = LineCollection(mpl.line_holder, colors=mpl.colorholder , linestyle='solid')
plt.axes().add_collection(lines)
plt.axes().set_aspect('equal', 'datalim')
plt.draw()
plt.show()
This creates a plot, however the window is always the same (0-~.8) no matter what the data is, even if all of the data is outside that window. The resulting window has no ability to zoom out, only in, so this is a major problem. I can't find anywhere where any kind of sizing is set, nor can II find details on what defaults are. I need the window to automatically fit the data, but I can't find any function that does it (for some reason, autoscale_on(True) doesn't do it). The data is highly variable, so setting hard limits is not an option. How can i get this to display properly?
Not sure if this what you wanted, but I can change it if this was not what you were looking for.
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
import pylab as p
fig = plt.figure()
pts1 = []
pts2 = []
for i in range(100):
pts1.append([i,i])
pts2.append([-i-3,-i])
lines = LineCollection([pts1,pts2], linestyles='solid')
subplt = fig.add_subplot(111,aspect='equal')
subplt.add_collection(lines)
subplt.autoscale_view(True,True,True)
p.show()
Hope that helps.
Have a look at Eli Bendersky's Website, specifically this post. The example at the bottom of the post can be downloaded. It allows you to set whether the x axis will follow the plot or will remain static while the y axis changes with the data.