Trying to make an interactive map where the selection point moves using sliders

So this successfully replicate the issue. Sliders move and update and no error is thrown, but dot it not moving

from bokeh.layouts import column, row
from bokeh.models import CustomJS, Slider
from bokeh.plotting import ColumnDataSource, figure, output_notebook, show
#from bokeh.tile_providers import get_provider, Vendors
#tile_provider = get_provider('STAMEN_TERRAIN')
output_notebook()

odd_locs = ColumnDataSource({'x': list(range(1,10,2)), 'y': list(range(1,10,2))})
even_locs = ColumnDataSource({'x': list(range(0,10,2)), 'y':list(range(0,10,2))})
source = ColumnDataSource({'x':[2], 'y':[2]})
x_slider = Slider(start=0, end=10, value=0, step = 2, title="X_Slider")
y_slider = Slider(start=0, end=10, value=0, step =2, title="Y_Slider")

p = figure(x_range=(0,10),y_range=(0,10))
p.circle('x','y',source=source, color= "blue")
callback = CustomJS(args=dict(source=source, 
                    odd_locs = odd_locs,
                    even_locs = even_locs,
                    x_slider=x_slider, 
                    y_slider=y_slider),
                    code=""" 
                        var data = source.data;
                        const odd = odd_locs.data;
                        const even = even_locs.data;
                        const red = x_slider.value;
                        const blue = y_slider.value;
                        const idx_lat = even.x.indexOf(red);
                        const idx_long = even.y.indexOf(blue);
                        const lat = odd['x'][idx_lat];
                        const long = odd['y'][idx_long];
                        data = {'x': [lat], 'y': [long]};
                        source.change.emit();
                    """)
x_slider.js_on_change('value', callback)
y_slider.js_on_change('value', callback)

layout = row(p, column(x_slider, y_slider))
show(layout)

@tpike3

See the post immediately above. Specifically this line in the callback.

I removed the brackets, but no impact. I put the brackets because p.circle requires arrays and not data types for a plot. (e.g. source = ColumnDataSource({‘x’:2, ‘y’:2} throws an error vs source = ColumnDataSource({‘x’:[2], ‘y’:[2]}).

The difference is not the brackets, but rather replacing data = with source.data = in the callback function

1 Like

@_jm That did it! Thanks!

@_jm and @p-himik Thanks again for help, I believe I finally got it narrowed to the root issue.

The dot is still disappearing on the map and I know it is not finding the value in the array, but it is there.
Code for callback with “print” statement

callback = CustomJS(args=dict(source=source, 
                    lat_plot=lat_plot,
                    long_plot=long_plot,
                    latitude_slider=latitude_slider, 
                    longitude_slider=longitude_slider),
                    code=""" 
                        var data = source.data;
                        const lat = lat_plot.data;
                        const long = long_plot.data;
                        const Y = latitude_slider.value.toFixed(2);
                        const X = longitude_slider.value.toFixed(2);
                        const idx_long = long.globe.indexOf(X);
                        const idx_lat = lat.globe.indexOf(Y);
                        document.write(long.globe + "<br>" +  longitude_slider.value.toFixed(2) + "<br>" + idx_long)
                        const lat_pt = lat['web'][idx_lat];
                        const long_pt = long['web'][idx_long];
                        source.data = {x: [long_pt], y: [lat_pt]};
                        source.change.emit();
                    """)

This will print
…6.75, 6.85, 6.95, 7.05… //array long.globe
6.85 //longitude.values.toFixed(2)
-1 // idx_long

My impression is although the number looks the same they are to different binary versions but I do not how to make them the same.

@tpike3

The two quantities are not equal b/c they are fundamentally different types. The toFixed() method in JavaScript returns a string representation of the number. Presumably your actual data is a floating-point array. Hence, even though it looks as if the number you seek is there, it’s only the same in the sense of what you see printed.

This gets to some of the earlier points I made about that indexOf() returning -1 and yielding an undefined result when you attempt to index the array with it.

In general, I think you need to be very careful when attempting to do equivalence testing of floating-point data. Without having insight into your real data, it’s hard to say what is the best way forward here.

1 Like

@_jm thanks! It works…I got it working by doing lots of conversions ending up with string equivalence.The returning -1 comment previously was critical as that is when I noticed that python and javascript where interpreting the 2 float numbers differently and I thought toFixed() was rounding for Javascript.

My biggest problem was figuring out how to see what indexOf() was actually returning as inspecting the webpage code I was getting caught up in the Bokeh code and not seeing what the variables were. In the end I muddle through with a document.write() having never really used Javascript before.

Regardless, thanks for all your help and patience!!!

@tpike3

Great that you have your app working. Another option is to use console.log( ), which you can use to dump output to the web-browser’s JavaScript console (which is accessed as outlined early on in this topic.)

Good luck with the remainder of the development, and certainly ask questions of those of us in the community if something else arises.