def interactive(__interact_f, **kwargs): """Build a group of widgets to interact with a function.""" f = __interact_f co = kwargs.pop('clear_output', True) kwargs_widgets = [] container = Box() container.result = None container.args = [] container.kwargs = dict() kwargs = kwargs.copy() new_kwargs = _find_abbreviations(f, kwargs) # Before we proceed, let's make sure that the user has passed a set of args+kwargs # that will lead to a valid call of the function. This protects against unspecified # and doubly-specified arguments. getcallargs(f, **{n: v for n, v, _ in new_kwargs}) # Now build the widgets from the abbreviations. kwargs_widgets.extend(_widgets_from_abbreviations(new_kwargs)) # This has to be done as an assignment, not using container.children.append, # so that traitlets notices the update. We skip any objects (such as fixed) that # are not DOMWidgets. c = [w for w in kwargs_widgets if isinstance(w, DOMWidget)] container.children = c # Build the callback def call_f(name, old, new): container.kwargs = {} for widget in kwargs_widgets: value = widget.value container.kwargs[widget.description] = value if co: clear_output(wait=True) try: container.result = f(**container.kwargs) except Exception as e: ip = get_ipython() if ip is None: container.log.warn("Exception in interact callback: %s", e, exc_info=True) else: ip.showtraceback() # Wire up the widgets for widget in kwargs_widgets: widget.on_trait_change(call_f, 'value') container.on_displayed(lambda _: call_f(None, None, None)) return container
def interactive(__interact_f, **kwargs): """Build a group of widgets to interact with a function.""" f = __interact_f co = kwargs.pop('clear_output', True) kwargs_widgets = [] container = Box() container.result = None container.args = [] container.kwargs = dict() kwargs = kwargs.copy() new_kwargs = _find_abbreviations(f, kwargs) # Before we proceed, let's make sure that the user has passed a set of args+kwargs # that will lead to a valid call of the function. This protects against unspecified # and doubly-specified arguments. getcallargs(f, **{n:v for n,v,_ in new_kwargs}) # Now build the widgets from the abbreviations. kwargs_widgets.extend(_widgets_from_abbreviations(new_kwargs)) # This has to be done as an assignment, not using container.children.append, # so that traitlets notices the update. We skip any objects (such as fixed) that # are not DOMWidgets. c = [w for w in kwargs_widgets if isinstance(w, DOMWidget)] container.children = c # Build the callback def call_f(name, old, new): container.kwargs = {} for widget in kwargs_widgets: value = widget.value container.kwargs[widget.description] = value if co: clear_output(wait=True) try: container.result = f(**container.kwargs) except Exception as e: ip = get_ipython() if ip is None: container.log.warn("Exception in interact callback: %s", e, exc_info=True) else: ip.showtraceback() # Wire up the widgets for widget in kwargs_widgets: widget.on_trait_change(call_f, 'value') container.on_displayed(lambda _: call_f(None, None, None)) return container
def interactive(__interact_f, **kwargs): """ Builds a group of interactive widgets tied to a function and places the group into a Box container. Returns ------- container : a Box instance containing multiple widgets Parameters ---------- __interact_f : function The function to which the interactive widgets are tied. The **kwargs should match the function signature. **kwargs : various, optional An interactive widget is created for each keyword argument that is a valid widget abbreviation. """ f = __interact_f co = kwargs.pop('clear_output', True) manual = kwargs.pop('__manual', False) kwargs_widgets = [] container = Box(_dom_classes=['widget-interact']) container.result = None container.args = [] container.kwargs = dict() kwargs = kwargs.copy() new_kwargs = _find_abbreviations(f, kwargs) # Before we proceed, let's make sure that the user has passed a set of args+kwargs # that will lead to a valid call of the function. This protects against unspecified # and doubly-specified arguments. getcallargs(f, **{n: v for n, v, _ in new_kwargs}) # Now build the widgets from the abbreviations. kwargs_widgets.extend(_widgets_from_abbreviations(new_kwargs)) # This has to be done as an assignment, not using container.children.append, # so that traitlets notices the update. We skip any objects (such as fixed) that # are not DOMWidgets. c = [w for w in kwargs_widgets if isinstance(w, DOMWidget)] # If we are only to run the function on demand, add a button to request this if manual: manual_button = Button(description="Run %s" % f.__name__) c.append(manual_button) container.children = c # Build the callback def call_f(name=None, old=None, new=None): container.kwargs = {} for widget in kwargs_widgets: value = widget.value container.kwargs[widget._kwarg] = value if co: clear_output(wait=True) if manual: manual_button.disabled = True try: container.result = f(**container.kwargs) except Exception as e: ip = get_ipython() if ip is None: container.log.warn("Exception in interact callback: %s", e, exc_info=True) else: ip.showtraceback() finally: if manual: manual_button.disabled = False # Wire up the widgets # If we are doing manual running, the callback is only triggered by the button # Otherwise, it is triggered for every trait change received # On-demand running also suppresses running the function with the initial parameters if manual: manual_button.on_click(call_f) else: for widget in kwargs_widgets: widget.on_trait_change(call_f, 'value') container.on_displayed(lambda _: call_f(None, None, None)) return container
def interactive(__interact_f, **kwargs): """Build a group of widgets to interact with a function.""" f = __interact_f co = kwargs.pop('clear_output', True) manual = kwargs.pop('__manual', False) kwargs_widgets = [] container = Box() container.result = None container.args = [] container.kwargs = dict() kwargs = kwargs.copy() new_kwargs = _find_abbreviations(f, kwargs) # Before we proceed, let's make sure that the user has passed a set of args+kwargs # that will lead to a valid call of the function. This protects against unspecified # and doubly-specified arguments. getcallargs(f, **{n:v for n,v,_ in new_kwargs}) # Now build the widgets from the abbreviations. kwargs_widgets.extend(_widgets_from_abbreviations(new_kwargs)) # This has to be done as an assignment, not using container.children.append, # so that traitlets notices the update. We skip any objects (such as fixed) that # are not DOMWidgets. c = [w for w in kwargs_widgets if isinstance(w, DOMWidget)] # If we are only to run the function on demand, add a button to request this if manual: manual_button = Button(description="Run %s" % f.__name__) c.append(manual_button) container.children = c # Build the callback def call_f(name=None, old=None, new=None): container.kwargs = {} for widget in kwargs_widgets: value = widget.value container.kwargs[widget.description] = value if co: clear_output(wait=True) if manual: manual_button.disabled = True try: container.result = f(**container.kwargs) except Exception as e: ip = get_ipython() if ip is None: container.log.warn("Exception in interact callback: %s", e, exc_info=True) else: ip.showtraceback() finally: if manual: manual_button.disabled = False # Wire up the widgets # If we are doing manual running, the callback is only triggered by the button # Otherwise, it is triggered for every trait change received # On-demand running also suppresses running the fucntion with the initial parameters if manual: manual_button.on_click(call_f) else: for widget in kwargs_widgets: widget.on_trait_change(call_f, 'value') container.on_displayed(lambda _: call_f(None, None, None)) return container