Hello,
What I am trying to do is allow the user to tap on the map and plot time series data for the n-closest points.
The tap stream along with the Dynamic map work for the rasterized image. The problem is if I use an hv.overlay
(that is the commented part). The reason for using an hv.overlay
is that I will create a list of hv.Curves
with a time series for each and then I can use hv.Overlay(list_of_curves)
As an alternative, Can I make the callable function clicked_point
return a Bokeh plot?
Thanks
from pyproj import Transformer
import holoviews as hv
import pandas as pd
import numpy as np
import holoviews.operation.datashader as hd
import datashader as ds
from holoviews import opts
hv.extension("bokeh")
renderer = hv.renderer("bokeh").instance(mode="server")
TOOLS = ['box_select', 'lasso_select', 'reset', 'tap']
# Dummy data
lats = np.linspace(30.266,30.466, num=1000)
lons = np.linspace(-97.73,-97.93, num=1000)
velocity = np.random.randint(0, 10000, size=1000)
df = pd.DataFrame({'latitude': lats, 'longitude': lons, 'velocity': velocity})
# Transform to mercator
lonlat_to_webmercator = Transformer.from_crs(
"EPSG:4326", "EPSG:3857", always_xy=True)
df['longitude_mercator'], df['latitude_mercator'] = \
lonlat_to_webmercator.transform(
df['longitude'], df['latitude'])
map_points = hv.Points(
df,
["longitude_mercator", "latitude_mercator"]
)
spreaded = hd.dynspread(
hd.rasterize(
map_points,
aggregator=ds.mean('velocity'),
element_type=hv.Image,
precompute=True,
),
threshold=0.5,
max_px=10
).opts(tools = ['hover'])
map_plot = spreaded.opts(
opts.Image(
cmap="rainbow_r",
cnorm='linear',
colorbar=True,
clabel="mm/yr",
bgcolor="black",
height=700,
toolbar="left",
responsive=True,
show_frame=False,
xaxis=None,
yaxis=None,
),
)
extracted_dims = hd.inspect_points(map_plot)
map_plot = hv.element.tiles.EsriImagery() * map_plot \
* extracted_dims.opts(tools=['hover'] + TOOLS)
posxy = hv.streams.Tap(source=spreaded, x=0, y=0)
# Doesnt work
# def clicked_point(x, y):
# if x == 0 and y == 0:
# return hv.Overlay([hv.Points([])])
# return hv.Overlay([hv.Points(data={'x': [x,x+50], 'y': [y, y+50]})])
def clicked_point(x, y):
if x == 0 and y == 0:
return hv.Points([])
return hv.Points(data={'x': [x,x+50], 'y': [y, y+50]}).opts(marker = 'triangle', size = 20 )
tap_dmap = hv.DynamicMap(clicked_point, streams=[posxy]).opts(
height = 300,
responsive=True,
framewise=True,
).opts(tools= TOOLS)
h = hv.Layout(map_plot + tap_dmap).cols(1)
h