4

I am trying to make interactive sliders with ipywidgets on jupyter notebook to change the data of a plot when a user changes a slider Widget, which is simple and we can find example codes easily. The problem that I have is twofold: 1) when there are many parameters (= variables,sliders) in my function to be displayed, sliders are vertically arranged so that it is getting hard to control them without scrolling the jupyter page. Is there any way to arrange sliders as I wish like m by n grid? 2) To pass a large number of integer-/float-valued sliders, I made a single dictionary to be passed to the function interactive. Here, the key (=slider/variable/parameter) names are displayed seemingly in random order. I tried to pass the dictionary after sorting by the key names beforehand, but it does not still resolve the issue.

I'd appreciate it if you can share any ideas.

def myfun(**var_dict):
    v = [value for value in var_dict.values()]
    return np.sum(v)

var_dict = {'var1':1,'var2':2,'var3':3,'var4':4}
w = interactive(myfun,**var_dict)
display(w)

ipywidgets interactive sliders

  • consider using an [ordered dict](https://docs.python.org/2/library/collections.html#collections.OrderedDict)? – nluigi Jun 05 '16 at 13:06
  • I tried OrderedDict, but did not work possibly because Python’s function call semantics pass-in keyword arguments using a regular unordered dictionary. – Kijung Yoon Jun 07 '16 at 15:04

1 Answers1

4

You will not be able to solve this using **kwargs. As stated in PEP468 "The only reason they [keyword arguments] don't work is because the interpreter throws that ordering information away." "Starting in version 3.5 Python will preserve the order of keyword arguments as passed to a function"

So if you want to get this behavior you should either: name your arguments when you use 'interactive':

from ipywidgets import interactive
from IPython.display import display
import numpy as np
def myfun(**kwargs):
    return np.sum(list(kwargs.itervalues()))
w=interactive(myfun,var1=1,var2=2,var3=3,var4=4)
display(w)

or, if you really want to use a dict, as far as I know, the best is to build the widgets yourself, without the use of 'interactive'. You could do this this way:

from IPython.display import display,clear_output
from ipywidgets import widgets
from collections import OrderedDict
var_dict = OrderedDict([('var1',1),('var2',2),('var3',3),('var4',4)])

def myfct(change,list_widgets):
    clear_output()
    print np.sum([widget.value for widget in list_widgets])

list_widgets=[]

# create the widgets
for name,value in var_dict.iteritems():
    list_widgets.append(widgets.IntSlider(value=value,min=value-2,max=value+2,description=name))

# link the widgets with the function
for widget in list_widgets:
    widget.observe(lambda change:myfct(change,list_widgets),names='value',type='change')

# group the widgets into a FlexBox
w = widgets.VBox(children=list_widgets)

# display the widgets
display(w)

Enjoy :-)

sweetdream
  • 1,321
  • 15
  • 16
  • Option 1 ("name your arguments when you use `interactive`") does not reliably work for me when using python 3.5.2, IPython 5.1.0 and ipywidgets 5.2.2. After restarting the Kernel of the jupyter notebook the order of widgets also changes seemingly randomly. – Fabian Rost Jan 03 '17 at 13:41