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()
Related
I was trying the first simple animation from this page. I am clearly a beginner at making animations. I paste the code below.
from matplotlib import pyplot as plt
from celluloid import Camera
fig = plt.figure()
camera = Camera(fig)
for i in range(10):
plt.plot([i] * 10)
camera.snap()
animation = camera.animate()
It gives me the following error.
Animation was deleted without rendering anything. This is most likely unintended. To prevent deletion, assign the Animation to a variable that exists for as long as you need the Animation.
As far as I can see, animate() has already been assigned a name. Could anyone resolve this issue for me?
To avoid this error (in fact is just a UserWarning), you have to display or save the animation. At the bottom of your code:
from matplotlib import pyplot as plt
from celluloid import Camera
fig = plt.figure()
camera = Camera(fig)
for i in range(10):
plt.plot([i] * 10)
camera.snap()
animation = camera.animate()
plt.show()
# OR
animation.save('test.mp4')
I want to display the coordinates of my cursor in an image displayed with matplotlib within a Jupyter notebook.
I am using the %matplotlib notebook magic as per this question.
While this provides a nice answer for a static figure, this results in a huge amount of flickering and bugs (the figure sometimes not showing) when used in an interactive setting where the figure is constantly redrawn during slicing. For example,
%matplotlib notebook
from ipywidgets import interact
import matplotlib.pyplot as plt
import numpy as np
vol = np.random.uniform(size=(16, 16, 16))
#interact(z=(0, 15))
def show(z):
plt.imshow(vol[z])
plt.show()
Without %matplotlib notebook, the figure is updating without any flicker, but does not show the cursor coordinates. With the magic, the coordinates are displayed, but the flickering is unbearable.
Is there a way to have pixel coordinates without flickering in that simple situation?
The problem is the use of plt.show(), which will replace the figure. Instead you probably want to update the existing figure.
%matplotlib notebook
from ipywidgets import interact
import matplotlib.pyplot as plt
import numpy as np
vol = np.random.uniform(size=(16, 16, 16))
fig, ax = plt.subplots()
im = ax.imshow(vol[0])
#interact(z=(0, 15))
def show(z):
im.set_array(vol[z])
im.set_clim(vol[z].min(), vol[z].max())
fig.canvas.draw_idle()
Note the the above provides the same functionality as the code in the question, i.e. each array is normalized individually. However, you might decide to set the color normalization only once such that all arrays share the same color limits.
%matplotlib notebook
from ipywidgets import interact
import matplotlib.pyplot as plt
import numpy as np
vol = np.random.uniform(size=(16, 16, 16))
fig, ax = plt.subplots()
im = ax.imshow(vol[0], vmin=vol.min(), vmax=vol.max())
fig.colorbar(im)
#interact(z=(0, 15))
def show(z):
im.set_array(vol[z])
fig.canvas.draw_idle()
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 )
Edit: My question is not in regards to an "animation" per se. My question here, is simply about how to continuously show, a new inline image, in a for loop, within an Ipython notebook.
In essence, I would like to show an updated image, at the same location, inline, and have it update within the loop to show. So my code currently looks something like this:
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from IPython import display
%matplotlib inline
fig, ax = plt.subplots(nrows = 1, ncols = 1, figsize=(10, 10))
for ii in xrange(10):
im = np.random.randn(100,100)
ax.cla()
ax.imshow(im, interpolation='None')
ax.set_title(ii)
plt.show()
The problem is that this currently just..., well, shows the first image, and then it never changes.
Instead, I would like it to simply show the updated image at each iteration, inline, at the same place. How do I do that? Thanks.
I am not sure that you can do this without animation. Notebooks capture the output of matplotlib to include in the cell once the plotting is over. The animation framework is rather generic and covers anything that is not a static image. matplotlib.animation.FuncAnimation would probably do what you want.
I adapted your code as follows:
%matplotlib notebook
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation
f = plt.figure()
ax = f.gca()
im = np.random.randn(100,100)
image = plt.imshow(im, interpolation='None', animated=True)
def function_for_animation(frame_index):
im = np.random.randn(100,100)
image.set_data(im)
ax.set_title(str(frame_index))
return image,
ani = matplotlib.animation.FuncAnimation(f, function_for_animation, interval=200, frames=10, blit=True)
Note: You must restart the notebook for the %matplotlib notebook to take effect and use a backend that supports animation.
EDIT: There is normally a way that is closer to your original question but it errors on my computer. In the example animation_demo there is a plain "for loop" with a plt.pause(0.5) statement that should also work.
You can call figure.canvas.draw() each time you append something new to the figure. This will refresh the plot (from here). Try:
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from IPython import display
from time import sleep
fig = plt.figure()
ax = fig.gca()
fig.show()
for ii in range(10):
im = np.random.randn(100, 100)
plt.imshow(im, interpolation='None')
ax.set_title(ii)
fig.canvas.draw()
sleep(0.1)
I could not test this in an IPython Notebook, however.
I've been using matplotlib for five months now on a daily basis, and I still find creation of new figures confusing.
Usually I create a figure with 2x2 subplots using, for example, somthing like:
import matplotlib.pyplot as plt
import itertools as it
fig,axes = plt.subplots(2,2)
axit = (ax for ax in it.chain(*axes))
for each of four data series I want to plot:
ax = next(axit)
ax.plot(...)
The question I have now is: how can operate completely independently of pyplot, ie, how can I create a figure, populate it with plots, make style changes, and only tell that figure to appear at the exact moment I want it to appear. Here is what I am having trouble with:
import matplotlib as mpl
gs = gridspec.GridSpec(2,2)
fig = mpl.figure.Figure()
ax1 = fig.add_subplot(gs[0])
ax1.plot([1,2,3])
ax2 = fig.add_subplot(gs[1])
ax2.plot([3,2,1])
After running the above, the only thing that comes to mind would be to use:
plt.draw()
But this does not work. What is missing to make the figure with the plots appear? Also, is
fig = mpl.figure.Figure()
all I have to do to create the figure without pyplot?
This works for me without matplotlib.pyplot
import sys
from PyQt5 import QtWidgets
from matplotlib.backends.backend_qt5agg import (
FigureCanvasQTAgg as FigureCanvas)
from matplotlib.figure import Figure
import numpy as np
fig=Figure()
canvas=FigureCanvas(fig)
ax=canvas.figure.add_subplot(111)
x=np.arange(-5,5,0.1)
y=np.sin(x)
ax.plot(x,y)
canvas.show()
app=QtWidgets.QApplication(sys.argv)
app.exec()
You could attach a suitable backend to your figure manually and then show it:
from matplotlib.backends import backend_qt4agg # e.g.
backend_qt4agg.new_figure_manager_given_figure(1, fig)
fig.show()
... but why not use pyplot?