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))
Related
Is it possible to have a matplotlib plot directly displayed in the plot viewer? I am currently working in VS Code on a juptyer notebook, both recently installed/updated. By default, the plot would open inline, like any other result of a cell, and I can open that in the plot viewer by clicking the icon in the top-left corner. Is it possible to have it displayed directly in the plot viewer, without the need to open it manually? I am just trying with something basic, like:
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
ax.plot(x, y)
Thank you!
Add %matplotlib qt to your code before creating the figure/axes instances
import matplotlib.pyplot as plt
import numpy as np
%matplotlib qt
fig, ax = plt.subplots()
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
ax.plot(x, y)
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()
I've been trying to create an interactive 3d plot in jupyter notebook.This worked great with matplotlib. Unfortunately matplotlib is very unfit to display intersecting planes. Therefore I wanted to switch to mayavi.
However mayavi shows some weird behaviour when I try to interactively change its values. Running the following Code:
%matplotlib notebook
#math
import numpy as np
#plotting
from mayavi import mlab
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.axes3d import Axes3D
from IPython import display
import time
mlab.init_notebook()
X = np.arange(-5, 5, 0.3)
Y = np.arange(-5, 5, 0.3)
X,Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
mlab.clf()
#plot setup
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
def foo(x, y):
display.clear_output()
ax.cla()
#generate plots
ax.pcolor(X,Y,R,cmap='Blues')
ax.plot(x, y, 'ro')
mlab.mesh(X + x,Y,R, colormap='Blues')
#display plots
display.display(plt.gcf())
display.display(mlab.gcf())
def op_on_click(event):
foo(event.xdata, event.ydata)
foo(3,0)
time.sleep(10)
foo(10,0)
fig.canvas.mpl_connect('button_press_event', op_on_click)
It will immediately display the mayavi plot and update it after 10 seconds (as expected). But it does not redraw when the on_click event of the matplotlib figure is triggered.
Running it without mlab.clf() shows that the meshes actually get generated, the plot just doesnt get redrawn.
Any help on how to make it react to the on_click would be very appreciated.
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