Search code examples
pythonjupyter-notebookarcgisbokehdatashader

Map background with datashader - "Map data not yet available"


I'm trying to overlay interactive datashader plot on top of map and I only getting "Map data not yet available" background instead of map background. I have tried different map services and different maps but none of them worked. Here is the code I found for a similar data set:

import bokeh.plotting as bp
from bokeh.models.tiles import WMTSTileSource
bp.output_notebook()

def base_plot(tools='pan,wheel_zoom,reset',webgl=False):
    p = bp.figure(tools=tools,
        plot_width=int(850), plot_height=int(500),
        x_range=x_range, y_range=y_range, outline_line_color=None,
        min_border=0, min_border_left=0, min_border_right=0,
        min_border_top=0, min_border_bottom=0, webgl=webgl)

    p.axis.visible = False
    p.xgrid.grid_line_color = None
    p.ygrid.grid_line_color = None

    return p

-

background = "black"
from datashader.bokeh_ext import InteractiveImage

def image_callback(x_range, y_range, w, h, color_fn=tf.shade):
    cvs = ds.Canvas(plot_width=w, plot_height=h, x_range=x_range, y_range=y_range)
    agg = cvs.points(df, 'Dropoff_longitude', 'Dropoff_latitude', ds.count('Passenger_count'))
    image = color_fn(agg)
    return tf.dynspread(image,threshold=0.75, max_px=8)
    #return(image)

p = base_plot()

url="https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{Z}/{Y}/{X}.png"
#url="http://tile.stamen.com/toner-background/{Z}/{X}/{Y}.png"
tile_renderer = p.add_tile(WMTSTileSource(url=url))
tile_renderer.alpha=1.0 if background == "black" else 0.15

InteractiveImage(p, image_callback)

Here's how it looks at the output:

Output screenshot

Does anyone know why this is happening?

Thanks in advance!


Solution

  • It looks to me like you are taking source data as bare latitudes and longitudes (numbers like -75.2), and trying to overlay it with image tiles indexed using Web Mercator coordinates (numbers like -8235000). The map tile sources are then correctly reporting that there is no image data available for that resolution. If you zoomed out by a factor of a million or so, you'd see the map tiles, but then they wouldn't be aligned with the data. Because Bokeh only supports Web Mercator coordinates when using tile sources, you need to project the data into Web Mercator before running datashader on it, if you want to overlay it with map tiles. You can use datashader.utils.lnglat_to_meters() for this purpose; see its docstring for details. Once things have been projected your example works fine:

    screenshot