When the “Remap Selected” button in the example below is clicked, the plot updates successfully, but it shrinks from full-width to a small box:
after click (which updates the hv.DynamicMap for the points on the map):
I had some limited success in this demo example using sizing_mode=‘fixed’, but in more complicated panel configurations that causes other issues with different screen sizes… I am hoping there’s a way to use “stretch_both” but have the inner grid dimensions stay consistent through dynamicmap update events?
Has anyone run into this before? Seems similar to Plot changes size when partially updated
import geoviews as gv
import geoviews.tile_sources as gts
import geopandas
from cartopy import crs
import holoviews as hv
import panel as pn
import pandas as pd
from holoviews.streams import param
hv.extension('bokeh')
class TerrMapper(param.Parameterized):
cities = ['Buenos Aires', 'Brasilia', 'Santiago', 'Bogota', 'Caracas','Tacna','Pucallpa','Lima','Langa']
terrs = ['A','A','B','B','C','C','C','C','C']
terr_map = param.Dict(default=dict(zip(cities, terrs)), doc = 'mapping dictionary for cities-->territories')
terr_colors = param.Dict(default={'A':'red','B':'blue','C':'green'})
class Point_Remap_Test:
def __init__(self):
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]})
self.gdf = geopandas.GeoDataFrame(df, geometry=geopandas.points_from_xy(df.Longitude, df.Latitude),crs="EPSG:3857")
#tried to split the stream out to a parameterized class as part of troubleshooting; not sure this added any value
self.terrs = TerrMapper()
self.terrs.param.set_param(terr_map=self.terrs.param.terr_map.default)
self.territory_list = list(set(self.terrs.param.terr_map.default.values()))
self.territory_picklist = pn.widgets.Select(options= self.territory_list,name='Territory',width=250)
self.terr_stream = {'terr_map':self.terrs.param.terr_map}
#point collection should be dynamic and update it's territory assignment based on the mapping dictionary from the stream
self.points = hv.DynamicMap(self.dynamic_pnts,streams=self.terr_stream)
#second selection stream to capture lasso point selections
self.sel = hv.streams.Selection1D(source=self.points)
#coloring based on New_Territory; which is the dimension that should change as self.terr_stream changes
poly_plot = self.points.opts(color='New_Territory',cmap=self.terrs.param.terr_colors.default,tools=['lasso_select'],size=10)
self.tiles = gts.OSM.options(level='glyph')
self.plot=self.tiles*poly_plot
#button + drop down are attempting to allow relabeling of lasso-selected points
self.button = pn.widgets.Button(name='<--Remap Selected', button_type='primary')
self.button.on_click(self.update_terrs)
def dynamic_pnts(self,terr_map):
'''
Apply current territory map to base geo dataframe
'''
new_df = self.gdf.copy()
new_df.loc[:,'New_Territory'] = new_df['City'].map(terr_map)
print('updating')
return gv.Points(new_df,vdims=['New_Territory'])
def update_terrs(self,event):
'''
Update the territory map based on selections
'''
if len(self.sel.index)>0:
selected_cities = self.gdf.loc[self.sel.index,'City'].values[:]
#there must be a better way to do this
#param_vals = self.terrs.param.get_param_values()
#temp_dict = [v for (k,v) in param_vals if k=='terr_map'][0]
temp_dict = self.terrs.terr_map.copy()
for city in selected_cities:
temp_dict[city] = self.territory_picklist.value
self.terrs.param.set_param(terr_map=temp_dict)
else:
print('no selection')
def createApp():
geoplt = Point_Remap_Test()
gspec = pn.GridSpec(sizing_mode='stretch_both')
#context switcher
gspec[0,0:4] = pn.Column("#New Territory",pn.Row(geoplt.territory_picklist,geoplt.button))
#map
gspec[1:3,0:4] = pn.pane.HoloViews(geoplt.plot)
return gspec
test = createApp()
test