John Robinson
John Robinson

Reputation: 370

Calling a Javascript method from the Bokeh Google Maps wrapper (fitBounds())

I have a bokeh Google maps plot with several Lat/ Lng data points, and I would like to use the fitBounds() method of the Google Maps v3 API to set the zoom level.

I have a Google Maps plot up and running, displaying on my site and showing the data points, but I need to set the zoom manually.

import bokeh.io
import bokeh.models
import bokeh.plotting
import pandas as pd

data = {
    'Latitude [deg]': [18.46, 25.7, 32.3],
    'Longitude [deg]': [-66, -80.2, -64.8],
}
data_frame = pd.DataFrame.from_dict(data)
data_source = bokeh.models.ColumnDataSource(data_frame)
mean_lat = data_frame['Latitude [deg]'].mean()
mean_lng = data_frame['Longitude [deg]'].mean()
gmap_options = bokeh.models.GMapOptions(lat=mean_lat, lng=mean_lng, zoom=10, map_type='satellite')
xy_gmap = bokeh.plotting.gmap('SuPeRSeCrEtAPIkey', gmap_options)
xy_gmap.circle(x='Longitude [deg]', y='Latitude [deg]', source=data_source, color="red")

# A callback like this? Could make the call in JavaScript after the page is loaded, and update map zoom??
# xy_gmap.fitBounds(x='Longitude [deg]', y='Latitude [deg]', source=data_source)

bokeh.io.show(xy_gmap)

I would like the bounds of the map to enclose all points in my dataframe, at the lowest zoom possible (as is done in Javascript by fitBounds() ). Currently, the map can only zoom to the manually set level.

Upvotes: 1

Views: 252

Answers (2)

John Robinson
John Robinson

Reputation: 370

Starting an answer for both methods described by bigreddot (using JS Bokeh.index and Python integration)

Bokeh.index

In the Javascript Console, you can use the following commands (should be self explanatory to get this into some JS code)

> var gmapPlotView;
> for (var property in Bokeh.index) { if (Bokeh.index[property].constructor.name == 'GMapPlotView') {gmapPlotView = Bokeh.index[property];} }    // Get the correct object, in the case that you have multiple plots, but only one map plot
> var bounds = gmapPlotView.map.getBounds();                  // To start from existing bounds
> var bounds = google.maps.LatLngBounds();                    // To start with fresh bounds
> var place = new google.maps.LatLng(45.5983128 ,8.9172776);  // Coordinates of place to put bounds, repeat for all points
> bounds.extend(place);                                       // Add each place to the bounds object
> gmapPlotView.map.fitBounds(bounds);                         // Set the maps new bounds

Note that the Bokeh google maps implementation does not plot your data on the Google Maps data layer, but on a bokeh canvas above the map (that is why there is a lag when panning the map between map tiles and your graphs).

Python Integration

In process....

Upvotes: 0

bigreddot
bigreddot

Reputation: 34618

As of Bokeh 1.2, there is no built-in way to accomplish this. The only suggestion I can offer is to note that there is a global Bokeh.index on the JavaScript side, and in that there is GMapPlotView for the corresponding GmapPlot that you made. This view has an attribute .map that is the actual Google map object. You could call the fitBounds method on that from JavaScript code. Bokeh GMapPlot objects follow Google's lead wrt to plot bounds, so if they get updated, the axes, etc. should respond.

Otherwise, I can only suggest opening a GitHub issue to discuss adding this as a new feature.

Upvotes: 1

Related Questions