GMapPlot, dots change location on color update

Hi,

I’m trying to plot dots on a GMapPlot, with a Select drop down to determine the color palette of the dots. Similar to what the crossfilter example does, except on a google map.

See minimal code example below.

The initial points get plotted correctly, but when I select an option from the drop down, the points on the map move. They are only supposed to change color. The dots seem to correspond to a different zoom setting for the GMapPlot. When I toggle the ZoomTool, the dots go to the right place.

I’ve written a simpler example where I just have a single color, so that color is not part of the ColumnDataSource. That works as expected.

Any help would be greatly appreciated, I’ve been banging my head against this for far too long.

Thanks,

Andrew

from bokeh.io import output_file, show

from bokeh.models import GMapPlot, GMapOptions, ColumnDataSource, Circle, DataRange1d, WheelZoomTool, Select

from bokeh.plotting import curdoc

from bokeh.layouts import layout, row, widgetbox

set up map / plot (my google maps API key: AIzaSyAh1cmN_U6smbyt5uCpMIhttQOYrE4JtLY)

map_options = GMapOptions(lat=49.74, lng=-123.117, map_type=“roadmap”, zoom=14)

plot = GMapPlot(

x_range=DataRange1d(), y_range=DataRange1d(), map_options=map_options,

api_key='PUT YOUR GOOGLE MAPS API KEY HERE'

)

c=[‘red’,‘green’,‘blue’]

create an initial source object (one color and size on each point)

source = ColumnDataSource( data=dict( lat = (49.746504,49.735954,49.744864),

                                    lon = (-123.117835,-123.114313,-123.114587),

                                    color = c ) )

set the circle parameters from the source elements

circle = Circle(x=“lon”, y=“lat”, fill_color=“color”, size=10, fill_alpha=0.5, line_color=None)

add the source to the plot as circles

plot.add_glyph(source, circle)

throw on some tools

plot.add_tools( WheelZoomTool() )

def update(attrname, old, new):

if color.value == 'RBG': c=['red','green','blue']

if color.value == 'Greyscale': c=['black','grey','white']

if color.value == 'CMY': c=['cyan','magenta','yellow']

# create the source object with the data to be plotted

source.data=dict(   lat = (49.746504,49.735954,49.744864),

                    lon = (-123.117835,-123.114313,-123.114587),

                    color=c)

# update the plot

plot.update()

add the selectors

color = Select(title=‘Color’, value=‘None’, options=[‘RBG’,‘Greyscale’,‘CMY’])

color.on_change(‘value’, update)

add the controls

controls = widgetbox([color], width=200)

layout = row(controls, plot)

curdoc().add_root(layout)

curdoc().title = “My Google Map”

``

Well, the problem is the DataRange1d, it's not really compatible with GMaps, which always insist on taking direct and complete control of the axis range values, in order to preserve a constant aspect ratio. DataRange1d tries to do it's thing (i.e. envelope the plot range to exactly fit the data points) but GMaps will just ignore the change. The solution is to use Range1d instead, which does not do any sort of auto-ranging.

Actually, this might just be a case where there should be a validation error. I'm not sure DataRange1d ever can make sense with GMap, in which case there should be an early warning to that effect. Please make a GitHub issue for this with this example code as well.

Thanks,

Bryan

···

On Jan 28, 2017, at 12:34 AM, Andrew Hamilton <[email protected]> wrote:

from bokeh.io import output_file, show
from bokeh.models import GMapPlot, GMapOptions, ColumnDataSource, Circle, DataRange1d, WheelZoomTool, Select
from bokeh.plotting import curdoc
from bokeh.layouts import layout, row, widgetbox

# set up map / plot (my google maps API key: AIzaSyAh1cmN_U6smbyt5uCpMIhttQOYrE4JtLY)
map_options = GMapOptions(lat=49.74, lng=-123.117, map_type="roadmap", zoom=14)
plot = GMapPlot(
    x_range=DataRange1d(), y_range=DataRange1d(), map_options=map_options,
    api_key='PUT YOUR GOOGLE MAPS API KEY HERE'
)

c=['red','green','blue']

# create an initial source object (one color and size on each point)
source = ColumnDataSource( data=dict( lat = (49.746504,49.735954,49.744864),
                                        lon = (-123.117835,-123.114313,-123.114587),
                                        color = c ) )

# set the circle parameters from the source elements
circle = Circle(x="lon", y="lat", fill_color="color", size=10, fill_alpha=0.5, line_color=None)

# add the source to the plot as circles
plot.add_glyph(source, circle)

# throw on some tools
plot.add_tools( WheelZoomTool() )

def update(attrname, old, new):

    if color.value == 'RBG': c=['red','green','blue']
    if color.value == 'Greyscale': c=['black','grey','white']
    if color.value == 'CMY': c=['cyan','magenta','yellow']

    # create the source object with the data to be plotted
    source.data=dict( lat = (49.746504,49.735954,49.744864),
                        lon = (-123.117835,-123.114313,-123.114587),
                        color=c)

    # update the plot
    plot.update()

# add the selectors
color = Select(title='Color', value='None', options=['RBG','Greyscale','CMY'])
color.on_change('value', update)

# add the controls
controls = widgetbox([color], width=200)
layout = row(controls, plot)

curdoc().add_root(layout)
curdoc().title = "My Google Map"

Thanks Bryan,

Range1d works as expected and I’ve posted the issue to GitHub:

https://github.com/bokeh/bokeh/issues/5826

Cheers,

Andrew

···

On Jan 27, 2017, at 10:48 PM, Bryan Van de Ven [email protected] wrote:

Well, the problem is the DataRange1d, it’s not really compatible with GMaps, which always insist on taking direct and complete control of the axis range values, in order to preserve a constant aspect ratio. DataRange1d tries to do it’s thing (i.e. envelope the plot range to exactly fit the data points) but GMaps will just ignore the change. The solution is to use Range1d instead, which does not do any sort of auto-ranging.

Actually, this might just be a case where there should be a validation error. I’m not sure DataRange1d ever can make sense with GMap, in which case there should be an early warning to that effect. Please make a GitHub issue for this with this example code as well.

Thanks,

Bryan

On Jan 28, 2017, at 12:34 AM, Andrew Hamilton [email protected] wrote:

from bokeh.io import output_file, show
from bokeh.models import GMapPlot, GMapOptions, ColumnDataSource, Circle, DataRange1d, WheelZoomTool, Select
from bokeh.plotting import curdoc
from bokeh.layouts import layout, row, widgetbox

set up map / plot (my google maps API key: AIzaSyAh1cmN_U6smbyt5uCpMIhttQOYrE4JtLY)

map_options = GMapOptions(lat=49.74, lng=-123.117, map_type=“roadmap”, zoom=14)
plot = GMapPlot(
x_range=DataRange1d(), y_range=DataRange1d(), map_options=map_options,
api_key=‘PUT YOUR GOOGLE MAPS API KEY HERE’
)

c=[‘red’,‘green’,‘blue’]

create an initial source object (one color and size on each point)

source = ColumnDataSource( data=dict( lat = (49.746504,49.735954,49.744864),
lon = (-123.117835,-123.114313,-123.114587),
color = c ) )

set the circle parameters from the source elements

circle = Circle(x=“lon”, y=“lat”, fill_color=“color”, size=10, fill_alpha=0.5, line_color=None)

add the source to the plot as circles

plot.add_glyph(source, circle)

throw on some tools

plot.add_tools( WheelZoomTool() )

def update(attrname, old, new):

if color.value == 'RBG': c=['red','green','blue']
if color.value == 'Greyscale': c=['black','grey','white']
if color.value == 'CMY': c=['cyan','magenta','yellow']

# create the source object with the data to be plotted
source.data=dict(   lat = (49.746504,49.735954,49.744864),
                    lon = (-123.117835,-123.114313,-123.114587),
                    color=c)

# update the plot
plot.update()

add the selectors

color = Select(title=‘Color’, value=‘None’, options=[‘RBG’,‘Greyscale’,‘CMY’])
color.on_change(‘value’, update)

add the controls

controls = widgetbox([color], width=200)
layout = row(controls, plot)

curdoc().add_root(layout)
curdoc().title = “My Google Map”


You received this message because you are subscribed to a topic in the Google Groups “Bokeh Discussion - Public” group.
To unsubscribe from this topic, visit https://groups.google.com/a/continuum.io/d/topic/bokeh/rz70sQpQq8c/unsubscribe.
To unsubscribe from this group and all its topics, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/3D22721D-0CE4-4F33-B365-D09EEC878232%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.