0

I'm building a bot which fetches data from the internet every 30 seconds.

I want to plot this data using matplotlib and be able to update the graphs when I fetch some new one.

At the beginning of my script I initialise my plots. Then I run a function to update these plots every 30 seconds, but my plot window freezes at this moment.

I've done some research but can't seem to find any working solution:

plt.show(block=False)
plt.pause(0.001)

What am I doing wrong ?

General structure of the code:

import matplotlib.pyplot as plt
import time

def init_plots():
    global fig
    global close_line

    plt.ion()
    fig = plt.figure()
    main_fig = fig.add_subplot(111)

    x = [datetime.fromtimestamp(x) for x in time_series]
    close_line, = main_fig.plot(x, close_history, 'k-')
    plt.draw()


def update_all_plots():
    global close_line

    x = [datetime.fromtimestamp(x) for x in time_series]

    close_line.set_xdata(time_series)
    close_line.set_ydata(close_history)

    plt.draw()


# SCRIPT :
init_plots()
while(True):
     # Fetch new data...
     # Update time series...
     # Update close_history...
     update_plots()
     time.sleep(30)
ypicard
  • 3,593
  • 3
  • 20
  • 34

2 Answers2

3

There is a module in matplotlib for specifically for plots that change over time: https://matplotlib.org/api/animation_api.html

Basically you define an update function, that updates the data for your line objects. That update function can then be used to create a FuncAnimation object which automatically calls the update function every x milliseconds:

ani = FuncAnimation(figure, update_function, repeat=True, interval=x)
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
Johannes
  • 3,300
  • 2
  • 20
  • 35
  • Thanks for your reply. Am I supposed to plot the graph on another thread so that my main script can continue without being blocked by the plot ? – ypicard Jun 30 '17 at 23:47
  • The only blocking part of the plotting is the `plt.show()` function. I usually start a separate thread that feeds data into the plot and then call `plt.show()` from my main script. So my main script blocks until the plot gets closed, but the data source keeps feeding data. But I guess you can make the main script non-blocking if you enable interactive mode: https://matplotlib.org/faq/usage_faq.html#what-is-interactive-mode – Johannes Jul 01 '17 at 12:49
  • And how do i keep my plot unfrozen while my python script sleeps (with time.sleep(x)) ? – ypicard Jul 01 '17 at 13:27
1

There is a simple way to do it, given a panda dataframe . You would usually do something like this to draw(df is dataframe) :

ax = df.plot.line()

Using

df.plot.line(reuse_plot=True,ax=ax)

one can reuse the same figure to redraw it elegantly and probably fast enough.

Possibly duplicate of Matplotlib updating live plot

user2679290
  • 144
  • 9