ipycytoscape icon indicating copy to clipboard operation
ipycytoscape copied to clipboard

Flickering when using as widget

Open cvanelteren opened this issue 4 years ago • 13 comments

I am trying to animate a graph using ipywidgets but the output is flickering.

Is there a native way to embed the widget in ipywidgets? I am trying to figure it out from the docs, but they seem to be incomplete. The CytoscapeWidget has a callback to widgets, perhaps you can send me in the right direction?

from ipycytoscape import CytoscapeWidget
import networkx as nx
class Visualizer:
    def __init__(self, graph):
        self.graph = graph
        self.widget= CytoscapeWidget()
        self.widget.graph.add_graph_from_networkx(graph)
        self.update_nodes()
        style = [
        dict(selector = 'node',
              css = {
                  "background-color": "data(color)",
                  "text-outline-width" : 10
                    }),
        dict(selector = ':selected',
            css = {"background-color" : 'red',
                   "line-color" : "black",
                   "source-arrow-color" : "yellow",
                   "target-arrow-color" : "purple"})]
        self.widget.set_style(style)
    def update_nodes(self, data = None):
        if data:
            for idx, c in enumerate(data):
                node = self.widget.graph.nodes[idx]
                node.data['color'] = c
        else:
            for node in self.widget.graph.nodes:
                if np.random.rand() < .5:
                    node.data['color'] = 'red'  
                else:
                    node.data['color'] = 'blue'

g = nx.complete_graph(10)
v = Visualizer(g)
ts = iw.IntSlider(min = 0, max = 10, step = 1)
print(iw.widgets.interaction.__file__)
def callback(*args, **kwargs):
    kwargs.get('x')
    v.update_nodes()
display(v.widget)
plot = iw.interactive(callback, x = ts)
plot

cvanelteren avatar Oct 19 '20 10:10 cvanelteren

Hey @cvanelteren thanks for the issue! :) Will have a look at it soon.

marimeireles avatar Oct 20 '20 09:10 marimeireles

hi thanks for the reply. Just naively, I believe the issue is that the whole widget is being redrawn. Let me know if I can help!

cvanelteren avatar Oct 20 '20 20:10 cvanelteren

Hey @cvanelteren so, I'm about to merge a PR that will fix your issue. I tested the following code:

from ipycytoscape import CytoscapeWidget
import numpy as np
import networkx as nx
import ipywidgets as iw
class Visualizer:
    def __init__(self, graph):
        self.graph = graph
        self.widget= CytoscapeWidget()
        self.widget.graph.add_graph_from_networkx(graph)
        self.update_nodes()
        style = [
        dict(selector = 'node',
              css = {
                  "background-color": "data(color)",
                  "text-outline-width" : 10
                    }),
        dict(selector = ':selected',
            css = {"background-color" : 'red',
                   "line-color" : "black",
                   "source-arrow-color" : "yellow",
                   "target-arrow-color" : "purple"})]
        self.widget.set_style(style)
    def update_nodes(self, data = None):
        if data:
            for idx, c in enumerate(data):
                node = self.widget.graph.nodes[idx]
                node.data['color'] = c
        else:
            for node in self.widget.graph.nodes:
                if np.random.rand() < .5:
                    node.data['color'] = 'red'  
                else:
                    node.data['color'] = 'blue'

g = nx.complete_graph(10)
v = Visualizer(g)
ts = iw.IntSlider(min = 0, max = 10, step = 1)
print(iw.widgets.interaction.__file__)
def callback(*args, **kwargs):
    kwargs.get('x')
    v.update_nodes()
display(v.widget)
plot = iw.interactive(callback, x = ts)
plot

But I think it will work with yours too. If you need, I can release a new version of ipycytoscape now, do you? I think this is a cool example to have in the docs of how to use ipycytoscape as a widget, please feel free to add it to the docs =)

marimeireles avatar Oct 21 '20 19:10 marimeireles

Just naively, I believe the issue is that the whole widget is being redrawn. Let me know if I can help!

@cvanelteren you're spot on with the diagnosis. I think there are actually two redraws happening.

  1. Becuase you use interactive ipywidgets will redraw the output
    • instead I would do: ts.observe(callback, names='value')
  2. ipycytoscape was redrawing the graph every time
    • fixed by https://github.com/QuantStack/ipycytoscape/pull/109

ianhi avatar Oct 21 '20 20:10 ianhi

Thanks for the fix. I pulled the repo, however no my widget stopped working altogether with: Error displaying widget: model not found

The extension is enabled:

JupyterLab v2.2.6
Known labextensions:
   app dir: /home/casper/miniconda3/share/jupyter/lab
        @axlair/jupyterlab_vim v0.12.4  enabled  OK
        @jupyter-widgets/jupyterlab-manager v2.0.0  enabled  OK
        jupyter-cytoscape v1.0.4  enabled  OK
        jupyter-matplotlib v0.7.4  enabled  OK
        jupyterlab-dash v0.3.0  enabled  OK
        jupyterlab-plotly v4.11.0  enabled  OK
        plotlywidget v4.11.0  enabled  OK
        vispy v0.3.0  enabled  OK

cvanelteren avatar Oct 22 '20 00:10 cvanelteren

@cvanelteren How'd you install the the pulled extension? You need to follow the full instructions here: https://ipycytoscape.readthedocs.io/en/latest/develop-install.html

pip install .
jupyter labextension install .

ianhi avatar Oct 22 '20 00:10 ianhi

I installed initially using the extension manager. I tried reinstalling it using:

  • jupyter labextension uninstall jupyter-cytoscape
  • jupyter labextension install . Produces error log with `Error: Cannot find module 'jupyter-cytoscape/package.json'. Through nbextension it install but error persists. Pretty odd.

cvanelteren avatar Oct 22 '20 01:10 cvanelteren

Weird, what directory are you running those commands from?

Perhaps starting from scratch will help. (at worst make a new conda env) I would try the following:

pip uninstall ipycytoscape
jupyter labextension uninstall jupyter-cytoscape
git clone https://github.com/QuantStack/ipycytoscape.git
cd ipycytoscape
pip install .
jupyter labextension install .

ianhi avatar Oct 22 '20 01:10 ianhi

I tried that too. Same error: cat /tmp/jupyterlab-debug-gsea1xwh.log | egrep "Error" Error: Cannot find module 'jupyter-cytoscape/package.json' raise RuntimeError(msg) RuntimeError: JupyterLab failed to build

cvanelteren avatar Oct 22 '20 01:10 cvanelteren

Ok I torched my env and reinstalled it. All is good now. Update looks good! Also saves the layout thanks a bundle!

cvanelteren avatar Oct 22 '20 02:10 cvanelteren

Working on a different computer the flickering has returned on the latest master version. I notice 2 draws for every slider update above.

Environment

jupyter core     : 4.7.0
jupyter-notebook : 6.1.5
qtconsole        : not installed
ipython          : 7.19.0
ipykernel        : 5.3.4
jupyter client   : 6.1.7
jupyter lab      : 3.0.0rc10
nbconvert        : 6.0.7
ipywidgets       : 7.5.1
nbformat         : 5.0.8
traitlets        : 5.0.5
nbextensions

Known nbextensions:
  config dir: /home/casper/.jupyter/nbconfig
    notebook section
      jupyter-cytoscape/extension  enabled 
      - Validating: OK
      jupyter-js-widgets/extension  enabled 
      - Validating: OK
  config dir: /home/casper/miniconda3/etc/jupyter/nbconfig
    notebook section
      jupyter-cytoscape/extension  enabled 
      - Validating: OK
      jupyter-matplotlib/extension  enabled 
      - Validating: OK
      jupyter-js-widgets/extension  enabled 
      - Validating: OK

cvanelteren avatar Nov 27 '20 09:11 cvanelteren

We have to add this to our test routine somehow... Do you know more precisely when it happened @cvanelteren it'd help to track the problem. Thanks for the update.

marimeireles avatar Nov 27 '20 09:11 marimeireles

On this machine 3.0.0rc10 is running of jupyterlab, the ipycytoscape was installed using the latest master branch. Under jupyterlab, the update seems to be blitted but flicker (2x draw it seems) when a change is detected. In the example of above, if one were to keep the colors the same for every slider update, no flickering will occur.

cvanelteren avatar Nov 27 '20 13:11 cvanelteren