Two ipython widgets for one variable - python

I am trying to make a interactive function where I can control the input with 2 widgets for the same variable. I Trying this because I want to have the option to slider the values (for a quick view) and also pick one specific (typing one value). I tried this linking the widgets with the ipywidget.jslink. I guessed once the widgets where linked I could input the values in any of them to pass to the variable. However, it is not what happens: below, only the values I set in the Slider updates the function (in other words, typing a value in the widget doesn't update the output). Why doesn't jslink work? In this link I found that substituting ipw.jslink for traitlets.linkworks fine.
import ipywidgets as ipw
from IPython.display import display
def f(x):
return x**2
a=ipw.IntSlider(min=-10,max=20,step=1,value=10)
b=ipw.IntText(min=-10,max=20,step=1,value=10)
ipw.jslink((a,'value'),(b,'value'))
wid=ipw.interactive(f, x=a)
display(wid,b)

If the issue is the Python objects not updating on the backend, it is probably because you are using jslink instead of link [ref]. Otherwise, I think this is an old issue with a previous version. I recreated with captured output and both the slider and Text call the function f(x):
from IPython.display import display
output = ipw.Output()
#output.capture()
def f(x):
print(x**2)
return x**2
a=ipw.IntSlider(min=-10,max=20,step=1,value=10)
b=ipw.IntText(min=-10,max=20,step=1,value=10)
ipw.jslink((a,'value'),(b,'value'))
wid=ipw.interactive(f, x=a)
display(wid,b)
display(output)

Related

Using xbox controller for Jupyter notebook, keep variables assigned to joystick values in the real time

I am using a Jupyter notebook for my project with a Xbox controller to control a robot in real time.
import ipywidgets.widgets as widgets is used
it works directly assigning them to sliders or motors using traitlets, but I do not how to do calculations with them beforehand.
If I assign these values to variables, it gets the current value at the time of running the cell.
Here is working code that assigns directly to motor:
left_link = traitlets.dlink((controller.axes[1], 'value'), (robot.left_motor, 'value'), transform=lambda x: -x)
However, I need to calculate the angle I want to go, therefore calculating arctan2 of two axes of joystick values (the transform: lambda does not suffice I think?).
I do not understand how I should take on this problem, as I have never worked with always updating variables, like the Xbox controller variables. Please tell me if you need any more information.
The thing I was looking for was Observe()
like here:
import ipywidgets.widgets as widgets
int_range = widgets.IntSlider()
display(int_range)
def on_value_change(change):
print(change)
print(change['new'])
int_range.observe(on_value_change, names='value')
This allows reassigning the variable value everytime the controller changes it's value.

Accessing Jupyter notebook widgets values

While trying to use the Jupyter widgets to control a different function I am stumbling over this issue and am searching for a workaround.
The widget is displayed and I can interact with it just fine. Reading the value, as stated in the documentation using w.value also works. But now reading the value continuously in a loop does not work. Whereas I uncheck the box the value in the while loop never changes.
How can I control python functions via the widgets if they are not updated with the current state of the widgets?
Hope this helps. My reference is this link.
from IPython.display import display
import ipywidgets as widgets
def f(x):
return 'value of checkbox is: ' + str(x)
w = widgets.Checkbox(value=True, description='Updated?')
interact(f,x=w)

Is there a way to hide a displayed object using IPython?

I am using the IPython module in a Jupyter Notebook.
I am using the display module to display buttons.
from ipywidgets import widgets
import IPython.display as dsply
def click_reset(b):
print("reset domains button")
restoreDomains()
resetButton = widgets.Button(description="Reset Domains")
resetButton.on_click(click_reset)
dsply.display(resetButton)
This works fine, but I am trying to find a way to programatically hide certain buttons. Based off the execution of my other code, I want certain buttons to be removed from the UI. Is there anything like hide(resetButton) that I can use?
You can hide a widget using
resetButton.layout.visibility = 'hidden'
to let the widget still consume space, or
resetButton.layout.display = 'none'
to let the widget not consume space anymore.
The top-level attribute resetButton.visible = False is not longer supported.
When I use #SergeyGornostaev's answer, I still have a residual cross showing up on the left side of the cell output. I found the following command removes the widget all together:
resetButton.close()
You can hide every widget by setting it's property visible to False
resetButton.visible = False

How to sort key names in ipywidgets interactive widgets (slider)?

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
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 :-)

Get pixel location from mouse click in TKinter

I'm quite new to Python and have been unsuccessful in finding a way around this problem. I have a GUI using TKinter that displays an image using Label. I would like the user to be able to click on two places in the image and use those two pixel locations elsewhere.
Below is the basic code I'm using so far, but I'm unable to return the pixel locations. I believe bind is not what I want to use, is there another option?
px = []
py = []
def onmouse(event):
px.append(event.x)
py.append(event.y)
return px,py
self.ImgPanel.bind('<button-1>',onmouse)
If I try to use:
px,py = self.ImgPanel.bind('<button-1>',onmouse)
I get an error "Too many values to unpack"
bind is what you want, if you want to capture the x,y coordinate of the click. However, functions called from bindings don't "return". Technically they do, but they return a value to the internals of Tkinter.
What you need to do is set an instance or global variable within the bound function. In the code you included in your question, if you add global px,py, you can then use those values in other code.

Categories