If I write following class:
from matplotlib import pyplot as plt
import numpy as np
class FigureShowingUp:
def __init__(self):
self.fig, self.ax = plt.subplots(ncols=1, figsize=(8,6))
def make_plot(self):
x = np.linspace(0, 1)
y = np.random.normal(loc=0, scale=1, size=len(x))
self.ax.scatter(x,y)
And import it in a notebook like:
from test_fig_class import FigureShowingUp
test = FigureShowingUp()
The plot always shows up upon initialization. How do I prevent that ?
I don't use notebooks very much, but presumably you have to turn off interactive plotting:
from matplotlib import pyplot as plt; plt.ioff()
Then show the figure after making the plot:
def make_plot(self):
x = np.linspace(0, 1)
y = np.random.normal(loc=0, scale=1, size=len(x))
self.ax.scatter(x,y)
plt.show()
Related
I have the following code to generate a simple graph.
%matplotlib notebook
from ipywidgets import *
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2 * np.pi)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
line, = ax.plot(x, np.sin(x))
def update(w = 1.0):
line.set_ydata(np.sin(w * x))
plt.show()
interact(update)
The code generates the plot just fine -
output
But when I drag the slider, the figure will not update. Any ideas on why this is?
Note: Your code actually works for me out of the box, so it may be worth updating your dependencies and see if that fixes it.
However, the main thing you want to change is to call fig.canvas.draw() instead of plt.show()
%matplotlib notebook
from ipywidgets import *
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2 * np.pi)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
line, = ax.plot(x, np.sin(x))
def update(w = 1.0):
line.set_ydata(np.sin(w * x))
fig.canvas.draw()
interact(update)
Using Ipympl
There is also a widget based notebook backend (that will also work in jupyterlab): ipympl which you can install with pip install ipympl and use with %matplotlib ipympl
In general the ipympl backend will work better with other widgets than the notebook backend.
using interactive with matplotlib
One unfortunate consequence of interactive is that it assumes the output will be fully regenerated every time the slider value changes. This doesn't always play super nicely with the set_data methods you are using. So you are likely better off manually generating and connecting the sliders. I'll also note that I've written a package that automates using the set_data command to connect widgets to updating matplotlib plots: https://mpl-interactions.readthedocs.io/en/stable/. With that package your code would be
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
import mpl_interactions.ipyplot as iplt
x = np.linspace(0, 2 * np.pi, 1000)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
def f(x, w):
return np.sin(w * x)
controls = iplt.plot(x, f, w=(1, 10))
This would do a job.
# load the interactive tool
from ipywidgets import interact, interactive, widgets, fixed
try:
from ipywidgets import Layout
except:
pass
import numpy as np
import matplotlib.pyplot as plt
%matplotlib notebook
def fta(freq = 50.0):
"showing sine frequency"
y = np.sin(freq*x)
f, ax1 = plt.subplots(nrows=1,figsize=(8,6))
ax1.plot(x[0:100], y[0:100],'b')
ax1.set_ylim(ymin=-1.1, ymax=1.1)
ax1.grid();
# then use it interactively,
interactive( fta, freq=(0.0,100.0))
I need help on how to update 3D quiver head value from csv
currently, I have a csv file with 3 columns of x, y, z axis that I want to update into u,v,w variable on my python code.
The problem I am facing is that the result animation does not animate properly. It is a static picture shown below.
https://i.stack.imgur.com/Os8FX.png
I'm sure that I must have messed up on how to iterate/read the csv data file.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots(subplot_kw=dict(projection="3d"))
# Reading the data from a CSV file using pandas
repo = pd.read_csv('test.csv',sep=',',header=0)
data = np.array((repo['x'].values, repo['y'].values, repo['z'].values))
def get_arrow():
x = 0
y = 0
z = 0
u = data[0][:]
v = data[1][:]
w = data[2][:]
return x,y,z,u,v,w
quiver = ax.quiver(0,0,0,0,0,0)
ax.set_xlim(-.5, .5)
ax.set_ylim(-.5, .5)
ax.set_zlim(-.5, .5)
def update(theta):
global quiver
quiver.remove()
quiver = ax.quiver(*get_arrow())
ani = FuncAnimation(fig, update, frames=np.linspace(0,2*np.pi,200), interval=50)
plt.show()
I'm not sure how the arrows will behave because the data is unknown, but I tried to create them with sample data. I've also included a library for GIF images and jupytert, so you can modify it to suit your environment.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.animation import FuncAnimation
import random
from IPython.display import HTML
from matplotlib.animation import PillowWriter
random.seed(20210110)
repo = (pd.DataFrame({'x':np.random.randint(0,5, size=50),
'y':np.random.randint(0,5, size=50),
'z':np.random.randint(0,5, size=50)}))
data = np.array((repo['x'].values, repo['y'].values, repo['z'].values))
fig, ax = plt.subplots(subplot_kw=dict(projection="3d"))
quiver = ax.quiver([],[],[],[],[],[])
ax.set_xlim(-5, 5)
ax.set_ylim(-5, 5)
ax.set_zlim(-5, 5)
def update(i):
global quiver
quiver.remove()
quiver = ax.quiver(0,0,0,data[0][i],data[1][i],data[2][i])
ani = FuncAnimation(fig, update, frames=50, interval=50)
# plt.show()
ani.save('./quiver_test_ani.gif', writer='pillow')
plt.close()
# jupyter lab
# HTML(ani.to_html5_video())
how to do this in jupyter notebook:
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
m = 100
n = 100
matrix = np.random.normal(0,1,m*n).reshape(m,n)
fig = plt.figure()
ax = fig.add_subplot(111)
plt.ion()
fig.show()
fig.canvas.draw()
for i in range(0,100):
#ax.clear()
plt.plot(matrix[i,:])
fig.canvas.draw()
but using "%matplotlib qt5" instead of "notebook"?
When I try it it show the figure only after the loop is ended. I would like to see it updating every plot.
In principle you can do the following in interactive mode:
%matplotlib qt4
import numpy as np
import matplotlib.pyplot as plt
m = 100
n = 100
matrix = np.random.normal(0,1,m*n).reshape(m,n)
fig = plt.figure()
ax = fig.add_subplot(111)
plt.ion()
plt.draw()
for i in range(0,30):
#ax.clear()
plt.plot(matrix[i,:])
plt.draw()
plt.pause(0.1)
plt.ioff()
plt.show()
However, it might crash in jupyter after finishing the loop, due to Qt being used.
It should however work, when using the tk backend, %matplotlib tk.
You might want to consider using a FuncAnimation instead of interactive mode. While this would suffer from the same limitations with Qt in Jupyter I find it more intuitive to use a function for updating the plot and there is no need to redraw the canvas manually.
%matplotlib tk
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation
m = 100
n = 100
matrix = np.random.normal(0,1,m*n).reshape(m,n)
fig = plt.figure()
ax = fig.add_subplot(111)
def update(i):
#ax.clear()
plt.plot(matrix[i,:])
ani = matplotlib.animation.FuncAnimation(fig, update, frames=30, repeat=False)
plt.show()
I asked a new question on why this would no work with the qt backend.
In the following lines I report a code that generates a plot changing over the time with Python on Anaconda Spyder
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(-3, 3, 0.01)
N = 1
fig = plt.figure()
ax = fig.add_subplot(111)
for N in range(8):
y = np.sin(np.pi*x*N)
line, = ax.plot(x, y)
plt.draw()
plt.pause(0.5)
line.remove()
I would like to do the some with Jupyter, but it is not possible. Particularly it seems that the Matplotlib method .pause() does not exist on Jupyter.
Is there anyone who can explain me this difference and can help me building up a code for plots variating over the time with Python on Jupyter, please?
It works for me if I select an interactive backend using the magic command %matplotlib; it is likely that your Jupyter notebook settings are set to display plots inline.
import matplotlib.pyplot as plt
import numpy as np
%matplotlib
x = np.arange(-3, 3, 0.01)
N = 1
fig = plt.figure()
ax = fig.add_subplot(111)
for N in range(8):
y = np.sin(np.pi*x*N)
line, = ax.plot(x, y)
plt.draw()
plt.pause(0.5)
line.remove()
To restore your setings, use the magic %matplotlib inline
I have read widely on this topic and spent several hours looking for ways to implement an animation for my plot.
I have managed an "animation" in-loop using plt.ion(), however, I can't get anything in matplotlib.animation to produce me an animated clip.
Below is a basic setup of the data I have to animate.
import matplotlib.pyplot as plt
import numpy as np
class plot_output(object):
def __init__(self):
self.fig, self.ax = plt.subplots(2,10)
plt.ion()
plt.show()
def iterate_animation(self, i, weight_list):
X = weight_list[i]
for i in range(20):
self.ax[i/10, i%10].cla()
wi = X[:,i]
wi=wi.reshape((28,28))
self.ax[i/10, i%10].axis('off')
self.ax[i/10, i%10].imshow(wi,cmap=plt.cm.gist_yarg,
interpolation='gaussian', aspect='equal')
plt.draw()
w_list = [np.random.rand(784,20) for i in range(4)]
p = plot_output()
for i in range(4):
p.iterate_animation(i=i, weight_list=w_list)