Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jupyter with ipywidgets and plotly v4?

Using Jupyter from Anaconda install on Windows 10; also installed conda install -c plotly plotly, and apparently got Plotly v4.

I just want to start with a simple example - and use ipywidget sliders instead of Plotly ones. So, I've found:

https://moderndata.plot.ly/widgets-in-ipython-notebook-and-plotly/

EXAMPLE 3: interact

A simple example of using the interact decorator from ipywidgets to create a simple set of widgets to control the parameters of a plot.

Link to IPython notebook

Right - so I went to that link, and reorganized the code there into this:

import plotly.graph_objs as go
import numpy as np
from ipywidgets import interact

fig = go.FigureWidget()
scatt = fig.add_scatter()

xs=np.linspace(0, 6, 100)
fig.show()

@interact(a=(1.0, 4.0, 0.01), b=(0, 10.0, 0.01), color=['red', 'green', 'blue'])
def update(a=3.6, b=4.3, color='blue'):
    with fig.batch_update():
        scatt.x=xs
        scatt.y=np.sin(a*xs-b)
        scatt.line.color=color

... and when I run this cell, it draws an empty plot:

jupyter_plotly_fail.png

... and fails with:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
C:\ProgramData\Anaconda3\lib\site-packages\ipywidgets\widgets\interaction.py in update(self, *args)
    254                     value = widget.get_interact_value()
    255                     self.kwargs[widget._kwarg] = value
--> 256                 self.result = self.f(**self.kwargs)
    257                 show_inline_matplotlib_plots()
    258                 if self.auto_display and self.result is not None:

<ipython-input-21-7dcd6b5f2be1> in update(a, b, color)
     12 def update(a=3.6, b=4.3, color='blue'):
     13     with fig.batch_update():
---> 14         scatt.x=xs
     15         scatt.y=np.sin(a*xs-b)
     16         scatt.line.color=color

C:\ProgramData\Anaconda3\lib\site-packages\plotly\basedatatypes.py in __setattr__(self, prop, value)
    349         else:
    350             # Raise error on unknown public properties
--> 351             raise AttributeError(prop)
    352 
    353     def __getitem__(self, prop):

AttributeError: x

Apparently, this is because there were enough changes in Plotly v4 to warrant a Version 4 migration guide | plotly; browsing through that, I tried modifying the code like so:

import plotly.graph_objs as go
import numpy as np
from ipywidgets import interact

fig = go.FigureWidget()
scattf = fig.add_scatter()
scatt = scattf.data[-1]

xs=np.linspace(0, 6, 100)
scattf.show()

@interact(a=(1.0, 4.0, 0.01), b=(0, 10.0, 0.01), color=['red', 'green', 'blue'])
def update(a=3.6, b=4.3, color='blue'):
    with fig.batch_update():
        scatt.x=xs
        scatt.y=np.sin(a*xs-b)
        scatt.line.color=color

... and now I don't get the error anymore - but the plot remains empty, and does not update when I drag the sliders.

Can someone let me know, how can I get this example working, so that a plot is drawn, and updated/redrawn when I drag the slider?


EDIT: messed a bit more, and now I have this code:

import plotly.graph_objs as go
import numpy as np
from ipywidgets import interact

fig = go.FigureWidget()
scattf = fig.add_scatter()
scatt = scattf.data[-1]

xs=np.linspace(0, 6, 100)
#scattf.show() # adds extra plot, if there is scattf.show() in update()!

@interact(a=(1.0, 4.0, 0.01), b=(0, 10.0, 0.01), color=['red', 'green', 'blue'])
def update(a=3.6, b=4.3, color='blue'):
    with fig.batch_update():
        scatt.x=xs
        scatt.y=np.sin(a*xs-b)
        scatt.line.color=color
        scattf.show()

update() # update once; so we don't get empty plot at start? not really - still getting empty plot at start, and another one after which is updated

Two problems here:

  • After running the cell, there is first drawn plot empty, and another one plotted - how can I get it to plot only one plot with the default values? (Without the last update(), there is only one plot, but empty at start - and have to drag a slider to have it start drawing)
  • Plot now changes when dragging the sliders - but it flickers a lot; any way to reduce the flicker?
like image 624
sdbbs Avatar asked Jan 18 '26 13:01

sdbbs


2 Answers

Right, so found Interactive Data Analysis with FigureWidget ipywidgets - and rewrote the example accordingly; this has much smoother response, and no double draws - however, I'm still not sure if this is the way to do it; so if anyone knows better, please post ...

import plotly.graph_objs as go
import numpy as np
#from ipywidgets import interact, interactive
from ipywidgets import widgets
from IPython.display import display

aSlider = widgets.FloatSlider(
    value=2.0,
    min=1.0,
    max=4.0,
    step=0.01,
    description='a:',
    continuous_update=False
)

bSlider = widgets.FloatSlider(
    value=1.0,
    min=0.0,
    max=10.0,
    step=0.01,
    description='b:',
    continuous_update=True
)

colorDropdown = widgets.Dropdown(
    description='Color:',
    value='blue',
    options=['red', 'blue', 'green']
)

fig = go.FigureWidget()
#fig.show()
scattf = fig.add_scatter()
scatt = scattf.data[-1]

xs=np.linspace(0, 6, 100)

def response(change):
    with fig.batch_update():
        fig.data[0].x=xs
        fig.data[0].y=np.sin(aSlider.value*xs-bSlider.value)
        fig.data[0].line.color=colorDropdown.value
        fig.layout.xaxis.title = 'whatever'

aSlider.observe(response, names="value")
bSlider.observe(response, names="value")
colorDropdown.observe(response, names="value")

response("doesn't matter what I send here, just triggering") # MUST be before widgets.VBox - if response(x) is last, NOTHING is drawn! 

widgets.VBox([aSlider,
              bSlider,
              colorDropdown,
              fig])
like image 141
sdbbs Avatar answered Jan 21 '26 03:01

sdbbs


In Jupyter notebook or JupyterLab environments you can do like this:

import numpy as np
import plotly.graph_objects as go
from ipywidgets import interact

xs=np.linspace(0, 6, 100)

fig = go.FigureWidget()
fig.add_scatter()

@interact(a=(1.0, 4.0, 0.01), b=(0, 10.0, 0.01), color=['red', 'green', 'blue'])
def update(a=3.6, b=4.3, color='blue'):
    with fig.batch_update():
        fig.data[0].x=xs
        fig.data[0].y=np.sin(a*xs-b)
        fig.data[0].line.color=color
fig

enter image description here

like image 45
Sandu Ursu Avatar answered Jan 21 '26 03:01

Sandu Ursu



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!