Skip to content
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

Scattergl Hover:closest and Click only active with first-plotted trace #2079

Open
tobsecret opened this issue Jan 15, 2020 · 5 comments
Open
Labels
bug something broken P3 backlog

Comments

@tobsecret
Copy link

tobsecret commented Jan 15, 2020

EDIT
Problem:
Scattergl hover and click functionalities are only available for the first-plotted trace if one has multiple traces but does not matter when using Scatter.
/EDIT

I am using plotly 4.4.1 and was trying out the network demo on the plotly website. Since I have lots of nodes and edges in my graph, I tried using Scattergl instead.

This works and speeds up the plotting but disables the tool tips on hover on hovermode="closest". The hover does however still find the points, which we can see when we press "Toggle Spike Lines", which snap onto the point our cursor is closest to.

Clicking on the "compare data on hover" button let's tool tips appear but this is a very erratic experience when we have a lot of points close to each other.

EDIT: I have produced a smaller code example in the next comment on this thread.

Not sure if this was addressed in plotly/plotly.js#4323 which should be part of my version (4.4.1).
Below is the network demo with Scatter substituted for Scattergl, which can reproduce my issue:

import plotly.graph_objects as go

import networkx as nx

G = nx.random_geometric_graph(200, 0.125)
edge_x = []
edge_y = []
for edge in G.edges():
    x0, y0 = G.nodes[edge[0]]['pos']
    x1, y1 = G.nodes[edge[1]]['pos']
    edge_x.append(x0)
    edge_x.append(x1)
    edge_x.append(None)
    edge_y.append(y0)
    edge_y.append(y1)
    edge_y.append(None)

edge_trace = go.Scattergl(
    x=edge_x, y=edge_y,
    line=dict(width=0.5, color='#888'),
    hoverinfo='none',
    mode='lines')

node_x = []
node_y = []
for node in G.nodes():
    x, y = G.nodes[node]['pos']
    node_x.append(x)
    node_y.append(y)

node_trace = go.Scattergl(
    x=node_x, y=node_y,
    mode='markers',
    hoverinfo='text',
    marker=dict(
        showscale=True,
        # colorscale options
        #'Greys' | 'YlGnBu' | 'Greens' | 'YlOrRd' | 'Bluered' | 'RdBu' |
        #'Reds' | 'Blues' | 'Picnic' | 'Rainbow' | 'Portland' | 'Jet' |
        #'Hot' | 'Blackbody' | 'Earth' | 'Electric' | 'Viridis' |
        colorscale='YlGnBu',
        reversescale=True,
        color=[],
        size=10,
        colorbar=dict(
            thickness=15,
            title='Node Connections',
            xanchor='left',
            titleside='right'
        ),
        line_width=2))
node_adjacencies = []
node_text = []
for node, adjacencies in enumerate(G.adjacency()):
    node_adjacencies.append(len(adjacencies[1]))
    node_text.append('# of connections: '+str(len(adjacencies[1])))

node_trace.marker.color = node_adjacencies
node_trace.text = node_text
fig = go.Figure(data=[edge_trace, node_trace],
             layout=go.Layout(
                title='<br>Network graph made with Python',
                titlefont_size=16,
                showlegend=False,
                hovermode='closest',
                margin=dict(b=20,l=5,r=5,t=40),
                annotations=[ dict(
                    text="Python code: <a href='https://plot.ly/ipython-notebooks/network-graphs/'> https://plot.ly/ipython-notebooks/network-graphs/</a>",
                    showarrow=False,
                    xref="paper", yref="paper",
                    x=0.005, y=-0.002 ) ],
                xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
                yaxis=dict(showgrid=False, zeroline=False, showticklabels=False))
                )
fig.show()
@tobsecret
Copy link
Author

tobsecret commented Jan 17, 2020

I have been able to narrow this down, and make a more compact example.
It turns out, this just has to do with the layering of the traces in the call to go.Figure.

If one calls go.Figure(data=[node_trace, edge_trace]), then the hover information for node_trace is displayed, but if one calls go.Figure(data=[edge_trace, node_trace]), then the hovering does not work anymore and neither does clicking, it turns out.
Note that this is only true for go.Scattergl and not true for go.Scatter!

#node trace
#creating fake nodes
number_of_nodes = 1791
letters = list('abcdefghijklmnopqrstuvwxyz')
node_xy = np.random.normal(size=(2,number_of_nodes))
node_text = np.char.add(np.random.choice(letters, size=number_of_nodes), np.char.mod('%d', np.arange(number_of_nodes)))
#Plotting the nodes:
node_trace = go.Scattergl(x=node_xy[0], y=node_xy[1], mode='markers', marker={'size':20}, text=node_text)
#edge trace
#creating fake edges
number_of_edges = 17574
edge_xy = np.array([node_xy[:,np.random.choice(range(number_of_nodes))] 
 if i%3 else [None, None] 
 for i in range(number_of_edges + number_of_edges//2)])
#Plotting the edges:
edge_trace = go.Scattergl(x=edge_xy[:,0], y=edge_xy[:,1], 
                          mode='lines', line=dict(width=0.5, color='#888'), hoverinfo='none')
fig = go.Figure(data=[node_trace, edge_trace], layout={'clickmode':'select+event'})
fig

Below you can see how the above minimal example draws the edges above the nodes. This is the version where hovering and clicking on nodes is functional:
plotly_layer_problem

@tobsecret tobsecret changed the title Scattergl Hover not active with hovermode="closest" but active with "compare" Scattergl Hover:closest and Click only active with first-plotted trace Jan 17, 2020
@emmanuelle
Copy link
Contributor

Hi @tobsecret , I tried to reproduce the problem but with your example I can click on nodes and they appear as in your screenshot above. What happens when you click on nodes? Nothing? Is there something printed in the javascript console?

@tobsecret
Copy link
Author

tobsecret commented Jan 21, 2020

Thanks for testing it out, @emmanuelle !

I am not sure I understand correctly. Did you copy the big code box from the example I gave above and got something similar to the screenshot?
In that case, the hovering and clicking works for me too, as is also shown in the screenshot. The problems arise for me, when I plot the layers in the reverse order. This is important for these network plots, as you can see in the example, most of the nodes are buried under the edges.

Does the hovering/ clicking still work when you construct the figure like this:

fig = go.Figure(data=[edge_trace, node_trace], layout={'clickmode':'select+event'})

@StefPetro
Copy link

Was there found any solution to this? I have the same problem, where only the first scatter plot is able to provide hoverinfo.
This means that the second scatter plot, which is the node_trace, is not able to show any hoverinfo.

In the example code for the network from the plotly website, if you remove hoverinfo=None from the edge_trace and try and plot it again, you get information for the edges. But if you then switch the ordering of the scatter plots in the go.Figure() to data=[node_trace, edge_trace], you don't get any hoverinfo from the edges, but from the nodes.

@tobsecret
Copy link
Author

That's interesting! I have just resorted to using go.Scatter and plotting smaller graphs, because frankly, the super large graphs were not that informative to begin with. I have not been working on this project for a while though, so maybe there's a new better solution available.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug something broken P3 backlog
Projects
None yet
Development

No branches or pull requests

4 participants