Ipywidget not rendering in Binder

Problem

I have a repo which includes a couple of widgets, which are not rendering when launched in Binder.

Background
When I run the notebook(s) locally, the widgets display fine, as in the screenshots:


However, these aren’t rendering when the repo is launched in Binder.
Locally, my system looks like this:

jupyter core     : 4.7.1
jupyter-notebook : 6.3.0
qtconsole        : 5.2.2
ipython          : 7.5.0
ipykernel        : 5.5.5
jupyter client   : 7.1.2
jupyter lab      : 3.0.16
nbconvert        : 6.0.7
ipywidgets       : 7.6.3
nbformat         : 5.1.3
traitlets        : 4.3.3

Question

Any ideas where i’m going wrong?

Binder uses more current infrasctructure and tech than you have in your local system.
Specifically this means…

I think you are using old approaches and haven’t updated to handle newer ipywidgets output handling that the software and tech running via MyBinder needs. Did you not notice the log button turn blue at the bottom when you tried to press your buttons? If you then clicked that blue button at the bottom, you’d see your output is going to the log. Example showing your output in the log at the bottom:

This is symptomatic of not handling out properly. See here.
The good news is this should be a fairly easy update to your code to address this.

Here is one option for making the scenario buttons work again. Starting at the line that reads def click_for_answer(scenario):, replace the code at the bottom of the cell that begins def plot_Watts(): in your functions.ipynb file (I believe it is code cell #14 in functions.ipynb) with the following:

def click_for_answer(scenario):
    scenario_int = int(scenario[-1])
    with outputs[scenario_int]:
        if scenario == "scenario 1":
            plot_Watts()
        elif scenario == "scenario 2":
            plot_Harris()
        elif scenario == "scenario 3":
            plot_Seropian()
        elif scenario == "scenario 4":
            plot_Lerner()
        elif scenario == "scenario 5":
            plot_Taylor()
        elif scenario == "scenario 6":
            plot_Paine()
        
   
def on_button_clicked(b, scenario):
    scenario_int = int(scenario[-1])
    with outputs[scenario_int]:
        click_for_answer(scenario=scenario)
    b.disabled = True  # Disable the button after it has been clicked


def button(scenario):
    button = widgets.Button(
        description='Click for answer',
        disabled=False,
        button_style='',
        tooltip='Button',
        icon='eye'
    )
    button.on_click(lambda b: on_button_clicked(b, scenario))
    return button

# Create an output widget for displaying dynamic content for eachs cenario  button
outputs = [widgets.Output() for x in range(7)]
scenario_1_button = widgets.VBox([button(scenario="scenario 1"),outputs[1]])
scenario_2_button = widgets.VBox([button(scenario="scenario 2"),outputs[2]])
scenario_3_button = widgets.VBox([button(scenario="scenario 3"),outputs[3]])
scenario_4_button = widgets.VBox([button(scenario="scenario 4"),outputs[4]])
scenario_5_button = widgets.VBox([button(scenario="scenario 5"),outputs[5]])
scenario_6_button = widgets.VBox([button(scenario="scenario 6"),outputs[6]])

You’ll see that essentially I’ve added a context manager, the with outputs[scenario_int]: to handle hooking to the notebook where to display output generated by clicking the buttons.
That implementation may be more complex than necessary, but it works to display the results in the notebook and doesn’t make all the plots show in all the scenario button cells output. Because your code is a little more convoluted than running a single the code block and widget in the same celI, I may have missed an easier solution than this.
If other things, such as the chart_picker functions , aren’t working, then based on that you should be able to handle it similarly, I think.

Note that scenario button 5 seems to through an error about ValueError: Could not save to JPEG for display.

Keep in mind given all this:
Developing locally may still work if you implement more modern use of ipywidgets. The possible issue being your old tech & versions may not even support the newer, more thorough approaches.

2 Likes

Thank you so much, this is really useful. I will check the links you provided and try implementing a similar approach for the chart_picker() function.

1 Like