question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

blitting doesn't work - would be useful to speed up graph draw for faster realtime-graphs

See original GitHub issue

I have the following code in jupyterlab. This allows me to move a slider and update a graph in realtime. However the framerate is quite low (1fps) if I call fig.canvas.draw(). I therefore tried blitting, however it does not seem to affect the graph. Is this supposed to work with ipympl?

Many thanks for your help.

Environment: Jupyterlab==1.2.6 ipympl==0.5.6 jupyter labextension list:

@ibqn/jupyterlab-codecellbtn v0.1.3 enabled ok @jupyter-widgets/jupyterlab-manager v1.1.0 enabled ok @jupyterlab/google-drive v1.0.0 enabled ok @jupyterlab/toc v1.0.1 enabled ok jupyter-matplotlib v0.7.2 enabled ok jupyterlab-plotly v1.5.2 enabled ok plotlywidget v1.5.2 enabled ok

import pandas as pd, numpy as np
import time
import matplotlib.pyplot as plt

from ipywidgets import interact, interactive, fixed, interact_manual, Layout, VBox, HBox
import ipywidgets as widgets

from itertools import count
%matplotlib widget


blit = False # False works, True doesn't.

plt.close('all')
plt.ioff()

output = widgets.Output(layout={'width': '700px', 'height': '300px'})
fig, axs= plt.subplots(3, 2, figsize=(10, 8), sharex=True)
fig.canvas.header_visible = False
fig.canvas.toolbar_visible = False


for i in range(3):    
    axs[i,0].set_ylim(-1.5,1.5)
    axs[i,0].set_xlim(0,20)
    
# index giver
x_value = count()

# expanding dataset
x, y = [], []

# initialise dummy data
[x.append(next(x_value)) for i in range(2)]
[y.append([1]*3) for i in range(2)]

# setup desired and actual angle plots
col_names = ['col1', 'col2', 'col3']
ax_df = pd.DataFrame(index=x,columns=col_names, data=y).plot(subplots=True, ax=axs[:,0])

if blit:
    bgs = []
    for ax in ax_df:
        # cache the background
        ax_background = fig.canvas.copy_from_bbox(ax.bbox)
        bgs.append(ax_background)
    
    fig.canvas.draw()  # initial draw required

# monitor framerate
t_start = time.time()   

# event handler
def on_value_changed(change):    
    with output:    
        next_x = next(x_value) # generate next x axis value
        x.append(next_x)
        y.append([change.new]*3) 

        for i in range(3):            
            if blit:              
                # update data
                line = ax_df[i].get_lines()[0]
                line.set_data(x, pd.DataFrame(y).iloc[:,i])
                
                # restore background
                fig.canvas.restore_region(bgs[i])
                
                # redraw just the points
                ax_df[i].draw_artist(line)

                # fill in the axes rectangle
                fig.canvas.blit(ax_df[i].bbox)
                
            else:
                # update data
                ax_df[i].get_lines()[0].set_data(x, pd.DataFrame(y).iloc[:,i])

                # rescale view
                ax_df[i].autoscale_view(None,'x',None)
                ax_df[i].relim()
            
        fig.canvas.flush_events()
        
        if not blit:
            fig.canvas.draw() # this slows down framerate, not required for blit

        print(f"FPS: {round(next_x/(time.time() - t_start),2)}", end=", ")

sliders = []
int_slider = widgets.FloatSlider(description="test", 
                                 min=-1, max=1, 
                                 value = 0, continuous_update=True,
                                 orientation="horizontal",                                      
                                 layout=widgets.Layout(width="500px", height="20px"))    
int_slider.observe(on_value_changed, names="value")
sliders = widgets.VBox([int_slider, fig.canvas, output])
display(sliders)


Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:8

github_iconTop GitHub Comments

3reactions
ianhicommented, Dec 3, 2020
1reaction
ianhicommented, Dec 2, 2020

indeed. I’ve since learned that for this backend draw_idle just calls draw so I was apparently fooling myself with the placebo effect before.

Since ipympl inherits most of it’s functionality from the WebAgg backend from core matplotlib I suspect that the path getting working blitting is for this PR to be moved forward: https://github.com/matplotlib/matplotlib/pull/9240

(though I could be totally wrong about that)

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to enable matplotlib blitting to create fast realtime graph ...
The issue seems to originate from the implementation of matplotlib backend "webagg" used by default in jupyter lab (e.g. when using the ...
Read more >
Faster rendering by using blitting - Matplotlib
Blitting speeds up repetitive drawing by rendering all non-changing graphic elements into a background image once. Then, for every draw, only the changing ......
Read more >
Speeding up Matplotlib - Bastibe.de
I am using pause() here to update the plot without blocking. The correct way to do this is to use draw() instead, but...
Read more >
Graph Sensor Data with Python and Matplotlib - SparkFun Learn
Speeding Up the Plot Animation. Clearing a graph and redrawing everything can be a time-consuming process (at least in terms of computer time)....
Read more >
Faster graphing for a GUI? : r/Python - Reddit
I tried enabling the 'blit' feature, but it screws up the drawing ... Once I can get my random data working at a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found