Ask Your Question
2

Interact layout in Jupyter-Notebook

asked 2019-07-10 16:50:07 -0500

eocansey gravatar image

updated 2019-07-11 10:27:05 -0500

Iguananaut gravatar image

When I run this code

@interact(layout=dict(top=[['f', 'color']], 
left=[['axes'],['fill']], 
bottom=[['zoom']]))
def _(f=input_box(x^2,width=20), 
color=color_selector(widget='colorpicker', label=""),
axes=True,
fill=True,
zoom=range_slider(-3,3, default=(-3,3))):
    show(plot(f,(x,zoom[0], zoom[1]), color=color, axes=axes,fill=fill))

in Jupyter notebook, the controls are not organised as specified. But this is not so with the old SageNB notebook. How can I make the controls specified in the layout parameter to appear in the output as originally specified? Please advise.

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
2

answered 2019-07-11 11:09:00 -0500

Iguananaut gravatar image

updated 2019-07-11 11:11:09 -0500

Looks like this is an open issue, opened as of two years ago with no progress: https://trac.sagemath.org/ticket/22663 (perhaps another reason there shouldn't be such a rush to deprecate SageNB, but it's a little late for that now...) Custom Jupyter Widgets do allow extensive layout customization but perhaps not in a way that's been integrated with or is fully backwards-compatible with the old Sage @interact decorator. This is because in the Jupyter notebook it's using the interact provided by ipywidgets(https://ipywidgets.readthedocs.io/en/...)

It seems the easiest way to control widget layout is to manually create the individual widgets and wrap them in HBox and VBox widgets. It would also be really nice to be able to use Layout Templates though those are rather new, in the latest ipywidgets, which is not in Sage yet. So with what I have, I was able to do something I think close to what you're trying to get:

(Note: I renamed the actual function for the interact ff so I could access its widget attribute)

Obviously this is still a bit ugly. Part of that is because I lazily re-used the widget elements that were automatically created by the original @interact call. I could either not do that and re-create the individual widgets myself. Or you an play around with adjusting their existing layout attributes. After some experimentation I wound up with

top = HBox(ff.widget.children[:2])
left = VBox(ff.widget.children[2:4])
mid = HBox([left, ff.widget.children[5]])
bottom = ff.widget.children[4]
app = VBox([top, mid, bottom])

for w in app.children:
    w.layout.width = '100%'

for w in top.children:
    w.layout.width = '50%'

for w in left.children:
    w.layout.width='98%'

mid.children[0].width='20%'
mid.children[1].width='80%'

bottom.layout.width='99%'

app

Which gave me:

Which is a little nicer (some of the widths aren't exactly 100%, since I found that if I made it 100% my browser would add annoying scroll bars).

Alas, none of this is as nice as the old @interact(layout=...) for tutorial purposes...

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2019-07-10 16:49:30 -0500

Seen: 51 times

Last updated: Jul 11