-
-
Notifications
You must be signed in to change notification settings - Fork 525
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
unexpected Interactivity of "layered" plotly objects in Tabs #804
Comments
I am also having issues with the use of tabs causing a loss of plot interactivity except on the lowest level tab. This issue occurs for Plotly and hvplot objects, however it does not occur for Holoviews and Geoviews objects. Software Info:
Description of the Problem: I have created the following panel called "example": This panel contains the following elements:
Expected Behaviour: Observed Behaviour: For Element 2. (the histogram), if the user hovers over any graph component then the appropriate hover data is displayed in all 3 tabs. However if the user tries to interact with element 2., eg by selecting an attribute from the dropdown to display the appropriate histogram, then this only works for tab C. Furthermore, I noticed that if I choose an attribute from the dropdown, sometimes the selection doesn't seem to take and the plot doesn't update - this following error is then displayed in my Jupyter notebook:
Please note that this error does not trigger when choosing an attribute from the dropdown in the panel app "app_numeric" directly, however it does intermittently occur when "app_numeric" is added to the GridSpec. I also created a second panel called "example2": This panel is identical to "example" except that Element 2. was created using Plotly here.
Code to Reproduce Issue: Setup:import pandas as pd
import numpy as np
import random
import copy
import feather
import plotly.graph_objects as go
import plotly.express as px
import panel as pn
import holoviews as hv
import geoviews as gv
import geoviews.feature as gf
import cartopy
import cartopy.feature as cf
from geoviews import opts
from cartopy import crs as ccrs
import hvplot.pandas
import colorcet as cc
from colorcet.plotting import swatch
gv.extension("bokeh") Create dataframe:cols = {"name":["Jim","Alice","Bob","Julia","Fern","Bill","Jordan","Pip","Shelly","Mimi"],
"age":[19,26,37,45,56,71,20,36,37,55],
"age_band":["18-24","25-34","35-44","45-54","55-64","65-74","18-24","35-44","35-44","55-64"],
"insurance_renew_month":[1,2,3,3,3,4,5,5,6,7],
"postcode_prefix":["EH","M","G","EH","EH","M","G","EH","M","EH"],
"postcode_order":[3,2,1,3,3,2,1,3,2,3],
"local_authority_district":["S12000036","E08000003","S12000049","S12000036","S12000036","E08000003","S12000036","E08000003","S12000049","S12000036"],
"blah1":[3,None,None,8,8,None,1,None,None,None],
"blah2":[None,None,None,33,5,None,66,3,22,3],
"blah3":["A",None,"A",None,"C",None,None,None,None,None],
"blah4":[None,None,None,None,None,None,None,None,None,1]}
df = pd.DataFrame.from_dict(cols)
df Out[2]: name age age_band insurance_renew_month ... blah1 blah2 blah3 blah4
0 Jim 19 18-24 1 ... 3.0 NaN A NaN
1 Alice 26 25-34 2 ... NaN NaN None NaN
2 Bob 37 35-44 3 ... NaN NaN A NaN
3 Julia 45 45-54 3 ... 8.0 33.0 None NaN
4 Fern 56 55-64 3 ... 8.0 5.0 C NaN
5 Bill 71 65-74 4 ... NaN NaN None NaN
6 Jordan 20 18-24 5 ... 1.0 66.0 None NaN
7 Pip 36 35-44 5 ... NaN 3.0 None NaN
8 Shelly 37 35-44 6 ... NaN 22.0 None NaN
9 Mimi 55 55-64 7 ... NaN 3.0 None 1.0
[10 rows x 11 columns] Prepare Data for Fig1 and Plot:swatch("CET_L17")
normal_cmap = cc.CET_L17
df_count = df.count().sort_values(ascending=False)
df_count = df_count.to_frame().reset_index().rename(columns={"index":"attribute",0:"count"}) # Plot Fig1
fig1 = df_count[::-1].hvplot.bar(x="attribute",y="count",color="count",cmap=normal_cmap,invert=True, width=500, height=300) Prepare and Plot UK Choropleth Map:# Load Shapefile
shapefile = "/Users/maleko/Local_Authority_Districts_April_2019_Boundaries_UK_BUC/Local_Authority_Districts_April_2019_Boundaries_UK_BUC.shp"
gv.Shape.from_shapefile(shapefile, crs=ccrs.OSGB()) # Identify Attribute to Link Map & Data (It is "lad19cd"):
shapes = cartopy.io.shapereader.Reader(shapefile)
list(shapes.records())[0] # Plot UK Choropleth:
swatch("CET_R3")
new_cmap = cc.CET_R3
heatmap = gv.Shape.from_records(shapes.records(), df, on={"lad19cd":"local_authority_district"},
value="postcode_order",index="postcode_prefix", crs=ccrs.OSGB()).opts(tools=["hover"],
cmap = new_cmap, colorbar=True, hover_color="white", hover_alpha=0, title="UK Postcode Heatmap", width=500, height=800)
non_heatmap = gv.Shape.from_records(shapes.records(), df, on={"lad19cd":"local_authority_district"},
crs=ccrs.OSGB()).opts(title="UK Dealership Map", width=500, height=800)
wikimap = hv.Tiles('https://maps.wikimedia.org/osm-intl/{Z}/{X}/{Y}@2x.png', name="Wikimedia").opts(width=500, height=800)
pins = gv.Points([(-1.67514,54.96003,"Gateshead"),(-1.51591,54.52271,"Darlington"),(-2.28369,53.46123,"Manchester"),(-0.05944,51.64624,"Enfield"),(-3.73886,56.15171,"Tillicoultry")]).opts(tools=["hover"],color="#6a0dad",size = 15,hover_color="green")
result1 = wikimap*heatmap*pins
result2 = wikimap*non_heatmap*pins
map_app_df = pn.Tabs(("Show Heatmap",result1),("Hide Heatmap",result2)) A. Create Histogram Using hvplot:num_atts = ["age","insurance_renew_month"]
num_atts
def num_plot_df(numeric="age"):
if numeric =="age":
fig2= df.hvplot.hist(y="age",by=["age_band"],
bins=[18,25,35,45,55,65,74],
xticks=[(21.5,"18-24"),(30,"25-34"),(40,"35-44"),(50,"45-54"),(60,"55-64"),(69.5,"65-74")],
color="teal",legend=False,
line_width=4,line_color="w", width=500, height=300)
return fig2
elif numeric =="insurance_renew_month":
fig3 = df.hvplot.hist(y="insurance_renew_month",
bins=[1,2,3,4,5,6,7,8,9,10,11,12],
xticks=[(1.5,"JAN"),(2.5,"FEB"),(3.5,"MAR"),(4.5,"APR"),(5.5,"MAY"),(6.5,"JUN"),
(7.5,"JUL"),(8.5,"AUG"),(9.5,"SEP"),(10.5,"OCT"),(11.5,"NOV"),(12.5,"DEC")],
color="teal",legend=False,
line_width=4,line_color="w", width=500, height=300)
return fig3
app_numeric = pn.interact(num_plot_df,numeric=num_atts) Create Gridspec For hvplot Version:gspec = pn.GridSpec(sizing_mode="scale_both", max_height=1000)
gspec[0,0] = fig1
gspec[1,0] = app_numeric
gspec[0:2,1] = map_app_df B. Create Histogram Using Plotlydef num_plot_df_plotly(numeric="age",nbins=12):
if numeric in num_atts:
numplot = px.histogram(df,x=numeric,nbins=nbins, width=500, height=300)
numplot.update_traces(marker_line_color="rgb(255,255,255)",
marker_line_width=4)
return numplot
app_numeric2 = pn.interact(num_plot_df_plotly,numeric=num_atts,nbins=(1,20)) Create Gridspec For Plotly Version:gspec2 = pn.GridSpec(sizing_mode="scale_both", max_height=1000)
gspec2[0,0] = fig1
gspec2[1,0] = app_numeric2
gspec2[0:2,1] = map_app_df Final tabbed Gridspec panel for the hvplot version:example = pn.Tabs(("A",gspec),("B",gspec),("C",gspec))
example.show() Final tabbed Gridspec panel for the Plotly version:example2 = pn.Tabs(("A",gspec2),("B",gspec2),("C",gspec2))
example2.show() |
@jonmmease Do you have any idea what might be happening here? |
Hi, is there any update on this issue? Thanks |
No sorry and if there was we'd post it here. It's not clear to me whether this is an issue with Panel, Bokeh or Plotly tbh so it's hard to figure out what is happening. |
Code for the above example:
|
As a temporary workaround, I move all the content of the non-active tabs far up on the page by adjusting the margins. This way none of the invisible plotly figures overlap with the figures on the active tab. This workaround works well, even for nested tabs. But I have to warn you that the response time for switching tabs becomes rather slow when you have a lot of tabs.
|
Hi @philippjfr , From my side I tried to add JavaScript to replace "visibility: hidden" to "display: none", but was not successful because, the JavaScript was not called every time the tab changes. |
Hi, any progress on this issue? |
Hi! Since it's quite an old bug and there is no much progress here, maybe it's worth to write a warning in documentation that it's better to avoid use Tabs together with interactive plots in Panel, what do you think? Otherwise Panel users have to debug this issue, then google this page and finally have to redesign their application. |
The above examples seem specifically related to Plotly, right? I.e. it's not that interactive plots have trouble in tabs in Panel in general, but that specifically Plotly objects interact across tabs? If so such a general warning would not be appropriate; it's a very specific bug. It does sound like "display: none" is worth trying in Panel, though. |
@jbednar agree, not general interactive plots, but it seems specifically Plotly objects together with Tabs create an issue. |
I'll see if I can come up with a fix very soon. |
Hoping for fix to this issue soon. Plotly itself has tabs implemented in Dash. |
My first one of these so apologies if it's missing info / already flagged.
Software info:
python: 3.6.9
Panel = 0.6.2
plotly = 4.2.1
bokeh = 1.3.4
jupyter notebook server = 6.0.0
browser: Google chrome (and same behavior in embedded html output)
OS: Windows 8.1
Description of expected behavior and the observed behavior
Below applies to within jupyter notebook, in browser window (.show()) and in html output (.save(embed = True))
Expected behavior: plotly objects within panel tabs to have same interactivity as when not in tabs.
observed behavior: Only plotly object in "bottom level" (last in list of tabs, "fig2" tab in example) retains full interactivity (pan, zoom, select, legend trace select etc.)). All other tab "levels" (tabs other than the last one in tab list, "fig1" tab inexample) retain only legend select interactivity. Interactions with the area bound by the axis (where a crosshair is seen) in "fig1" results in changes to the "fig2" plotly object.
Complete, minimal, self-contained example code that reproduces the issue
Screenshots of issue
The text was updated successfully, but these errors were encountered: