1+ from typing import Union
12import numpy as np
23import pandas as pd
34import matplotlib as mpl
4445 )
4546)
4647class NetworkArtist (mpl .artist .Artist ):
47- def __init__ (self , network , layout = None ):
48+ def __init__ (
49+ self ,
50+ network ,
51+ layout = None ,
52+ vertex_labels : Union [None , list , dict , pd .Series ] = None ,
53+ ):
54+ """Network container artist that groups all plotting elements.
55+
56+ Parameters:
57+ network (networkx.Graph or igraph.Graph): The network to plot.
58+ layout (array-like): The layout of the network. If None, this function will attempt to
59+ infer the layout from the network metadata, using heuristics. If that fails, an
60+ exception will be raised.
61+ vertex_labels (list, dict, or pandas.Series): The labels for the vertices. If None, no vertex labels
62+ will be drawn. If a list, the labels are taken from the list. If a dict, the keys
63+ should be the vertex IDs and the values should be the labels.
64+ """
4865 super ().__init__ ()
4966
5067 self .network = network
51- self ._ipx_internal_data = _create_internal_data (network , layout )
68+ self ._ipx_internal_data = _create_internal_data (
69+ network , layout , vertex_labels = vertex_labels
70+ )
5271 self ._clear_state ()
5372
5473 def _clear_state (self ):
@@ -176,6 +195,22 @@ def _add_edges(self):
176195 return self ._add_directed_edges ()
177196 return self ._add_undirected_edges ()
178197
198+ def _add_vertex_labels (self ):
199+ """Draw vertex labels."""
200+ label_style = get_style (".vertex_label" )
201+
202+ texts = []
203+ vertex_labels = self ._ipx_internal_data ["vertex_df" ]["label" ]
204+ for offset , label in zip (self ._vertices ._offsets , vertex_labels ):
205+ text = mpl .text .Text (
206+ offset [0 ],
207+ offset [1 ],
208+ label ,
209+ ** label_style ,
210+ )
211+ texts .append (text )
212+ self ._vertex_labels = texts
213+
179214 def _add_directed_edges (self ):
180215 """Draw directed edges."""
181216 edge_style = get_style (".edge" )
@@ -307,7 +342,8 @@ def _process(self):
307342 # in that order will get drawn on top (vis-a-vis zorder).
308343 self ._add_vertices ()
309344 self ._add_edges ()
310- # self._draw_vertex_labels()
345+ if "label" in self ._ipx_internal_data ["vertex_df" ].columns :
346+ self ._draw_vertex_labels ()
311347 # self._draw_edge_labels()
312348
313349 # TODO: callbacks for stale vertices/edges
@@ -348,7 +384,7 @@ def draw(self, renderer, *args, **kwds):
348384
349385
350386# INTERNAL ROUTINES
351- def _create_internal_data (network , layout = None ):
387+ def _create_internal_data (network , layout = None , vertex_labels = None ):
352388 """Create internal data for the network."""
353389 nl = network_library (network )
354390 directed = detect_directedness (network )
@@ -363,6 +399,10 @@ def _create_internal_data(network, layout=None):
363399 for i , layouti in enumerate (layout .T ):
364400 vertex_df [f"_ipx_layout_{ i } " ] = layouti
365401
402+ # Vertex labels
403+ if vertex_labels is None :
404+ vertex_df ["label" ] = vertex_labels
405+
366406 # Edges are a list of tuples, because of multiedges
367407 tmp = []
368408 for u , v , d in network .edges .data ():
@@ -382,6 +422,10 @@ def _create_internal_data(network, layout=None):
382422 layout , columns = [f"_ipx_layout_{ i } " for i in range (ndim )]
383423 )
384424
425+ # Vertex labels
426+ if vertex_labels is None :
427+ vertex_df ["label" ] = vertex_labels
428+
385429 # Edges are a list of tuples, because of multiedges
386430 tmp = []
387431 for edge in network .es :
0 commit comments