Reputation: 33
I'm trying to create a skill tree using networkx, but due to the length of descriptions, it's not feasible to have permanent labels/annotations with the ability descriptions, so was hoping to be able to have them show up on mouseover.
The gist of the code is:
G = nx.Graph()
G.add_node('A', name='Node A', description='This is node A')
G.add_node('B', name='Node B', description='This is node B')
G.add_edge('A', 'B')
pos = nx.kamada_kawai_layout(G)
col_a='#000000'
col_b='#111111'
colours={'A':col_a, 'B':col_b}
fig, ax = plt.subplots(figsize=(20, 20))
nx.draw(G, pos, node_color=[colors[node] for node in G.nodes()], with_labels=False, node_size=2700)
node_labels = nx.get_node_attributes(G, 'name')
nx.draw_networkx_labels(G, pos, labels=node_labels, font_size=9)
ax.set_facecolor("#666666")
mpld3.save_html(fig,"Skill tree.html")
I had some help in the comments that has since been deleted, the code that was given is below, but it doesn't provide the mouseover descriptions. So I'm just putting it here in case it's easily fixable and someone can help from it:
class NodeDescription(plugins.PluginBase):
JAVASCRIPT = """
mpld3.register_plugin("node_description", NodeDescription);
NodeDescription.prototype = Object.create(mpld3.Plugin.prototype);
NodeDescription.prototype.constructor = NodeDescription;
function NodeDescription(fig, props){
mpld3.Plugin.call(this, fig, props);
};
NodeDescription.prototype.draw = function(){
var tooltip = this.props.tooltip;
for (var i = 0; i < this.fig.axes.length; i++){
var ax = this.fig.axes[i];
ax.elements.push(mpld3.path_tooltip(tooltip));
}
}
"""
def __init__(self, points, tooltip, **kwargs):
self.points = points
self.tooltip = tooltip
self.metadata = kwargs
def get_dict(self):
x = [point[0] for point in self.points]
y = [point[1] for point in self.points]
return {'type': 'node_description', 'x': x, 'y': y, 'tooltip': self.tooltip, 'metadata': self.metadata}
def get_javascript(self):
return self.JAVASCRIPT
node_positions = [(x, y) for x, y in pos.values()]
node_descriptions = nx.get_node_attributes(G, 'description')
plugins.connect(fig, NodeDescription(node_positions, tooltip=list(node_descriptions.values())))
Upvotes: 3
Views: 787
Reputation: 1374
I really encourage you to look into Bokeh. It's a python library that has a ton of options and does exactly what you need.
I wrote a very basic code to render the graph, but know that you can really make it your own and change the nodes' and edges' colors & size based on attributes.
First you need to install it:
pip install bokeh
And here's the code:
import networkx as nx
from bokeh.models import Circle
from bokeh.plotting import figure, output_file
from bokeh.plotting import from_networkx
from bokeh.io import save
G = nx.Graph()
G.add_node('A', name='Node A', description='This is node A')
G.add_node('B', name='Node B', description='This is node B')
G.add_edge('A', 'B')
# there are multiple positioning algos, you should play around with them
pos = nx.kamada_kawai_layout(G)
HOVER_TOOLTIPS = [
("name", "@name"),
("description", "@description"),
]
# Create a plot — set dimensions, toolbar, and title
plot = figure(tooltips=HOVER_TOOLTIPS,
tools="pan,wheel_zoom,save,reset", active_scroll='wheel_zoom', title='my plot', sizing_mode='stretch_both', width=1000, height=1000)
network_graph = from_networkx(G, nx.spring_layout, scale=10, center=(0, 0), pos=pos)
network_graph.node_renderer.glyph = Circle(size=50, fill_color='blue')
plot.renderers.append(network_graph)
output_file(filename=str('test.html'))
save(plot, filename='test.html')
And here some pictures of the result:
Then when you hover with your mouse:
Upvotes: 1