0

I am trying to plot some data from a camera dynamically using drawnow. However, the dynamic plotting (using matplotlib and drawnow) doesn't seem to be working on jupyter notebook.

It's currently working in Pycharm.

My code:

import matplotlib.pyplot as plt
import numpy as np
from drawnow import *


x = np.random.randn(10, 2)


def function_to_draw_figure():
    plt.plot(i, j, 'r.')


plt.ion()
figure()
for i, j in x:
    drawnow(function_to_draw_figure)
    plt.xlim(-1, 1)
    plt.ylim(-1, 1)
    plt.pause(0.5)

I would expect this example to plot 10 points dynamically on the same figure (as in pycharm). What actually happens is that multiple figures appear rather than one.

Any thoughts why I am not able to do it using jupyter notebook?

2 Answers2

1

I never quite understood the purpose of drawnow. You should get the exact same result just calling your function.

Neither drawnow nor its equivalent simply using plt.ion() and plt.draw() or plt.pause() will work in jupyter notebooks. For sure not using the %matplotlib inline backend (because you cannot animate pngs); but also not with the %matplotlib notebook backend due to the event loop which has not been started until the final figure is shown.

Options to show an animation in jupyter notebooks are listed in Animation in iPython notebook.

The recommended way would be to create a FuncAnimation.

The animation from above would then look like

%matplotlib notebook
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np

x = np.random.rand(10, 2)


def function_to_draw_figure(i):
    line.set_data(*x[i,:])

plt.figure()
line, = plt.plot([], marker="o")
plt.xlim(0, 1)
plt.ylim(0, 1)

ani = FuncAnimation(plt.gcf(), function_to_draw_figure, frames=len(x), 
                    interval=500, repeat=False)

plt.show()
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • Thanks, but your code is stacking the figures not updating them. –  Apr 30 '18 at 16:42
  • At the final iteration (final figure), you should see only one point (x[9,:]). –  Apr 30 '18 at 16:46
  • Really? So `drawnow` clears the figure for each call? – ImportanceOfBeingErnest Apr 30 '18 at 16:57
  • Yes, If you run my code in pycharm or any other IDE, it will plot each point dynamically . At each iteration, you plot the current point on the same figure. The point will jump from a position to next position. –  Apr 30 '18 at 17:07
  • 1
    I see. It will even clear the complete figure. Pretty unefficient if you ask me. Btw, the [drawnow page](https://github.com/stsievert/python-drawnow) clearly states that it's not working in IPython (hence also not in Juypter). I updated the answer. – ImportanceOfBeingErnest Apr 30 '18 at 17:23
  • Thanks, for the answer. I would like to know why using * in *x[i,:]. The code seems work in both cases without pointing to the variable. –  Apr 30 '18 at 17:46
  • For `plot` the unpacking was necessary. However, `set_data` accepts a 2D array, or 2 1D arrays. So it doesn't matter. This is just a leftover from previous code. Remove it or leave it, just as you like. – ImportanceOfBeingErnest Apr 30 '18 at 18:20
0

Have you tried using matplotlib with the notebook backend in your Jupyter notebook?

You can do this by adding %matplotlib notebook magic command in a cell at the beginning of your notebook (e.g. right after importing matplotlib)

More info here: http://ipython.readthedocs.io/en/stable/interactive/plotting.html

byouness
  • 1,746
  • 2
  • 24
  • 41
  • I am not familiar with drawnow, maybe this example showing how to update the data in the figure without redrawing the whole figure every time can help you: https://stackoverflow.com/a/34486703/2699660 – byouness Apr 30 '18 at 16:25