3

I'm trying to control the display of a scatter plot with a checkbox. When I built it using the interact function it worked as expected. The plot was shown or hidden based on the value in the checkbox.

import matplotlib.pyplot as plt
from ipywidgets import interact, widgets
%matplotlib inline

def on_change(Display):
    if Display == True:
        plt.scatter(x,y)
        plt.show()  
    return Display

interact(on_change, Display=False);

When I tried to do the same thing using the observe function every time I clicked on the checkbox I get an additional plot displayed below. What do I need to do to get it to redraw the same plot so it works like the example above?

I suppose something in the interact example is clearing the display but it's not clear how to do this manually.

import matplotlib.pyplot as plt
from ipywidgets import interact, widgets
%matplotlib inline

x = [1,2,3,4,5,6,7,8]
y = [5,2,4,2,1,4,5,2]

def on_change(change):
    if change['new'] == True:
        scat = plt.scatter(x,y)
        plt.show()   

cb = widgets.Checkbox(False, description = "Display")
cb.observe(on_change, names='value')
display(cb)
ibli
  • 31
  • 2

1 Answers1

1

A couple of alterations I made to your example to hopefully demonstrate what you want. I have taken a more object-oriented route, not sure if you specifically wanted to avoid it but it helps achieve your desired outcome, it seems like you are moving towards a simple GUI here.

1) Include an Output widget (out) - basically a cell output which you can display like a normal widget. You can use a context manager block (with out:) when you want to print to that specific output widget. You can also clear the widget with out.clear_output()

2) Use the object oriented interface in matplotlib rather than using plt. I find this easier to control which plots are displayed and in which location at the right times.

  • temporarily suspend the interactive matplotlib with plt.ioff()
  • Create your figure and axis with fig, ax = plt.subplots(). NB figures can have multiple axes/subplots but we only need one.
  • 'plot' the scatter data to your axis using ax.scatter(x,y), but this won't cause it to appear.
  • Explicitly display the figure with display(fig).

I'm assuming you want your figure to be replotted each time you check the box, so I have included it in the observe function. If your figure doesn't change, it would make sense to move it outside of the loop.


import matplotlib.pyplot as plt
from ipywidgets import interact, widgets
%matplotlib inline

out = widgets.Output()

x = [1,2,3,4,5,6,7,8]
y = [5,2,4,2,1,4,5,2]

def on_change(change):
    if change['new'] == True:
        with out:
            plt.ioff()
            fig,ax = plt.subplots()
            ax.scatter(x,y)
            display(fig)
    else:
        out.clear_output()

cb = widgets.Checkbox(False, description = "Display")
cb.observe(on_change, names='value')
display(cb)
display(out)
ac24
  • 5,325
  • 1
  • 16
  • 31