3

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?
1
  • In my understanding, you don't call .show on a plotly FigureWidget. Instead, you evaluate it in the last line of the cell. I.e., the last line of the cell has to be fig. You also don't need .update at all, the figure is updated as soon as its properties have changed (unless batched by with fig.batch_update():). Commented Feb 6, 2020 at 21:56

2 Answers 2

3

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])
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for this. It's crazy that Python gets to parade around as the premier tool for data science when the libraries and support for doing something as fundamental as this require several days of crafting the perfect stackoverflow search query to find your solution.
3

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

2 Comments

Your code works, in contrast to the OP's attempts, because you evaluate fig in the last line of the cell.
Is there a way to export both the plotly plot and the ipywidget sliders into an html file (as javascript) (from plotly.offline import plot)?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.