Hello,
I am trying to plot a second set of points based on the selection from an initial set, but on the same plot.
The functionality I am aiming for is highlighting a group of unselected; related points (e.g. that the user might have missed when they made their selection).
I made a mock example with cities/countries
- dark circles borders should show up around all points from same country set that user selected from filled circles.
e.g. if the user selects a subset of the 4 cities in Peru, I want to show dark circles around the full set of all 4 cities.
import holoviews as hv
import geoviews as gv
import geoviews.tile_sources as gts
import pandas as pd
import geopandas
from holoviews import streams
import panel as pn
hv.extension('bokeh')
df = pd.DataFrame(
{'City': ['Buenos Aires', 'Brasilia', 'Santiago', 'Bogota', 'Caracas','Tacna','Pucallpa','Lima','Langa'],
'Country': ['Argentina', 'Brazil', 'Chile', 'Colombia', 'Venezuela','Peru','Peru','Peru','Peru'],
'Latitude': [-34.58, -15.78, -33.45, 4.60, 10.48, -18.006,-8.392,-12.046,-12.125],
'Longitude': [-58.66, -47.91, -70.66, -74.08, -66.86,-70.246,-74.582,-77.0427,-76.4211]})
gdf = geopandas.GeoDataFrame(df, geometry=geopandas.points_from_xy(df.Longitude, df.Latitude),crs="EPSG:3857")
gv_table = hv.Table(gdf)
tiles = gts.OSM.options(level='glyph')
point_size_slider = pn.widgets.IntSlider(name="Point Size",start=3,end=12,value=7)
@pn.depends(size=point_size_slider.param.value)
def base_points(size):
return gv.Points(gv_table,kdims=['Longitude','Latitude'],vdims=['City','Country']).opts(size=size,tools=['lasso_select'],nonselection_alpha=0.75)
test = hv.DynamicMap(base_points)
sel = streams.Selection1D(source=test)
@pn.depends(size=point_size_slider.param.value)
def highlight_missed(index,size):
'''
Add another layer of points (empty black circle outlines) for the selected points; but expand visible points to all that share country label
'''
if len(index)>0:
#TODO: is there a better way to slice a dynamic map and get the underlying data by index?
selected_countries = test.items()[0][1].data.loc[index,'Country'].values[:]
return gv.Points(gdf[gdf['Country'].isin(selected_countries)],kdims=['Longitude','Latitude'],vdims=['City','Country']).opts(size=size,fill_color=None,line_width=1,line_color='black')
else:
return gv.Points(gdf,kdims=['Longitude','Latitude'],vdims=['City','Country']).opts(size=size+1,fill_color=None,line_width=1,line_color='black')
test2 = hv.DynamicMap(highlight_missed,streams=[sel])
plot = tiles*test*test2
layout = pn.Column(point_size_slider,plot.opts(width=600,height=600))
layout
When I run this, it seems to only put the dark border around the points selected; not expanding the set to include the remaining points in the country:
Any advice would be appreciated!