I can't get Jupyterlab to make plots interactable with widgets - python

I have some plots that I want to interact with through widgets in Jupyterlab.
I installed the Widgets extension like described in this manual.
Anaconda shows me that ipywidgets and widgetsnbextension are installed in my environment.
In order to get the hang of the procedure, I followed a tutorial. When executing the code, I get the error message
'Javascript Error: IPython is not defined'.
I tried to change the magic command to %matplotlib inline, this builds an empty plot, that doesn't show any curve.
import ipywidgets as widgets
from IPython.display import display
import matplotlib.pyplot as plt
import numpy as np
%matplotlib nbagg
x=np.linspace(0,2,1000)
fig, ax=plt.subplots(1,figsize=(10,4))
plt.suptitle('Sine Wave')
def update_plot(amp, phase, freq):
'''
this function linked to the sliders and
it replots the sine waves when the sliders are changed
'''
ax.clear()
y = amp * np.sin(freq * 2 * np.pi * x + phase * 2 * np.pi)
ax.plot(x,y)
plt.show()
amp=widgets.FloatSlider(min=1,max=10,value=4,description='Amp')
phase=widgets.FloatSlider(min=0,max=5,value=0,description='Phase')
freq=widgets.FloatSlider(min=1,max=10,value=1,description='Freq')
widgets.interactive(update_plot, amp=amp, phase=phase, freq=freq)
This should deliver a plot of a sine curve, that is interactable via the sliders to change amplitue, phase and frequency.
I don't know what I could try to get it running.

Quick update:
I don't know what's wrong with the code I tried before, but I found another example that works and is more minimalistic as well:
from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
def plot_func(freq):
x = np.linspace(0, 2*np.pi,1000)
y = np.sin(x * freq)
plt.plot(x, y)
interact(plot_func, freq = widgets.FloatSlider(value=2.5, min=1,
max=5.0,step=0.5))
I'll now just use this example as template to make my own codes.

Related

Dynamically plot instead of %matplotlib notebook in jupyter lab without side effect

I recently used jupyter lab instead of jupyter notebook.
But the following code can't work expectations.
import matplotlib.pyplot as plt
import numpy as np
from tqdm.notebook import tqdm, trange
#%matplotlib widget # For jupyter lab
%matplotlib notebook # For jupyter notebook
plt.ion()
fig, ax = plt.subplots()
xs = []
for i in trange(100):
x = i / 10
xs.append(x)
ax.clear()
ax.plot(xs, np.sin(xs))
fig.canvas.draw()
It works on the jupyter notebook, the plot will update dynamically.
But It doesn't work on the jupyter lab.
Of cause, the magic code of %matplotlib is changed on the individual environment.
By the way, I know another method to plot dynamically.
This method also work jupyter lab.
But this method can't work tqdm because clear_output will clear progress bar too.
How to avoid this problem instead of the above question?
I seem the below question is more simple than the above question.
import matplotlib.pyplot as plt
import numpy as np
from tqdm.notebook import tqdm, trange
from io import BytesIO
import imageio
from IPython.display import Image, display_png, clear_output
#%matplotlib widget
%matplotlib notebook
plt.ion()
fig, ax = plt.subplots()
xs = []
for i in trange(100):
x = i / 10
xs.append(x)
ax.clear()
ax.plot(xs, np.sin(xs))
io = BytesIO()
fig.savefig(io, format='png')
clear_output(wait=True)
display_png(Image(io.getvalue()))
Updated:
The result of the above script is the following gif.
This plot is dynamically rendering while running the script.
(This script is not complitely because the tqdm progress bar is cleared.
the problem is side effect of IPython.display.clear_output.)

Matplotlib FuncAnimation not plotting any chart inside Jupyter Notebook

Simple matplotlib plot. Here is my code
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
from itertools import count
import random
x = []
y = []
index=count()
def animate(i):
x.append(next(index))
y.append(random.randint(0,10))
plt.plot(x,y)
a = FuncAnimation(plt.gcf(),animate,interval=1000)
plt.tight_layout()
plt.show()
Running the code above I get
<Figure size 576x396 with 0 Axes>
but no chart appears.
Are you using Jupyter notebooks to run it? I tried with native libraries and it works just fine. The plots are visible.
Checking here i see the same situation. Could you try to use %matplotlib inline before importing matplotlib as:
%matplotlib inline # this line before importing matplotlib
from matplotlib import pyplot as plt
That said, the animation can be displayed using JavaScript. This is similar to the ani.to_html5() solution, except that it does not require any video codecs.
from IPython.display import HTML
HTML(a.to_jshtml())
this answer brings a more complete overview...

iPython notebook with Matplotlib only drawing the last fig.canvas.draw() call [duplicate]

I am trying to put animations in an iPython notebook and am not finding a solution. I saw one post that discussed using interactive widgets, but there are a couple problems that I have with this: First, every example I see with widgets uses a slider or some other input, whereas I just want the animation to run automatically when the cell is run. Second, all the documentation seems out of date on Jupyter's site--whenever I download and run their notebooks I get these messages about certain modules being deprecated and then later in the file something fails to run, presumably because they're trying to import and access files that no longer exist.
I've seen a few other pages on the topic but they often require downloading binaries or other modules, but I'm partly using this to teach some students Math and I've gotten them to download Anaconda--I was hoping to not further confuse the issue by making them also download and install more complicated things all while spending time not talking about the Math.
So in short, is there a way that I can create animations in an iPython notebook that only require the use of simple import commands that will run out-of-the-box so to speak with the software that comes from Anaconda?
[Edit: I should also note that I've used Tkinter to make animations, and I could make one in matplotlib I'm sure. So if there were a way to get the animations you produce with those to render in an iPython notebook, that would certainly be a working solution for me.]
[Further edit: I suppose I could also say what I am hoping to animate at the moment, although I really want to be pretty flexible about the range of things I could animate if I decide to. Right now I'm trying to make a digital clock that displays each digit in Sumerian base-60 numerals to illustrate a different counting and base system. So it should initially display | then after a second || and so on until ten gets represented as < and so on until eventually the clock ticks over to a minute where it now displays |:| to represent one minute, one second.]
[Note to future humans: If you're implementing some animation and are willing to publicly host it, please leave a link to it in the comments! I'm curious to see how people are making animations these days, and also a little curious to see what they're animating.]
Some options you have for animating plots in Jupyter/IPython, using matplotlib:
Using display in a loop Use IPython.display.display(fig) to display a figure in the output. Using a loop you would want to clear the output before a new figure is shown. Note that this technique gives in general not so smooth resluts. I would hence advice to use any of the below.
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
from IPython.display import display, clear_output
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
for i in range(len(x)):
animate(i)
clear_output(wait=True)
display(fig)
plt.show()
%matplotlib notebook Use IPython magic %matplotlib notebook to set the backend to the notebook backend. This will keep the figure alive instead of displaying a static png file and can hence also show animations.
Complete example:
%matplotlib notebook
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
plt.show()
%matplotlib tk Use IPython magic %matplotlib tk to set the backend to the tk backend. This will open the figure in a new plotting window, which is interactive and can thus also show animations.
Complete example:
%matplotlib tk
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
plt.show()
Convert animation to mp4 video (option mentionned by #Perfi already):
from IPython.display import HTML
HTML(ani.to_html5_video())
or use plt.rcParams["animation.html"] = "html5" at the beginning of the notebook.
This will require to have ffmpeg video codecs available to convert to HTML5 video. The video is then shown inline. This is therefore compatible with %matplotlib inline backend. Complete example:
%matplotlib inline
import matplotlib.pyplot as plt
plt.rcParams["animation.html"] = "html5"
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
ani
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
from IPython.display import HTML
HTML(ani.to_html5_video())
Convert animation to JavaScript:
from IPython.display import HTML
HTML(ani.to_jshtml())
or use plt.rcParams["animation.html"] = "jshtml" at the beginning of the notebook.
This will display the animation as HTML with JavaScript. This highly compatible with most new browsers and also with the %matplotlib inline backend. It is available in matplotlib 2.1 or higher.
Complete example:
%matplotlib inline
import matplotlib.pyplot as plt
plt.rcParams["animation.html"] = "jshtml"
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
ani
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
from IPython.display import HTML
HTML(ani.to_jshtml())
You may find this tutorial interesting.
If you can turn what you need into a matplotlib animation, and I'm fairly sure from your description that it's possible, you can then use
from matplotlib import rc, animation
rc('animation', html='html5')
and display your animation using
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=N, interval=20, blit=True)
anim
Might come in handy!
Jupyter widgets is a good way of displaying animations. The code below displays an animated gif.....
from ipywidgets import Image
from IPython import display
animatedGif = "animatedGifs/01-progress.gif" #path relative to your notebook
file = open(animatedGif , "rb")
image = file.read()
progress= Image(
value=image,
format='gif',
width=100,
height=100)
display.display(progress)
You can close this animation using:
progress.close()
N.B. I found a few nice animated gifs from http://www.downgraf.com/inspiration/25-beautiful-loading-bar-design-examples-gif-animated/.
I had a similar problem, and this question helped me get started. I put together a notebook that illustrates using FuncAnimation along with good explanations of why the notebook does some things the way it does. It also has links to instructions on FFmpeg. It also has links to the examples I used in developing and understanding of animations. You can view my contribution at:
Animation Illustration
For your question, you might find interactive sliders a better tool. I also created a notebook which demonstrates interactive widgets in Jupyter. It is available here; however, the interactive parts don't work there.
Both are available in a GitHub Repostory

IPython interactive widget is not updating plotly when downloaded as html

I'm using Jupyter Notebook and trying to create an interactive plot. I really like how simple the ipywidgets.interactive is to use and having the ability to lay things out in VBox or HBox. The problem I'm having is once I download as html the ipywidgets.interactive is not updating my plot.
Here is what I have:
from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets
import plotly.graph_objs as go
import plotly.offline as py
import numpy as np
from IPython.display import display
py.init_notebook_mode()
xs = np.linspace(0,6,100)
ys = np.sin(xs)
scatter = go.Scatter(
x = xs,
y = ys
)
data = [scatter]
layout = go.Layout(title='test')
fig = go.FigureWidget(data=data, layout=layout)
slider = widgets.FloatRangeSlider(
min=1,
max=6,
step=.1,
description='desc'
)
def update_b(b):
fig.data[0].y = np.sin(xs+b)
vb = widgets.VBox((fig, interactive(update_b, b=(1, 6, .1))))
vb.layout.align_items='center'
# This displays it and allows it to be interactive, but only when I have it as .ipynb,
# not when I download as html
display(vb)
The way I am saving as html is:
1. Widgets > Save Notebook Widget State
2. From cmd: jupyter nbconvert --to html test_plot.ipynb
I have also done the following to enable the widget extension:
jupyter nbextension enable --py widgetsnbextension
Enabling notebook extension jupyter-js-widgets/extension...
- Validating: ok
After everything this is what I get:
The thing is the slider is movable but it does not update the graph. The graph is also able to be manipulated through zoom, etc. like normal with plotly. This leads me to believe there is something wrong with the way I've used interactive.
Any ideas?
Unfortunately this does not work this way, the function that links the slider with the plot is written in python and executes in the python kernel, so when you convert to a static html this function does not exist anymore.
I am not aware of some kind of python to javascript translator that allows these kind of functions to run without a python kernel, although plotly's Dash seems to be doing something in this line (see this issue). If you can put up a server you can use Voila or something similar to make the notebook look like a web page.
I'm not using plotly, however, try adding some line magic, like "widget" which makes the graph interactive...
%matplotlib widget
%matplotlib widget
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);
screenshot of notebook

How can I change the tools on a bokeh plot created using mpl.to_bokeh?

I am trying to display a complex signal in x and y and have the awesome interactive tools available from bokeh inside of an ipython notebook. In particular I would like to restrict the wheel zoom to the x axis, but I can't see how to do this after using mpl.to_bokeh(). Is there a way to set the default tools before using mpl.to_bokeh()?
For context here is a sample plot I would like to use:
import matplotlib.pyplot as plt
import bokeh.plotting as blt
from bokeh import mpl
from bokeh.plotting import show
blt.output_notebook()
import numpy as np
blt.figure(tools='xwheel_zoom') # this doesn't help
x= np.arange(100)/100
y= np.exp(1j*2*np.pi*x)
ax= plt.subplot(211)
plt.plot(x,y.real)
plt.subplot(212, sharex=ax)
plt.plot(x,y.imag)
fig= mpl.to_bokeh(name='subplots')
Unfortunately, doing this with the MPL compat layer would already be somewhat difficult with just a single plot. I am not sure there is currently any way at all to do it with a grid plot and MPL. However, it is pretty trivial to do if you use the bokeh API directly. In case that is an option for you, and it is helpful:
from bokeh.plotting import figure, gridplot, show
import numpy as np
x = np.arange(100)/100
y = np.exp(1j*2*np.pi*x)
p1 = figure(tools='xwheel_zoom')
p1.line(x,y.real)
p2 = figure(tools='xwheel_zoom')
p2.line(x,y.imag)
grid = gridplot([[p1, p2]])
show(grid)

Categories