comparison env/lib/python3.9/site-packages/networkx/drawing/nx_pylab.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 """
2 **********
3 Matplotlib
4 **********
5
6 Draw networks with matplotlib.
7
8 See Also
9 --------
10
11 matplotlib: http://matplotlib.org/
12
13 pygraphviz: http://pygraphviz.github.io/
14
15 """
16 from numbers import Number
17 import networkx as nx
18 from networkx.drawing.layout import (
19 shell_layout,
20 circular_layout,
21 kamada_kawai_layout,
22 spectral_layout,
23 spring_layout,
24 random_layout,
25 planar_layout,
26 )
27
28 __all__ = [
29 "draw",
30 "draw_networkx",
31 "draw_networkx_nodes",
32 "draw_networkx_edges",
33 "draw_networkx_labels",
34 "draw_networkx_edge_labels",
35 "draw_circular",
36 "draw_kamada_kawai",
37 "draw_random",
38 "draw_spectral",
39 "draw_spring",
40 "draw_planar",
41 "draw_shell",
42 ]
43
44
45 def draw(G, pos=None, ax=None, **kwds):
46 """Draw the graph G with Matplotlib.
47
48 Draw the graph as a simple representation with no node
49 labels or edge labels and using the full Matplotlib figure area
50 and no axis labels by default. See draw_networkx() for more
51 full-featured drawing that allows title, axis labels etc.
52
53 Parameters
54 ----------
55 G : graph
56 A networkx graph
57
58 pos : dictionary, optional
59 A dictionary with nodes as keys and positions as values.
60 If not specified a spring layout positioning will be computed.
61 See :py:mod:`networkx.drawing.layout` for functions that
62 compute node positions.
63
64 ax : Matplotlib Axes object, optional
65 Draw the graph in specified Matplotlib axes.
66
67 kwds : optional keywords
68 See networkx.draw_networkx() for a description of optional keywords.
69
70 Examples
71 --------
72 >>> G = nx.dodecahedral_graph()
73 >>> nx.draw(G)
74 >>> nx.draw(G, pos=nx.spring_layout(G)) # use spring layout
75
76 See Also
77 --------
78 draw_networkx()
79 draw_networkx_nodes()
80 draw_networkx_edges()
81 draw_networkx_labels()
82 draw_networkx_edge_labels()
83
84 Notes
85 -----
86 This function has the same name as pylab.draw and pyplot.draw
87 so beware when using `from networkx import *`
88
89 since you might overwrite the pylab.draw function.
90
91 With pyplot use
92
93 >>> import matplotlib.pyplot as plt
94 >>> G = nx.dodecahedral_graph()
95 >>> nx.draw(G) # networkx draw()
96 >>> plt.draw() # pyplot draw()
97
98 Also see the NetworkX drawing examples at
99 https://networkx.github.io/documentation/latest/auto_examples/index.html
100 """
101 try:
102 import matplotlib.pyplot as plt
103 except ImportError as e:
104 raise ImportError("Matplotlib required for draw()") from e
105 except RuntimeError:
106 print("Matplotlib unable to open display")
107 raise
108
109 if ax is None:
110 cf = plt.gcf()
111 else:
112 cf = ax.get_figure()
113 cf.set_facecolor("w")
114 if ax is None:
115 if cf._axstack() is None:
116 ax = cf.add_axes((0, 0, 1, 1))
117 else:
118 ax = cf.gca()
119
120 if "with_labels" not in kwds:
121 kwds["with_labels"] = "labels" in kwds
122
123 draw_networkx(G, pos=pos, ax=ax, **kwds)
124 ax.set_axis_off()
125 plt.draw_if_interactive()
126 return
127
128
129 def draw_networkx(G, pos=None, arrows=True, with_labels=True, **kwds):
130 """Draw the graph G using Matplotlib.
131
132 Draw the graph with Matplotlib with options for node positions,
133 labeling, titles, and many other drawing features.
134 See draw() for simple drawing without labels or axes.
135
136 Parameters
137 ----------
138 G : graph
139 A networkx graph
140
141 pos : dictionary, optional
142 A dictionary with nodes as keys and positions as values.
143 If not specified a spring layout positioning will be computed.
144 See :py:mod:`networkx.drawing.layout` for functions that
145 compute node positions.
146
147 arrows : bool, optional (default=True)
148 For directed graphs, if True draw arrowheads.
149 Note: Arrows will be the same color as edges.
150
151 arrowstyle : str, optional (default='-|>')
152 For directed graphs, choose the style of the arrowsheads.
153 See :py:class: `matplotlib.patches.ArrowStyle` for more
154 options.
155
156 arrowsize : int, optional (default=10)
157 For directed graphs, choose the size of the arrow head head's length and
158 width. See :py:class: `matplotlib.patches.FancyArrowPatch` for attribute
159 `mutation_scale` for more info.
160
161 with_labels : bool, optional (default=True)
162 Set to True to draw labels on the nodes.
163
164 ax : Matplotlib Axes object, optional
165 Draw the graph in the specified Matplotlib axes.
166
167 nodelist : list, optional (default G.nodes())
168 Draw only specified nodes
169
170 edgelist : list, optional (default=G.edges())
171 Draw only specified edges
172
173 node_size : scalar or array, optional (default=300)
174 Size of nodes. If an array is specified it must be the
175 same length as nodelist.
176
177 node_color : color or array of colors (default='#1f78b4')
178 Node color. Can be a single color or a sequence of colors with the same
179 length as nodelist. Color can be string, or rgb (or rgba) tuple of
180 floats from 0-1. If numeric values are specified they will be
181 mapped to colors using the cmap and vmin,vmax parameters. See
182 matplotlib.scatter for more details.
183
184 node_shape : string, optional (default='o')
185 The shape of the node. Specification is as matplotlib.scatter
186 marker, one of 'so^>v<dph8'.
187
188 alpha : float, optional (default=None)
189 The node and edge transparency
190
191 cmap : Matplotlib colormap, optional (default=None)
192 Colormap for mapping intensities of nodes
193
194 vmin,vmax : float, optional (default=None)
195 Minimum and maximum for node colormap scaling
196
197 linewidths : [None | scalar | sequence]
198 Line width of symbol border (default =1.0)
199
200 width : float, optional (default=1.0)
201 Line width of edges
202
203 edge_color : color or array of colors (default='k')
204 Edge color. Can be a single color or a sequence of colors with the same
205 length as edgelist. Color can be string, or rgb (or rgba) tuple of
206 floats from 0-1. If numeric values are specified they will be
207 mapped to colors using the edge_cmap and edge_vmin,edge_vmax parameters.
208
209 edge_cmap : Matplotlib colormap, optional (default=None)
210 Colormap for mapping intensities of edges
211
212 edge_vmin,edge_vmax : floats, optional (default=None)
213 Minimum and maximum for edge colormap scaling
214
215 style : string, optional (default='solid')
216 Edge line style (solid|dashed|dotted,dashdot)
217
218 labels : dictionary, optional (default=None)
219 Node labels in a dictionary keyed by node of text labels
220
221 font_size : int, optional (default=12)
222 Font size for text labels
223
224 font_color : string, optional (default='k' black)
225 Font color string
226
227 font_weight : string, optional (default='normal')
228 Font weight
229
230 font_family : string, optional (default='sans-serif')
231 Font family
232
233 label : string, optional
234 Label for graph legend
235
236 kwds : optional keywords
237 See networkx.draw_networkx_nodes(), networkx.draw_networkx_edges(), and
238 networkx.draw_networkx_labels() for a description of optional keywords.
239
240 Notes
241 -----
242 For directed graphs, arrows are drawn at the head end. Arrows can be
243 turned off with keyword arrows=False.
244
245 Examples
246 --------
247 >>> G = nx.dodecahedral_graph()
248 >>> nx.draw(G)
249 >>> nx.draw(G, pos=nx.spring_layout(G)) # use spring layout
250
251 >>> import matplotlib.pyplot as plt
252 >>> limits = plt.axis("off") # turn of axis
253
254 Also see the NetworkX drawing examples at
255 https://networkx.github.io/documentation/latest/auto_examples/index.html
256
257 See Also
258 --------
259 draw()
260 draw_networkx_nodes()
261 draw_networkx_edges()
262 draw_networkx_labels()
263 draw_networkx_edge_labels()
264 """
265 try:
266 import matplotlib.pyplot as plt
267 except ImportError as e:
268 raise ImportError("Matplotlib required for draw()") from e
269 except RuntimeError:
270 print("Matplotlib unable to open display")
271 raise
272
273 valid_node_kwds = (
274 "nodelist",
275 "node_size",
276 "node_color",
277 "node_shape",
278 "alpha",
279 "cmap",
280 "vmin",
281 "vmax",
282 "ax",
283 "linewidths",
284 "edgecolors",
285 "label",
286 )
287
288 valid_edge_kwds = (
289 "edgelist",
290 "width",
291 "edge_color",
292 "style",
293 "alpha",
294 "arrowstyle",
295 "arrowsize",
296 "edge_cmap",
297 "edge_vmin",
298 "edge_vmax",
299 "ax",
300 "label",
301 "node_size",
302 "nodelist",
303 "node_shape",
304 "connectionstyle",
305 "min_source_margin",
306 "min_target_margin",
307 )
308
309 valid_label_kwds = (
310 "labels",
311 "font_size",
312 "font_color",
313 "font_family",
314 "font_weight",
315 "alpha",
316 "bbox",
317 "ax",
318 "horizontalalignment",
319 "verticalalignment",
320 )
321
322 valid_kwds = valid_node_kwds + valid_edge_kwds + valid_label_kwds
323
324 if any([k not in valid_kwds for k in kwds]):
325 invalid_args = ", ".join([k for k in kwds if k not in valid_kwds])
326 raise ValueError(f"Received invalid argument(s): {invalid_args}")
327
328 node_kwds = {k: v for k, v in kwds.items() if k in valid_node_kwds}
329 edge_kwds = {k: v for k, v in kwds.items() if k in valid_edge_kwds}
330 label_kwds = {k: v for k, v in kwds.items() if k in valid_label_kwds}
331
332 if pos is None:
333 pos = nx.drawing.spring_layout(G) # default to spring layout
334
335 draw_networkx_nodes(G, pos, **node_kwds)
336 draw_networkx_edges(G, pos, arrows=arrows, **edge_kwds)
337 if with_labels:
338 draw_networkx_labels(G, pos, **label_kwds)
339 plt.draw_if_interactive()
340
341
342 def draw_networkx_nodes(
343 G,
344 pos,
345 nodelist=None,
346 node_size=300,
347 node_color="#1f78b4",
348 node_shape="o",
349 alpha=None,
350 cmap=None,
351 vmin=None,
352 vmax=None,
353 ax=None,
354 linewidths=None,
355 edgecolors=None,
356 label=None,
357 ):
358 """Draw the nodes of the graph G.
359
360 This draws only the nodes of the graph G.
361
362 Parameters
363 ----------
364 G : graph
365 A networkx graph
366
367 pos : dictionary
368 A dictionary with nodes as keys and positions as values.
369 Positions should be sequences of length 2.
370
371 ax : Matplotlib Axes object, optional
372 Draw the graph in the specified Matplotlib axes.
373
374 nodelist : list, optional
375 Draw only specified nodes (default G.nodes())
376
377 node_size : scalar or array
378 Size of nodes (default=300). If an array is specified it must be the
379 same length as nodelist.
380
381 node_color : color or array of colors (default='#1f78b4')
382 Node color. Can be a single color or a sequence of colors with the same
383 length as nodelist. Color can be string, or rgb (or rgba) tuple of
384 floats from 0-1. If numeric values are specified they will be
385 mapped to colors using the cmap and vmin,vmax parameters. See
386 matplotlib.scatter for more details.
387
388 node_shape : string
389 The shape of the node. Specification is as matplotlib.scatter
390 marker, one of 'so^>v<dph8' (default='o').
391
392 alpha : float or array of floats
393 The node transparency. This can be a single alpha value (default=None),
394 in which case it will be applied to all the nodes of color. Otherwise,
395 if it is an array, the elements of alpha will be applied to the colors
396 in order (cycling through alpha multiple times if necessary).
397
398 cmap : Matplotlib colormap
399 Colormap for mapping intensities of nodes (default=None)
400
401 vmin,vmax : floats
402 Minimum and maximum for node colormap scaling (default=None)
403
404 linewidths : [None | scalar | sequence]
405 Line width of symbol border (default =1.0)
406
407 edgecolors : [None | scalar | sequence]
408 Colors of node borders (default = node_color)
409
410 label : [None| string]
411 Label for legend
412
413 Returns
414 -------
415 matplotlib.collections.PathCollection
416 `PathCollection` of the nodes.
417
418 Examples
419 --------
420 >>> G = nx.dodecahedral_graph()
421 >>> nodes = nx.draw_networkx_nodes(G, pos=nx.spring_layout(G))
422
423 Also see the NetworkX drawing examples at
424 https://networkx.github.io/documentation/latest/auto_examples/index.html
425
426 See Also
427 --------
428 draw()
429 draw_networkx()
430 draw_networkx_edges()
431 draw_networkx_labels()
432 draw_networkx_edge_labels()
433 """
434 from collections.abc import Iterable
435
436 try:
437 import matplotlib.pyplot as plt
438 from matplotlib.collections import PathCollection
439 import numpy as np
440 except ImportError as e:
441 raise ImportError("Matplotlib required for draw()") from e
442 except RuntimeError:
443 print("Matplotlib unable to open display")
444 raise
445
446 if ax is None:
447 ax = plt.gca()
448
449 if nodelist is None:
450 nodelist = list(G)
451
452 if len(nodelist) == 0: # empty nodelist, no drawing
453 return PathCollection(None)
454
455 try:
456 xy = np.asarray([pos[v] for v in nodelist])
457 except KeyError as e:
458 raise nx.NetworkXError(f"Node {e} has no position.") from e
459 except ValueError as e:
460 raise nx.NetworkXError("Bad value in node positions.") from e
461
462 if isinstance(alpha, Iterable):
463 node_color = apply_alpha(node_color, alpha, nodelist, cmap, vmin, vmax)
464 alpha = None
465
466 node_collection = ax.scatter(
467 xy[:, 0],
468 xy[:, 1],
469 s=node_size,
470 c=node_color,
471 marker=node_shape,
472 cmap=cmap,
473 vmin=vmin,
474 vmax=vmax,
475 alpha=alpha,
476 linewidths=linewidths,
477 edgecolors=edgecolors,
478 label=label,
479 )
480 ax.tick_params(
481 axis="both",
482 which="both",
483 bottom=False,
484 left=False,
485 labelbottom=False,
486 labelleft=False,
487 )
488
489 node_collection.set_zorder(2)
490 return node_collection
491
492
493 def draw_networkx_edges(
494 G,
495 pos,
496 edgelist=None,
497 width=1.0,
498 edge_color="k",
499 style="solid",
500 alpha=None,
501 arrowstyle="-|>",
502 arrowsize=10,
503 edge_cmap=None,
504 edge_vmin=None,
505 edge_vmax=None,
506 ax=None,
507 arrows=True,
508 label=None,
509 node_size=300,
510 nodelist=None,
511 node_shape="o",
512 connectionstyle=None,
513 min_source_margin=0,
514 min_target_margin=0,
515 ):
516 """Draw the edges of the graph G.
517
518 This draws only the edges of the graph G.
519
520 Parameters
521 ----------
522 G : graph
523 A networkx graph
524
525 pos : dictionary
526 A dictionary with nodes as keys and positions as values.
527 Positions should be sequences of length 2.
528
529 edgelist : collection of edge tuples
530 Draw only specified edges(default=G.edges())
531
532 width : float, or array of floats
533 Line width of edges (default=1.0)
534
535 edge_color : color or array of colors (default='k')
536 Edge color. Can be a single color or a sequence of colors with the same
537 length as edgelist. Color can be string, or rgb (or rgba) tuple of
538 floats from 0-1. If numeric values are specified they will be
539 mapped to colors using the edge_cmap and edge_vmin,edge_vmax parameters.
540
541 style : string
542 Edge line style (default='solid') (solid|dashed|dotted,dashdot)
543
544 alpha : float
545 The edge transparency (default=None)
546
547 edge_ cmap : Matplotlib colormap
548 Colormap for mapping intensities of edges (default=None)
549
550 edge_vmin,edge_vmax : floats
551 Minimum and maximum for edge colormap scaling (default=None)
552
553 ax : Matplotlib Axes object, optional
554 Draw the graph in the specified Matplotlib axes.
555
556 arrows : bool, optional (default=True)
557 For directed graphs, if True draw arrowheads.
558 Note: Arrows will be the same color as edges.
559
560 arrowstyle : str, optional (default='-|>')
561 For directed graphs, choose the style of the arrow heads.
562 See :py:class: `matplotlib.patches.ArrowStyle` for more
563 options.
564
565 arrowsize : int, optional (default=10)
566 For directed graphs, choose the size of the arrow head head's length and
567 width. See :py:class: `matplotlib.patches.FancyArrowPatch` for attribute
568 `mutation_scale` for more info.
569
570 connectionstyle : str, optional (default=None)
571 Pass the connectionstyle parameter to create curved arc of rounding
572 radius rad. For example, connectionstyle='arc3,rad=0.2'.
573 See :py:class: `matplotlib.patches.ConnectionStyle` and
574 :py:class: `matplotlib.patches.FancyArrowPatch` for more info.
575
576 label : [None| string]
577 Label for legend
578
579 min_source_margin : int, optional (default=0)
580 The minimum margin (gap) at the begining of the edge at the source.
581
582 min_target_margin : int, optional (default=0)
583 The minimum margin (gap) at the end of the edge at the target.
584
585 Returns
586 -------
587 matplotlib.collection.LineCollection
588 `LineCollection` of the edges
589
590 list of matplotlib.patches.FancyArrowPatch
591 `FancyArrowPatch` instances of the directed edges
592
593 Depending whether the drawing includes arrows or not.
594
595 Notes
596 -----
597 For directed graphs, arrows are drawn at the head end. Arrows can be
598 turned off with keyword arrows=False. Be sure to include `node_size` as a
599 keyword argument; arrows are drawn considering the size of nodes.
600
601 Examples
602 --------
603 >>> G = nx.dodecahedral_graph()
604 >>> edges = nx.draw_networkx_edges(G, pos=nx.spring_layout(G))
605
606 >>> G = nx.DiGraph()
607 >>> G.add_edges_from([(1, 2), (1, 3), (2, 3)])
608 >>> arcs = nx.draw_networkx_edges(G, pos=nx.spring_layout(G))
609 >>> alphas = [0.3, 0.4, 0.5]
610 >>> for i, arc in enumerate(arcs): # change alpha values of arcs
611 ... arc.set_alpha(alphas[i])
612
613 Also see the NetworkX drawing examples at
614 https://networkx.github.io/documentation/latest/auto_examples/index.html
615
616 See Also
617 --------
618 draw()
619 draw_networkx()
620 draw_networkx_nodes()
621 draw_networkx_labels()
622 draw_networkx_edge_labels()
623 """
624 try:
625 import matplotlib.pyplot as plt
626 from matplotlib.colors import colorConverter, Colormap, Normalize
627 from matplotlib.collections import LineCollection
628 from matplotlib.patches import FancyArrowPatch
629 import numpy as np
630 except ImportError as e:
631 raise ImportError("Matplotlib required for draw()") from e
632 except RuntimeError:
633 print("Matplotlib unable to open display")
634 raise
635
636 if ax is None:
637 ax = plt.gca()
638
639 if edgelist is None:
640 edgelist = list(G.edges())
641
642 if len(edgelist) == 0: # no edges!
643 if not G.is_directed() or not arrows:
644 return LineCollection(None)
645 else:
646 return []
647
648 if nodelist is None:
649 nodelist = list(G.nodes())
650
651 # FancyArrowPatch handles color=None different from LineCollection
652 if edge_color is None:
653 edge_color = "k"
654
655 # set edge positions
656 edge_pos = np.asarray([(pos[e[0]], pos[e[1]]) for e in edgelist])
657
658 # Check if edge_color is an array of floats and map to edge_cmap.
659 # This is the only case handled differently from matplotlib
660 if (
661 np.iterable(edge_color)
662 and (len(edge_color) == len(edge_pos))
663 and np.alltrue([isinstance(c, Number) for c in edge_color])
664 ):
665 if edge_cmap is not None:
666 assert isinstance(edge_cmap, Colormap)
667 else:
668 edge_cmap = plt.get_cmap()
669 if edge_vmin is None:
670 edge_vmin = min(edge_color)
671 if edge_vmax is None:
672 edge_vmax = max(edge_color)
673 color_normal = Normalize(vmin=edge_vmin, vmax=edge_vmax)
674 edge_color = [edge_cmap(color_normal(e)) for e in edge_color]
675
676 if not G.is_directed() or not arrows:
677 edge_collection = LineCollection(
678 edge_pos,
679 colors=edge_color,
680 linewidths=width,
681 antialiaseds=(1,),
682 linestyle=style,
683 transOffset=ax.transData,
684 alpha=alpha,
685 )
686
687 edge_collection.set_cmap(edge_cmap)
688 edge_collection.set_clim(edge_vmin, edge_vmax)
689
690 edge_collection.set_zorder(1) # edges go behind nodes
691 edge_collection.set_label(label)
692 ax.add_collection(edge_collection)
693
694 return edge_collection
695
696 arrow_collection = None
697
698 if G.is_directed() and arrows:
699 # Note: Waiting for someone to implement arrow to intersection with
700 # marker. Meanwhile, this works well for polygons with more than 4
701 # sides and circle.
702
703 def to_marker_edge(marker_size, marker):
704 if marker in "s^>v<d": # `large` markers need extra space
705 return np.sqrt(2 * marker_size) / 2
706 else:
707 return np.sqrt(marker_size) / 2
708
709 # Draw arrows with `matplotlib.patches.FancyarrowPatch`
710 arrow_collection = []
711 mutation_scale = arrowsize # scale factor of arrow head
712
713 # FancyArrowPatch doesn't handle color strings
714 arrow_colors = colorConverter.to_rgba_array(edge_color, alpha)
715 for i, (src, dst) in enumerate(edge_pos):
716 x1, y1 = src
717 x2, y2 = dst
718 shrink_source = 0 # space from source to tail
719 shrink_target = 0 # space from head to target
720 if np.iterable(node_size): # many node sizes
721 source, target = edgelist[i][:2]
722 source_node_size = node_size[nodelist.index(source)]
723 target_node_size = node_size[nodelist.index(target)]
724 shrink_source = to_marker_edge(source_node_size, node_shape)
725 shrink_target = to_marker_edge(target_node_size, node_shape)
726 else:
727 shrink_source = shrink_target = to_marker_edge(node_size, node_shape)
728
729 if shrink_source < min_source_margin:
730 shrink_source = min_source_margin
731
732 if shrink_target < min_target_margin:
733 shrink_target = min_target_margin
734
735 if len(arrow_colors) == len(edge_pos):
736 arrow_color = arrow_colors[i]
737 elif len(arrow_colors) == 1:
738 arrow_color = arrow_colors[0]
739 else: # Cycle through colors
740 arrow_color = arrow_colors[i % len(arrow_colors)]
741
742 if np.iterable(width):
743 if len(width) == len(edge_pos):
744 line_width = width[i]
745 else:
746 line_width = width[i % len(width)]
747 else:
748 line_width = width
749
750 arrow = FancyArrowPatch(
751 (x1, y1),
752 (x2, y2),
753 arrowstyle=arrowstyle,
754 shrinkA=shrink_source,
755 shrinkB=shrink_target,
756 mutation_scale=mutation_scale,
757 color=arrow_color,
758 linewidth=line_width,
759 connectionstyle=connectionstyle,
760 linestyle=style,
761 zorder=1,
762 ) # arrows go behind nodes
763
764 # There seems to be a bug in matplotlib to make collections of
765 # FancyArrowPatch instances. Until fixed, the patches are added
766 # individually to the axes instance.
767 arrow_collection.append(arrow)
768 ax.add_patch(arrow)
769
770 # update view
771 minx = np.amin(np.ravel(edge_pos[:, :, 0]))
772 maxx = np.amax(np.ravel(edge_pos[:, :, 0]))
773 miny = np.amin(np.ravel(edge_pos[:, :, 1]))
774 maxy = np.amax(np.ravel(edge_pos[:, :, 1]))
775
776 w = maxx - minx
777 h = maxy - miny
778 padx, pady = 0.05 * w, 0.05 * h
779 corners = (minx - padx, miny - pady), (maxx + padx, maxy + pady)
780 ax.update_datalim(corners)
781 ax.autoscale_view()
782
783 ax.tick_params(
784 axis="both",
785 which="both",
786 bottom=False,
787 left=False,
788 labelbottom=False,
789 labelleft=False,
790 )
791
792 return arrow_collection
793
794
795 def draw_networkx_labels(
796 G,
797 pos,
798 labels=None,
799 font_size=12,
800 font_color="k",
801 font_family="sans-serif",
802 font_weight="normal",
803 alpha=None,
804 bbox=None,
805 horizontalalignment="center",
806 verticalalignment="center",
807 ax=None,
808 ):
809 """Draw node labels on the graph G.
810
811 Parameters
812 ----------
813 G : graph
814 A networkx graph
815
816 pos : dictionary
817 A dictionary with nodes as keys and positions as values.
818 Positions should be sequences of length 2.
819
820 labels : dictionary, optional (default=None)
821 Node labels in a dictionary keyed by node of text labels
822 Node-keys in labels should appear as keys in `pos`.
823 If needed use: `{n:lab for n,lab in labels.items() if n in pos}`
824
825 font_size : int
826 Font size for text labels (default=12)
827
828 font_color : string
829 Font color string (default='k' black)
830
831 font_family : string
832 Font family (default='sans-serif')
833
834 font_weight : string
835 Font weight (default='normal')
836
837 alpha : float or None
838 The text transparency (default=None)
839
840 horizontalalignment : {'center', 'right', 'left'}
841 Horizontal alignment (default='center')
842
843 verticalalignment : {'center', 'top', 'bottom', 'baseline', 'center_baseline'}
844 Vertical alignment (default='center')
845
846 ax : Matplotlib Axes object, optional
847 Draw the graph in the specified Matplotlib axes.
848
849
850 Returns
851 -------
852 dict
853 `dict` of labels keyed on the nodes
854
855 Examples
856 --------
857 >>> G = nx.dodecahedral_graph()
858 >>> labels = nx.draw_networkx_labels(G, pos=nx.spring_layout(G))
859
860 Also see the NetworkX drawing examples at
861 https://networkx.github.io/documentation/latest/auto_examples/index.html
862
863 See Also
864 --------
865 draw()
866 draw_networkx()
867 draw_networkx_nodes()
868 draw_networkx_edges()
869 draw_networkx_edge_labels()
870 """
871 try:
872 import matplotlib.pyplot as plt
873 except ImportError as e:
874 raise ImportError("Matplotlib required for draw()") from e
875 except RuntimeError:
876 print("Matplotlib unable to open display")
877 raise
878
879 if ax is None:
880 ax = plt.gca()
881
882 if labels is None:
883 labels = {n: n for n in G.nodes()}
884
885 text_items = {} # there is no text collection so we'll fake one
886 for n, label in labels.items():
887 (x, y) = pos[n]
888 if not isinstance(label, str):
889 label = str(label) # this makes "1" and 1 labeled the same
890 t = ax.text(
891 x,
892 y,
893 label,
894 size=font_size,
895 color=font_color,
896 family=font_family,
897 weight=font_weight,
898 alpha=alpha,
899 horizontalalignment=horizontalalignment,
900 verticalalignment=verticalalignment,
901 transform=ax.transData,
902 bbox=bbox,
903 clip_on=True,
904 )
905 text_items[n] = t
906
907 ax.tick_params(
908 axis="both",
909 which="both",
910 bottom=False,
911 left=False,
912 labelbottom=False,
913 labelleft=False,
914 )
915
916 return text_items
917
918
919 def draw_networkx_edge_labels(
920 G,
921 pos,
922 edge_labels=None,
923 label_pos=0.5,
924 font_size=10,
925 font_color="k",
926 font_family="sans-serif",
927 font_weight="normal",
928 alpha=None,
929 bbox=None,
930 horizontalalignment="center",
931 verticalalignment="center",
932 ax=None,
933 rotate=True,
934 ):
935 """Draw edge labels.
936
937 Parameters
938 ----------
939 G : graph
940 A networkx graph
941
942 pos : dictionary
943 A dictionary with nodes as keys and positions as values.
944 Positions should be sequences of length 2.
945
946 ax : Matplotlib Axes object, optional
947 Draw the graph in the specified Matplotlib axes.
948
949 alpha : float or None
950 The text transparency (default=None)
951
952 edge_labels : dictionary
953 Edge labels in a dictionary keyed by edge two-tuple of text
954 labels (default=None). Only labels for the keys in the dictionary
955 are drawn.
956
957 label_pos : float
958 Position of edge label along edge (0=head, 0.5=center, 1=tail)
959
960 font_size : int
961 Font size for text labels (default=12)
962
963 font_color : string
964 Font color string (default='k' black)
965
966 font_weight : string
967 Font weight (default='normal')
968
969 font_family : string
970 Font family (default='sans-serif')
971
972 bbox : Matplotlib bbox
973 Specify text box shape and colors.
974
975 clip_on : bool
976 Turn on clipping at axis boundaries (default=True)
977
978 horizontalalignment : {'center', 'right', 'left'}
979 Horizontal alignment (default='center')
980
981 verticalalignment : {'center', 'top', 'bottom', 'baseline', 'center_baseline'}
982 Vertical alignment (default='center')
983
984 ax : Matplotlib Axes object, optional
985 Draw the graph in the specified Matplotlib axes.
986
987 Returns
988 -------
989 dict
990 `dict` of labels keyed on the edges
991
992 Examples
993 --------
994 >>> G = nx.dodecahedral_graph()
995 >>> edge_labels = nx.draw_networkx_edge_labels(G, pos=nx.spring_layout(G))
996
997 Also see the NetworkX drawing examples at
998 https://networkx.github.io/documentation/latest/auto_examples/index.html
999
1000 See Also
1001 --------
1002 draw()
1003 draw_networkx()
1004 draw_networkx_nodes()
1005 draw_networkx_edges()
1006 draw_networkx_labels()
1007 """
1008 try:
1009 import matplotlib.pyplot as plt
1010 import numpy as np
1011 except ImportError as e:
1012 raise ImportError("Matplotlib required for draw()") from e
1013 except RuntimeError:
1014 print("Matplotlib unable to open display")
1015 raise
1016
1017 if ax is None:
1018 ax = plt.gca()
1019 if edge_labels is None:
1020 labels = {(u, v): d for u, v, d in G.edges(data=True)}
1021 else:
1022 labels = edge_labels
1023 text_items = {}
1024 for (n1, n2), label in labels.items():
1025 (x1, y1) = pos[n1]
1026 (x2, y2) = pos[n2]
1027 (x, y) = (
1028 x1 * label_pos + x2 * (1.0 - label_pos),
1029 y1 * label_pos + y2 * (1.0 - label_pos),
1030 )
1031
1032 if rotate:
1033 # in degrees
1034 angle = np.arctan2(y2 - y1, x2 - x1) / (2.0 * np.pi) * 360
1035 # make label orientation "right-side-up"
1036 if angle > 90:
1037 angle -= 180
1038 if angle < -90:
1039 angle += 180
1040 # transform data coordinate angle to screen coordinate angle
1041 xy = np.array((x, y))
1042 trans_angle = ax.transData.transform_angles(
1043 np.array((angle,)), xy.reshape((1, 2))
1044 )[0]
1045 else:
1046 trans_angle = 0.0
1047 # use default box of white with white border
1048 if bbox is None:
1049 bbox = dict(boxstyle="round", ec=(1.0, 1.0, 1.0), fc=(1.0, 1.0, 1.0))
1050 if not isinstance(label, str):
1051 label = str(label) # this makes "1" and 1 labeled the same
1052
1053 t = ax.text(
1054 x,
1055 y,
1056 label,
1057 size=font_size,
1058 color=font_color,
1059 family=font_family,
1060 weight=font_weight,
1061 alpha=alpha,
1062 horizontalalignment=horizontalalignment,
1063 verticalalignment=verticalalignment,
1064 rotation=trans_angle,
1065 transform=ax.transData,
1066 bbox=bbox,
1067 zorder=1,
1068 clip_on=True,
1069 )
1070 text_items[(n1, n2)] = t
1071
1072 ax.tick_params(
1073 axis="both",
1074 which="both",
1075 bottom=False,
1076 left=False,
1077 labelbottom=False,
1078 labelleft=False,
1079 )
1080
1081 return text_items
1082
1083
1084 def draw_circular(G, **kwargs):
1085 """Draw the graph G with a circular layout.
1086
1087 Parameters
1088 ----------
1089 G : graph
1090 A networkx graph
1091
1092 kwargs : optional keywords
1093 See networkx.draw_networkx() for a description of optional keywords,
1094 with the exception of the pos parameter which is not used by this
1095 function.
1096 """
1097 draw(G, circular_layout(G), **kwargs)
1098
1099
1100 def draw_kamada_kawai(G, **kwargs):
1101 """Draw the graph G with a Kamada-Kawai force-directed layout.
1102
1103 Parameters
1104 ----------
1105 G : graph
1106 A networkx graph
1107
1108 kwargs : optional keywords
1109 See networkx.draw_networkx() for a description of optional keywords,
1110 with the exception of the pos parameter which is not used by this
1111 function.
1112 """
1113 draw(G, kamada_kawai_layout(G), **kwargs)
1114
1115
1116 def draw_random(G, **kwargs):
1117 """Draw the graph G with a random layout.
1118
1119 Parameters
1120 ----------
1121 G : graph
1122 A networkx graph
1123
1124 kwargs : optional keywords
1125 See networkx.draw_networkx() for a description of optional keywords,
1126 with the exception of the pos parameter which is not used by this
1127 function.
1128 """
1129 draw(G, random_layout(G), **kwargs)
1130
1131
1132 def draw_spectral(G, **kwargs):
1133 """Draw the graph G with a spectral 2D layout.
1134
1135 Using the unnormalized Laplacian, the layout shows possible clusters of
1136 nodes which are an approximation of the ratio cut. The positions are the
1137 entries of the second and third eigenvectors corresponding to the
1138 ascending eigenvalues starting from the second one.
1139
1140 Parameters
1141 ----------
1142 G : graph
1143 A networkx graph
1144
1145 kwargs : optional keywords
1146 See networkx.draw_networkx() for a description of optional keywords,
1147 with the exception of the pos parameter which is not used by this
1148 function.
1149 """
1150 draw(G, spectral_layout(G), **kwargs)
1151
1152
1153 def draw_spring(G, **kwargs):
1154 """Draw the graph G with a spring layout.
1155
1156 Parameters
1157 ----------
1158 G : graph
1159 A networkx graph
1160
1161 kwargs : optional keywords
1162 See networkx.draw_networkx() for a description of optional keywords,
1163 with the exception of the pos parameter which is not used by this
1164 function.
1165 """
1166 draw(G, spring_layout(G), **kwargs)
1167
1168
1169 def draw_shell(G, **kwargs):
1170 """Draw networkx graph with shell layout.
1171
1172 Parameters
1173 ----------
1174 G : graph
1175 A networkx graph
1176
1177 kwargs : optional keywords
1178 See networkx.draw_networkx() for a description of optional keywords,
1179 with the exception of the pos parameter which is not used by this
1180 function.
1181 """
1182 nlist = kwargs.get("nlist", None)
1183 if nlist is not None:
1184 del kwargs["nlist"]
1185 draw(G, shell_layout(G, nlist=nlist), **kwargs)
1186
1187
1188 def draw_planar(G, **kwargs):
1189 """Draw a planar networkx graph with planar layout.
1190
1191 Parameters
1192 ----------
1193 G : graph
1194 A planar networkx graph
1195
1196 kwargs : optional keywords
1197 See networkx.draw_networkx() for a description of optional keywords,
1198 with the exception of the pos parameter which is not used by this
1199 function.
1200 """
1201 draw(G, planar_layout(G), **kwargs)
1202
1203
1204 def apply_alpha(colors, alpha, elem_list, cmap=None, vmin=None, vmax=None):
1205 """Apply an alpha (or list of alphas) to the colors provided.
1206
1207 Parameters
1208 ----------
1209
1210 colors : color string, or array of floats
1211 Color of element. Can be a single color format string (default='r'),
1212 or a sequence of colors with the same length as nodelist.
1213 If numeric values are specified they will be mapped to
1214 colors using the cmap and vmin,vmax parameters. See
1215 matplotlib.scatter for more details.
1216
1217 alpha : float or array of floats
1218 Alpha values for elements. This can be a single alpha value, in
1219 which case it will be applied to all the elements of color. Otherwise,
1220 if it is an array, the elements of alpha will be applied to the colors
1221 in order (cycling through alpha multiple times if necessary).
1222
1223 elem_list : array of networkx objects
1224 The list of elements which are being colored. These could be nodes,
1225 edges or labels.
1226
1227 cmap : matplotlib colormap
1228 Color map for use if colors is a list of floats corresponding to points
1229 on a color mapping.
1230
1231 vmin, vmax : float
1232 Minimum and maximum values for normalizing colors if a color mapping is
1233 used.
1234
1235 Returns
1236 -------
1237
1238 rgba_colors : numpy ndarray
1239 Array containing RGBA format values for each of the node colours.
1240
1241 """
1242 from itertools import islice, cycle
1243
1244 try:
1245 import numpy as np
1246 from matplotlib.colors import colorConverter
1247 import matplotlib.cm as cm
1248 except ImportError as e:
1249 raise ImportError("Matplotlib required for draw()") from e
1250
1251 # If we have been provided with a list of numbers as long as elem_list,
1252 # apply the color mapping.
1253 if len(colors) == len(elem_list) and isinstance(colors[0], Number):
1254 mapper = cm.ScalarMappable(cmap=cmap)
1255 mapper.set_clim(vmin, vmax)
1256 rgba_colors = mapper.to_rgba(colors)
1257 # Otherwise, convert colors to matplotlib's RGB using the colorConverter
1258 # object. These are converted to numpy ndarrays to be consistent with the
1259 # to_rgba method of ScalarMappable.
1260 else:
1261 try:
1262 rgba_colors = np.array([colorConverter.to_rgba(colors)])
1263 except ValueError:
1264 rgba_colors = np.array([colorConverter.to_rgba(color) for color in colors])
1265 # Set the final column of the rgba_colors to have the relevant alpha values
1266 try:
1267 # If alpha is longer than the number of colors, resize to the number of
1268 # elements. Also, if rgba_colors.size (the number of elements of
1269 # rgba_colors) is the same as the number of elements, resize the array,
1270 # to avoid it being interpreted as a colormap by scatter()
1271 if len(alpha) > len(rgba_colors) or rgba_colors.size == len(elem_list):
1272 rgba_colors = np.resize(rgba_colors, (len(elem_list), 4))
1273 rgba_colors[1:, 0] = rgba_colors[0, 0]
1274 rgba_colors[1:, 1] = rgba_colors[0, 1]
1275 rgba_colors[1:, 2] = rgba_colors[0, 2]
1276 rgba_colors[:, 3] = list(islice(cycle(alpha), len(rgba_colors)))
1277 except TypeError:
1278 rgba_colors[:, -1] = alpha
1279 return rgba_colors