jupyter-widgets / ipywidgets

Interactive Widgets for the Jupyter Notebook
https://ipywidgets.readthedocs.io
BSD 3-Clause "New" or "Revised" License
3.13k stars 950 forks source link

Complex Dashboards & Dynamic Controls in the Docs #1818

Open ixxie opened 6 years ago

ixxie commented 6 years ago

The ipywidgets documentation - in particular the widget events section - gives several helpful examples of how to link widgets. Unfortunately these examples are restricted to relatively simple usecases, and do not clarify how to create complex dashboards. In particular, it is not clear from the documentation how to make multiple widgets dynamically reshape the controls as well as the output of the dashboard.

@jasongrout helped me out in the Jupyter-widgets Gitter channel with the following illuminating example:

from IPython.display import display
import ipywidgets as widgets

class ModelUI:

    def __init__(self):
        self.d1 = widgets.Dropdown(options=["a", "b", "c"])
        self.d2 = widgets.Dropdown(options=[1,2,3])
        self.controls = widgets.VBox()
        self.UI = widgets.HBox([widgets.VBox([self.d1,self.d2]), self.controls])

        self.d1.observe(self.makeUI, "value")
        self.d2.observe(self.makeUI, "value")
        self.makeUI(None)

    def makeUI(self, change):
        # here we use d1 and d2 as global variables, and 
        # ignore what the actual specific change was
        if self.d1.value=="a" and self.d2.value==1:
            self.controls.children = (widgets.IntSlider(), widgets.IntSlider(), widgets.Text())
        elif self.d1.value=="b":
            self.controls.children = (widgets.Text(),)
        else:
            self.controls.children = (widgets.FloatSlider(),)

    def _ipython_display_(self):
        display(self.UI)

ModelUI()

It would be helpful to have a section in the documentation with methods, tools and design patterns for creating more complex dashboards. Most of all, examples of complex dashboards would be incredibly illuminating. In the coming weeks I will try and implement some real examples of the above pattern, and hopefully submit some PRs myself, but in the meantime I obliged @jasongrout's request and posted this issue.

jasongrout commented 6 years ago

Thanks!

ixxie commented 6 years ago

I now created a stackoverflow question corresponding to this issue.

KennethGrimes commented 1 year ago

I am also extremely interested in having some documentation regarding creating complex GUIs with Jupyter. As anything happened since publication of OP 5 years ago? Could you provide some explanation on the rationale for the code being structured that way?

maartenbreddels commented 1 year ago

During our last ipywidget workshop, we discussed this, and IIRC we all wanted to have something in the docs about this topic.

My short answer is, building UI's is difficult, and I've written a bit about this at https://github.com/jupyter-widgets/ipywidgets/issues/3348#issuecomment-1081573899

There, I talk about react-ipywidgets, which we now call Reacton, and I think this is the best solution thus far for building more complex UI's using ipywidgets.

I recently published an article about this, in case you are interested in a longer read: https://maartenbreddels.medium.com/advance-your-ipywidget-app-development-with-reacton-6734a5607d69

I hope this answers your question.

KennethGrimes commented 1 year ago

Hi Maarten, thanks for your reply.

Reacton looks really promising, but the trouble for me is that I need to host my notebook on an University server running JupyterHub, and the university server has "only" the standard anaconda packages, and I expect a lot of bureaucracy after asking them to install a new library for me.

After browsing through the galleries linked in issue #3348, I realize that I don't need such fancy dashboards, but an "intermediate" GUI, a little more complicated than single controls but not so complex either. What I had in mind is some top-down guidance on how to write the code for a GUI like for instance this one to set the parameters of a Gompertz curve https://en.wikipedia.org/wiki/Gompertz_function :

image

On the left there are three sliders to set the values of a, b and c and on the right the corresponding Gompertz curve is drawn with plotly (I personally prefer plotly instead of matplotlib because it has hovering per default). With some guidance (I'm mechanical and not software engineer) I could write the tutorial myself :)

maartenbreddels commented 1 year ago

That sounds like the perfect use case for https://ipywidgets.readthedocs.io/en/stable/examples/Using%20Interact.html hope that is a better fit for you now.

jasongrout commented 1 year ago

For example: https://stackoverflow.com/a/58862658

Or to better match your layout:

from IPython.display import display
import ipywidgets

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

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

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

update()

# Generate widgets and hook them up to the update function
w = ipywidgets.interactive(update, a=(1.0, 4.0, 0.01), b=(0, 10.0, 0.01), color=['red', 'green', 'blue'])

from ipywidgets import HBox, VBox
display(HBox([VBox(w.children[0:-1]), fig]))