Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Plot dynamically changing graph using matplotlib in Jupyter Notebook

I have a M x N 2D array: ith row represents that value of N points at time i.

I want to visualize the points [1 row of the array] in the form of a graph where the values get updated after a small interval. Thus the graph shows 1 row at a time, then update the values to next row, so on and so forth.

I want to do this in a jupyter notebook. Looking for reference codes.

I tried following things but no success:

  • http://community.plot.ly/t/updating-graph-with-new-data-every-100-ms-or-so/812

  • https://pythonprogramming.net/live-graphs-matplotlib-tutorial/

  • Create dynamic updated graph with Python

  • Update Lines in matplotlib

like image 252
Anuj Gupta Avatar asked Sep 23 '16 10:09

Anuj Gupta


People also ask

How do I make matplotlib dynamic?

To dynamically update plot in Python matplotlib, we can call draw after we updated the plot data. to define the update_line function. In it, we call set_xdata to set the data form the x-axis. And we call set_ydata to do the same for the y-axis.

What is the currently correct way to dynamically update plots in Jupyter IPython?

What is the currently correct way to dynamically update plots in Jupyter/iPython? We can first activate the figure using plt. ion() method. Then, we can update the plot with different sets of values.

Does matplotlib have interactive plots?

But did you know that it is also possible to create interactive plots with matplotlib directly, provided you are using an interactive backend?


2 Answers

Here's an alternative, possibly simpler solution:

%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()     ax.plot(matrix[i,:])     fig.canvas.draw() 
like image 86
Graham S Avatar answered Sep 19 '22 13:09

Graham S


I had been particularly looking for a good answer for the scenario where one thread is pumping data and we want Jupyter notebook to keep updating graph without blocking anything. After looking through about dozen or so related answers, here are some of the findings:

Caution

Do not use below magic if you want a live graph. The graph update does not work if the notebook uses below:

%load_ext autoreload %autoreload 2 

You need below magic in your notebook before you import matplotlib:

%matplotlib notebook 

Method 1: Using FuncAnimation

This has a disadvantage that graph update occurs even if your data hasn't been updated yet. Below example shows another thread updating data while Jupyter notebook updating graph through FuncAnimation.

%matplotlib notebook  from matplotlib import pyplot as plt from matplotlib.animation import FuncAnimation from random import randrange from threading import Thread import time  class LiveGraph:     def __init__(self):         self.x_data, self.y_data = [], []         self.figure = plt.figure()         self.line, = plt.plot(self.x_data, self.y_data)         self.animation = FuncAnimation(self.figure, self.update, interval=1000)         self.th = Thread(target=self.thread_f, daemon=True)         self.th.start()      def update(self, frame):         self.line.set_data(self.x_data, self.y_data)         self.figure.gca().relim()         self.figure.gca().autoscale_view()         return self.line,      def show(self):         plt.show()      def thread_f(self):         x = 0         while True:             self.x_data.append(x)             x += 1             self.y_data.append(randrange(0, 100))                time.sleep(1)    g = LiveGraph() g.show() 

Method 2: Direct Update

The second method is to update the graph as data arrives from another thread. This is risky because matplotlib is not thread safe but it does seem to work as long as there is only one thread doing updates.

%matplotlib notebook  from matplotlib import pyplot as plt from matplotlib.animation import FuncAnimation from random import randrange from threading import Thread import time  class LiveGraph:     def __init__(self):         self.x_data, self.y_data = [], []         self.figure = plt.figure()         self.line, = plt.plot(self.x_data, self.y_data)          self.th = Thread(target=self.thread_f, daemon=True)         self.th.start()      def update_graph(self):         self.line.set_data(self.x_data, self.y_data)         self.figure.gca().relim()         self.figure.gca().autoscale_view()      def show(self):         plt.show()      def thread_f(self):         x = 0         while True:             self.x_data.append(x)             x += 1             self.y_data.append(randrange(0, 100))                self.update_graph()              time.sleep(1)     from live_graph import LiveGraph  g = LiveGraph() g.show() 
like image 40
Shital Shah Avatar answered Sep 20 '22 13:09

Shital Shah