0

With plotly I am able to plot a 3D cylinder surface using go.Surface(...). Besides this cylinder trace I have a second trace with additional data points from a 3D scatter plot go.Scatter3d(...) on the final plot. These data have a lower radius than the surface cylinder:

import plotly.graph_objects as go
import numpy as np

def data_for_cylinder_along_z(center_x,center_y,radius,height_z):
    z = np.linspace(0, height_z, 50)
    theta = np.linspace(0, 2*np.pi, 50)
    theta_grid, z_grid=np.meshgrid(theta, z)
    x_grid = radius*np.cos(theta_grid) + center_x
    y_grid = radius*np.sin(theta_grid) + center_y
    return x_grid,y_grid,z_grid

Xc,Yc,Zc = data_for_cylinder_along_z(0,0,100,3600)
cyl = go.Surface(x=Zc_o, y=Yc_o, z=Xc_o, 
                   colorscale = 'Blues', 
                   showscale=False, opacity=0.2)


dots = go.Scatter3d(x=[240,869,2709,3001],
                       y=[30,60,83,25],
                       z =[35,40,29,27],
                      )

layout = go.Layout(scene = dict(aspectmode = "manual", 
                                aspectratio = dict(x=2, y=0.3, z=0.3),
                               ),
                  )

fig = go.Figure(data=[
                      cyl,
                      dots,
                     ],
                layout=layout,
               )

fig.show()

Now I want to get information for each scattered data point inside the cylinder by hovering over the plotly plot - but I have no access to these data. The hovering is stucked at the surface of the outer cylinder, I cannot get any information from inside. If the cyl-Statement is removed from fig=go.Figure(...) the hovering works as desired.

Is there a possibility to disable the hovering for the outer cylinder surface in plotly?

I tried to use internal plotly parameters like

hovertemplate=None
hoverinfo = 'skip'
contours=go.surface.Contours(
                       x=go.surface.contours.X(highlight=False))

but without success.

heisinger
  • 1
  • 1
  • Could you provide a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) ? – rochard4u Jun 27 '23 at 12:25
  • See this [SO answer](https://stackoverflow.com/questions/32319619/disable-hover-information-on-trace-plotly). They omit the hover template. `cyl = go.Surface(x=Zc, y=Yc, z=Xc, colorscale = 'Blues', showscale=False, opacity=0.2, hoverinfo='skip') ` – r-beginners Jun 27 '23 at 13:48
  • @r-beginners: Already tried. Setting the hoverinfo parameter that way results in not showing the according (x, y, z) information but the cursor still stucks at the outer cylinder surface. – heisinger Jun 28 '23 at 05:30

2 Answers2

0

You are not the only one. It looks like there is no solution at the moment

https://community.plotly.com/t/completely-excluding-a-trace-from-hover-info-snapping/35854

Edit: changing the theta range to

theta = np.linspace(0, 2*np.pi*0.8, 50)

to remove a segment:

Plot with segment removed

StephanT
  • 649
  • 5
  • 12
  • Thank you - that comforts me very much ;-) By the way: I remember the link, stumbled over it during my recherche... – heisinger Jun 28 '23 at 11:11
  • If the full cylinder is not necessary for the understanding of the graph, you could consider leaving out a segment so you can "look into" it and get the mouse hover on. Maybe leave out a slice of 30-60 degrees (roughly from 12 o'clock to 2 o'clock) – StephanT Jun 28 '23 at 11:51
  • Very nice idea. But unfortunately, in reality I have so much dots inside distributed over the hole angular range, that this wouldn't work productively. – heisinger Jun 28 '23 at 12:27
  • You could add a range slider widget to select the angle over which the cylinder needs to be shown/opened ;-) – StephanT Jun 28 '23 at 12:36
  • Yes - maybe I will try :-) Thank you! – heisinger Jun 28 '23 at 12:53
0

Based on the comment of the former answer, I replaced the cylinder surface by a stack of contours:

import plotly.graph_objects as go
import numpy as np

def data_for_cylinder_along_z(center_x,center_y,radius,height_z):
    z = np.linspace(0, height_z, 50)
    theta = np.linspace(0, 2*np.pi, 50)
    theta_grid, z_grid=np.meshgrid(theta, z)
    x_grid = radius*np.cos(theta_grid) + center_x
    y_grid = radius*np.sin(theta_grid) + center_y
    return x_grid,y_grid,z_grid

def boundary_circle(r, h, nt=100):
    theta = np.linspace(0, 2*np.pi, nt)
    x = r*np.cos(theta)
    y = r*np.sin(theta)
    z = h*np.ones(theta.shape)
    return x, y, z

cyl_dia = 100
cyl_len = 3600
frac = 100

Xc,Yc,Zc = data_for_cylinder_along_z(0,0,cyl_dia,cyl_len)
xb, yb, zb = boundary_circle(cyl_dia, h=0)
x_cont, y_cont, z_cont = [], [], []
for i in range(0,frac):
    x_cont += [val for val in xb] + [None]
    y_cont += [val for val in yb] + [None]
    z_cont += [val + i*cyl_len/frac for val in zb] + [None]
x_cont += [val for val in xb]
y_cont += [val for val in yb]
z_cont += [val + cyl_len for val in zb_low]

cyl = go.Surface(x=Zc_o, y=Yc_o, z=Xc_o, 
                 colorscale = 'Blues', 
                 showscale=False, opacity=0.2, 
#                  hoverinfo='skip'
                )

cyl_contour = go.Scatter3d(
                     x=z_cont, y=y_cont, z=x_cont,                   
                     hovertemplate=None,
                     hoverinfo = 'skip',
                     mode ='lines',
                     line = dict(color='blue', width=2),
                     opacity=0.15
                    )

dots = go.Scatter3d(x=[240,869,2709,3001],
                       y=[30,60,83,25],
                       z =[35,40,29,27],
                      )

layout = go.Layout(scene = dict(aspectmode = "manual", 
                                aspectratio = dict(x=2, y=0.3, z=0.3),
                               ),
#                    hovermode=False,
                   hoverdistance=0
                  )

fig = go.Figure(data=[
#                       cyl,
                      cyl_contour,
                      dots,
                     ],
                layout=layout,
               )

fig.show()

This is ok for my purpose (even if it does not completely satisfy me...)

enter image description here

heisinger
  • 1
  • 1