I'm trying to share a github repo on binder. Locally, my interactive plot using matplotlib and #interact works ok. On binder it works half way. Same code adds static images to the cell output in binder notebook when slider value changes.
Question: how to fix binder behavior and make an interactive plot?
git repository https://github.com/queezz/Complex_Numbers
My notebook looks like this:
%pylab inline
from ipywidgets import interact, widgets
x = np.linspace(0,np.pi,100)
#interact
def plot_interactive(a=widgets.FloatSlider(min=1, max=10, val=1)):
plot(x,np.sin(x*a))
gca().set_aspect('equal')
ylim(-1.1,1.1)
Screenshot from binder:
Found a good working example:
https://github.com/Kapernikov/ipywidgets-tutorial
The gist of it is to use %matplotlib widget and #widgets.interact.
It seems that usage of %pylab inline is discouraged now, see this git issue.
I copy a part of the code from the tutorial which produces the same result as wanted in the question.
%matplotlib widget
import ipywidgets as widgets
import matplotlib.pyplot as plt
import numpy as np
# set up plot
fig, ax = plt.subplots(figsize=(6, 4))
ax.set_ylim([-4, 4])
ax.grid(True)
# generate x values
x = np.linspace(0, 2 * np.pi, 300)
def my_sine(x, w, amp, phi):
"""
Return a sine for x with angular frequeny w and amplitude amp.
"""
return amp*np.sin(w * (x-phi))
#widgets.interact(w=(0, 10, 1), amp=(0, 4, .1), phi=(0, 2*np.pi+0.01, 0.01))
def update(w = 1.0, amp=1, phi=0):
"""Remove old lines from plot and plot new one"""
[l.remove() for l in ax.lines]
ax.plot(x, my_sine(x, w, amp, phi), color='C0')
I wasn't able to get #queez's answer that uses 'interact' to work today (later updated in early 2023 is below); however, the ipywidgets documentation presently includes a matplotlib example, which uses 'interactive', that I was able to take and adapt #qqueezz's solution to get it working. This seems to be a much more streamlined route to make an interactive plot.
#%matplotlib inline # from the example in the documentation. but doesn't seem necessary in current JupyterLab 3.1.11 or the classic notebook available now https://github.com/fomightez/communication_voila
from ipywidgets import interactive
import matplotlib.pyplot as plt
import numpy as np
def my_sine(x, w, amp, phi):
"""
Return a sine for x with angular frequency w and amplitude amp.
"""
return amp*np.sin(w * (x-phi))
def f( w, amp, phi):
plt.figure(2)
x = np.linspace(0, 2 * np.pi, 300)
plt.plot(x, my_sine(x, w, amp, phi), color='C0')
#plt.ylim(-5, 5)
plt.grid(True) #optional grid
plt.show()
interactive_plot = interactive(f, w=(0, 10, 1), amp=(0, 4, .1), phi=(0, 2*np.pi+0.01, 0.01))
#output = interactive_plot.children[-1]
#output.layout.height = '450px'
interactive_plot
You can go to the repo here, launch a session by choosing the launch binder badge to the right of 'Start with the matplotlib & widget demo as a notebook' under 'Direct links to start out in notebook mode:'.
Or click here to launch directly into that notebook via MyBinder.
UPDATE:
Later (early 2023), I found queez's code from Kapernikov: Ipywidgets with matplotlib did work with interact in JupyterLab using ipympl.
Not following yet what changed; however, wanted to note.
Related
I have a python animation script (using matplotlib's funcAnimation), which runs in Spyder but not in Jupyter. I have tried following various suggestions such as adding "%matplotlib inline" and changing the matplotlib backend to "Qt4agg", all without success. I have also tried running several example animations (from Jupyter tutorials), none of which have worked. Sometimes I get an error message and sometimes the plot appears, but does not animate. Incidentally, I have gotten pyplot.plot() to work using "%matplotlib inline".
Does anyone know of a working Jupyter notebook with a simple inline animation example that uses funcAnimation.
[Note: I am on Windows 7]
notebook backend
'Inline' means that the plots are shown as png graphics. Those png images cannot be animated. While in principle one could build an animation by successively replacing the png images, this is probably undesired.
A solution is to use the notebook backend, which is fully compatible with FuncAnimation as it renders the matplotlib figure itself:
%matplotlib notebook
jsanimation
From matplotlib 2.1 on, we can create an animation 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(ani.to_jshtml())
Some complete example:
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()
ax.axis([0,2*np.pi,-1,1])
l, = ax.plot([],[])
def animate(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())
Alternatively, make the jsanimation the default for showing animations,
plt.rcParams["animation.html"] = "jshtml"
Then at the end simply state ani to obtain the animation.
Also see this answer for a complete overview.
There is a simple example within this tutorial here: http://louistiao.me/posts/notebooks/embedding-matplotlib-animations-in-jupyter-notebooks/
To summarise the tutorial above, you basically need something like this:
from matplotlib import animation
from IPython.display import HTML
# <insert animation setup code here>
anim = animation.FuncAnimation() # With arguments of course!
HTML(anim.to_html5_video())
However...
I had a lot of trouble getting that to work. Essentially, the problem was that the above uses (by default) ffmpeg and the x264 codec in the background but these were not configured correctly on my machine. The solution was to uninstall them and rebuild them from source with the correct configuration. For more details, see the question I asked about it with a working answer from Andrew Heusser: Animations in ipython (jupyter) notebook - ValueError: I/O operation on closed file
So, try the to_html5_video solution above first, and if it doesn't work then also try the uninstall / rebuild of ffmpeg and x264.
Another option:
import matplotlib.animation
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams["animation.html"] = "jshtml"
plt.rcParams['figure.dpi'] = 150
plt.ioff()
fig, ax = plt.subplots()
x= np.linspace(0,10,100)
def animate(t):
plt.cla()
plt.plot(x-t,x)
plt.xlim(0,10)
matplotlib.animation.FuncAnimation(fig, animate, frames=10)
Here is the answer that I put together from multiple sources including the official examples. I tested with the latest versions of Jupyter and Python.
Download FFmpeg ( http://ffmpeg.zeranoe.com/builds/ )
Install FFmpeg making sure that you update the environmental variable ( http://www.wikihow.com/Install-FFmpeg-on-Windows ).
Run this script in Jupyter below. The variable imageList is the only thing that you need to modify. It is an list of images (your input).
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from IPython.display import HTML
#=========================================
# Create Fake Images using Numpy
# You don't need this in your code as you have your own imageList.
# This is used as an example.
imageList = []
x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
for i in range(60):
x += np.pi / 15.
y += np.pi / 20.
imageList.append(np.sin(x) + np.cos(y))
#=========================================
# Animate Fake Images (in Jupyter)
def getImageFromList(x):
return imageList[x]
fig = plt.figure(figsize=(10, 10))
ims = []
for i in range(len(imageList)):
im = plt.imshow(getImageFromList(i), animated=True)
ims.append([im])
ani = animation.ArtistAnimation(fig, ims, interval=50, blit=True, repeat_delay=1000)
plt.close()
# Show the animation
HTML(ani.to_html5_video())
#=========================================
# Save animation as video (if required)
# ani.save('dynamic_images.mp4')
If you have a list of images and want to animate through them, you can use something like this:
from keras.preprocessing.image import load_img, img_to_array
from matplotlib import animation
from IPython.display import HTML
import glob
%matplotlib inline
def plot_images(img_list):
def init():
img.set_data(img_list[0])
return (img,)
def animate(i):
img.set_data(img_list[i])
return (img,)
fig = figure()
ax = fig.gca()
img = ax.imshow(img_list[0])
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=len(img_list), interval=20, blit=True)
return anim
imgs = [img_to_array(load_img(i)) for i in glob.glob('*.jpg')]
HTML(plot_images(imgs).to_html5_video())
Thank to Kolibril. I finally can run animation on Jupyter and Google Colab.
I modify some code which will generate animation of drawing random line instead.
import matplotlib.animation
import matplotlib.pyplot as plt
from itertools import count
import random
plt.rcParams["animation.html"] = "jshtml"
plt.rcParams['figure.dpi'] = 150
fig, ax = plt.subplots()
x_value = []
y_value = []
index = count();
def animate(t):
x_value.append(next(index))
y_value.append(random.randint(0,10))
ax.cla()
ax.plot(x_value,y_value)
ax.set_xlim(0,10)
matplotlib.animation.FuncAnimation(fig, animate, frames=10, interval = 500)
enter image description here
I am trying to get the PyMC3 examples from Osvaldo Martin's Bayesian Analysis with Python working. On Windows 10, while the following code using matplotlib works fine (i.e. a chart is displayed):
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats
def posterior_grid(grid_points=100, heads=6, tosses=9):
"""
A grid implementation for the coin-flip problem
"""
grid = np.linspace(0, 1, grid_points)
prior = 0.5 - abs(grid - 0.5)
likelihood = stats.binom.pmf(heads, tosses, grid)
unstd_posterior = likelihood * prior
posterior = unstd_posterior / unstd_posterior.sum()
return grid, posterior
if __name__ == "__main__":
points = 100
h, n = 1, 4
grid, posterior = posterior_grid(points, h, n)
plt.plot(grid, posterior, 'o-', label='heads = {}\ntosses = {}'.format(h, n))
plt.xlabel(r'$\theta$')
plt.legend(loc=0)
plt.show()
...I cannot get the following - which uses PyMC3's traceplot - to display a chart:
import pymc3 as pm
import numpy as np
import scipy.stats as stats
if __name__ == "__main__":
np.random.seed(123)
n_experiments = 4
theta_real = 0.35
data = stats.bernoulli.rvs(p=theta_real, size=n_experiments)
print(data)
with pm.Model() as our_first_model:
theta = pm.Beta('theta', alpha=1, beta=1)
y = pm.Bernoulli('y', p=theta, observed=data)
start = pm.find_MAP()
step = pm.Metropolis()
trace = pm.sample(1000, step=step, start=start)
burnin = 100
chain = trace[burnin:]
pm.traceplot(chain, lines={'theta':theta_real});
The code runs and exits fine, but no chart is displayed.
I have tried in IntelliJ IDEA with the Python plugin, from an Anaconda console window for my root environment, and from IPython.
In IPython, I get the following output on the console:
Out[3]:
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x0000024BDD622F60>,
<matplotlib.axes._subplots.AxesSubplot object at 0x0000024BDD667208>]], dtype=object)
...so obviously something is happening. But how can I display the results as a chart?
I have also tried the exact library versions listed in the book with Python 3.5, but still no traceplot chart:
Ipython 5.0
NumPy 1.11.1
SciPy 0.18.1
Pandas 0.18.1
Matplotlib 1.5.3
Seaborn 0.7.1
PyMC3 3.0
Various further Googling got me to the following answers.
With IPython, you must invoke with ipython --pylab auto to give matplotlib a suitable backend (on Windows at least).
With IntelliJ IDEA / PyCharm, you need to add
import matplotlib.pyplot as plt
and then
plt.show()
after the traceplot line to show the plot.
I would like to programmatically check from a Jupyter Notebook if ipywidgets is enabled. What ways are there to do so? I tried looking into nbextensions and notebook modules, but did not find a function to list enabled extensions.
My Notebook is on GitHub, and I want to provide a static plot there, and additionally also an interactive version if the user is actually running the notebook and has ipywidgets installed, and enabled.
The plotting code is
# Setup by importing some libraries and configuring a few things
import numpy as np
import ipywidgets
import matplotlib.pyplot as plt
%matplotlib inline
# Create two random datasets
data = np.random.random(15)
smallerdata = np.random.random(15) * 0.3
# Define a plotting function
def drawPlot():
plt.plot(range(len(data)), data, label="random data");
plt.plot(range(len(smallerdata)), smallerdata, 'r--', label="smaller random data");
plt.title("Two random dataset compared");
plt.grid(axis='y');
plt.legend();
# Define an interactive annotation function
def updatePlot(s=0):
print("data {0:.2f}, smallerdata {1:.2f}".format(data[s], smallerdata[s]))
drawPlot()
plt.annotate(s=round(data[s], 2),
xy=(s, data[s]),
xytext=(s + 2, 0.5),
arrowprops={'arrowstyle': '->'});
plt.annotate(s=round(smallerdata[s], 2),
xy=(s, smallerdata[s]),
xytext=(s + 2, 0.3),
arrowprops={'arrowstyle': '->'});
plt.show();
In pseudocode, I would like to achieve something like this:
if nbextensions.enabled('ipywidgets'):
slider = ipywidgets.interactive(updatePlot, s=(0, len(data) - 1, 1));
display(slider)
else:
drawPlot()
From the command line, conceptually similar command is jupyter nbextension list, but I want to do this from a running Python environment, also also provide a static plot when the user is just looking at the Notebook on GitHub (or similar).
Thank you :)
I may misunderstand what exactly is demanded here; however, I feel like a usual try-except solution would work.
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
data = np.random.random(15)
smallerdata = np.random.random(15) * 0.3
def drawPlot():
plt.plot(range(len(data)), data, label="random data");
plt.plot(range(len(smallerdata)), smallerdata, 'r--', label="smaller random data");
plt.title("Two random dataset compared");
plt.grid(axis='y');
plt.legend();
def updatePlot(s=0):
print("data {0:.2f}, smallerdata {1:.2f}".format(data[s], smallerdata[s]))
drawPlot()
plt.annotate(s=round(data[s], 2),
xy=(s, data[s]),
xytext=(s + 2, 0.5),
arrowprops={'arrowstyle': '->'});
plt.annotate(s=round(smallerdata[s], 2),
xy=(s, smallerdata[s]),
xytext=(s + 2, 0.3),
arrowprops={'arrowstyle': '->'});
plt.show();
try:
import ipywidgets
from IPython.display import display
slider = ipywidgets.interactive(updatePlot, s=(0, len(data) - 1, 1));
display(slider)
except:
drawPlot()
!jupyter nbextension list
would be a way to get a list of enable extensions from inside the notebook, you could get the output and see if the string are there, for instance
import subprocess
output = subprocess.getoutput('jupyter nbextension list')
if 'jupytext/index enabled' not in output:
logging.error('jupytext is not active')
I am unable to display images in iPython from matplotlib, an image appears for a split of a second in a pop up window instead of inline and then closes immediately. nothing appears in the iPython console which is inside Spyder.
from statistics import mean
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.pyplot import style
style.use('fivethirtyeight')
xs = np.array([1,2,3,4,5,6], dtype=np.float64)
ys = np.array([5,4,6,5,6,7], dtype=np.float64)
def best_fit_slop_and_intercept (xs,ys):
m = ( ((mean(xs)*mean(ys))-mean(xs*ys)) /
((mean(xs)**2)-mean(xs**2)) )
b = mean(ys)-m*mean(xs)
return m,b
m,b = best_fit_slop_and_intercept(xs,ys)
print (m,b)
regression_line = [m*x + b for x in xs ]
print (regression_line)
predict_x = 9
predict_y = predict_x*m + b
plt.scatter(predict_x,predict_y, color = 'g')
plt.scatter(xs,ys)
plt.plot(xs, regression_line)
plt.show()
You can type %matplotlib inline inside the iPython console to generate your plots within the console inside spyder. You can also type %matplotlib qtto get an interactive window.
Your code snippet works for me with both settings. Failing that you can go to [preferences>iPython console>Graphics>Graphics backend] to adjust the graphics defaults and settings to see if that fixes the problem.
Trying to do some plotting in SymPy -
As per this video I have written :
from sympy.plotting import plot, plot_parametric
e = sin(2*sin(x**3))
plot(e, (x, 0, 5));
But after evaling that cell I don't get any output? There isn't an error or
anything, it just doesn't display anything.
Another test :
from sympy import *
from sympy.plotting import plot, plot_parametric
import math
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
expr = x**2 + sqrt(3)*x - Rational(1, 3)
lf = lambdify(x, expr)
fig = plt.figure()
axes = fig.add_subplot(111)
x_vals = np.linspace(-5., 5.)
y_vals = lf(x_vals)
axes.grid()
axes.plot(x_vals, y_vals)
plt.show();
So Im not sure what I'm doing wrong here, I'm not getting any errors though?
If the virtual environment content is of any interest here's a tree of that :
venv
I'm running this on Linux Ubuntu. The virtual environment that it's running in can be seen in the above paste link
You need to use the magic functions, more specifically the ones for matplotlib:
%matplotlib qt # displays a pop-up of the plot
%matplotlib inline # keeps it within the notebook
Runnable example using Python 3.4 Nov '15:
from sympy import *
from sympy.plotting import plot, plot_parametric
import math
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
expr = x**2 + sqrt(3)*x - Rational(1, 3)
lf = lambdify(x, expr)
fig = plt.figure()
axes = fig.add_subplot(111)
x_vals = np.linspace(-5., 5.)
y_vals = lf(x_vals)
axes.grid()
axes.plot(x_vals, y_vals)
To get plots to show inline in the IPython notebook, you need to enable matplotlib's inline backend. You can do this by running
%matplotlib inline