Networks¶
The film's code
import manimgx as m
class NetworksHero(m.Scene):
def construct(self) -> None:
vertices = [1, 2, 3, 4, 5, 6]
edges = [(1, 2), (2, 3), (3, 1), (3, 4), (4, 5), (5, 6), (6, 4)]
graph = m.Graph(vertices, edges, layout="spring", labels=True, layout_scale=3)
self.play(m.Create(graph))
self.play(graph.animate.change_layout("circular", layout_scale=3))
self.wait()
A network is vertices, joined by edges: a graph, as graph theory says it. (For the graph of
a function, see Plotting.) Graph joins its vertices
with lines, DiGraph with arrows, from each edge's first vertex to its
second. Each lays its vertices out for you (layout="spring", "circular", "tree", …),
or where you place them; a vertex is a dot unless you give another mobject.
Both can do what follows: add and remove vertices and edges, change their layout, and read a network from NetworkX.
Graph ¶
Code
import manimgx as m
class GraphExample(m.Scene):
def construct(self) -> None:
vertices = [1, 2, 3, 4, 5, 6]
edges = [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1), (1, 4), (2, 5)]
graph = m.Graph(
vertices,
edges,
layout="circular",
layout_scale=3,
labels=True,
vertex_config={1: {"fill_color": m.RED}},
edge_config={(1, 4): {"stroke_color": m.YELLOW}},
)
self.play(m.Create(graph))
self.play(graph[3].animate.move_to([0, 0, 0]))
An undirected graph: vertices joined by edges, laid out automatically or by hand; white dots and lines unless styled.
Each edge runs from the center of one vertex to the center of the other, behind them, and follows them as they move. It takes the arguments of a GenericGraph, which lists what a graph can do.
Source
src/manimgx/mobjects/graph.py
DiGraph ¶
Code
import manimgx as m
class DiGraphExample(m.Scene):
def construct(self) -> None:
edge_config = {
"stroke_width": 3,
"tip_config": {"tip_length": 0.2, "tip_width": 0.2},
(3, 4): {
"color": m.RED,
"tip_config": {"tip_shape": m.ArrowSquareTip},
},
}
graph = m.DiGraph(
[0, 1, 2, 3, 4],
[(0, 1), (1, 2), (3, 2), (3, 4), (4, 0)],
labels=True,
layout="circular",
layout_scale=3,
edge_config=edge_config,
)
self.play(m.Create(graph))
A directed graph: vertices joined by arrows, from the first vertex of each edge to the second; white dots and arrows unless styled.
Each edge runs from the outline of one vertex to the outline of the other and ends
in a tip, which the "tip_config" of edge_config shapes (see
TipConfig), for every edge or an edge's own; it
follows its vertices as they move. It takes the arguments of a
GenericGraph, which lists what a graph can do.
Source
src/manimgx/mobjects/graph.py
TipConfig ¶
The tip of a DiGraph's edge, given as "tip_config" in its
edge_config: for every edge, or an edge's own (see
add_tip).
tip_shapeThe class of the tip (default None: ArrowTriangleFilledTip).
tip_lengthThe tip's length, in scene units (default None: the edge's default).
tip_widthThe tip's width, in scene units, for the default filled triangle (default None: its length).
tip_shape ¶
The class of the tip (default None: ArrowTriangleFilledTip).
tip_length ¶
The tip's length, in scene units (default None: the edge's default).
tip_width ¶
The tip's width, in scene units, for the default filled triangle (default None: its length).
What a network can do¶
Graph and DiGraph are both made from GenericGraph, which holds what they can do.
GenericGraph ¶
What Graph and DiGraph have in common: vertices and edges, laid out and kept together; white dots and lines unless styled.
The vertices are any hashable values (numbers, strings, …): each is made a mobject,
a Dot by default, and graph[v] is the mobject of vertex v. The
edges are pairs of vertices: each is made a mobject, a Line by
default, drawn behind the vertices (z-index -1), and graph[(u, v)] is the mobject
of edge (u, v). An updater keeps the edges on their vertices: move a vertex (or
animate it) and its edges follow. Vertices and edges can be added and removed, and
the whole graph laid out anew.
The layout places the vertices: by a name — NetworkX's "circular",
"kamada_kawai", "planar", "shell", "spectral", "spiral" and "spring"
(random unless given a seed in layout_config), or "partite" (in columns, by
partitions) and "tree" (down from root_vertex) — by a dictionary of positions,
or by a function of one's own. It spans about layout_scale from the center, the
center at the scene's origin; points of two coordinates lie in the plane z = 0.
verticesThe vertices: hashable values, each a vertex's name.
edgesThe edges, each a pair of vertices.
labelsWhether each vertex is labeled with its name, typeset as math (a vertex that is a Dot becomes a LabeledDot); or a label for each, by vertex.
label_fill_colorThe color of the labels made from names.
layoutWhere the vertices go: a layout's name, their positions (a dictionary from each vertex to its point), or a layout function, called with the NetworkX graph,
scaleand the keywords oflayout_config.layout_scaleHow far the layout reaches from the center, in scene units.
layout_configKeywords for the layout function; None for none.
vertex_typeThe class of the vertices, called with each vertex's keywords.
vertex_configKeywords for the vertices: for all of them, and a vertex's own under its name, in place of those for all, as in
{"radius": 0.2, 3: {"color": RED}}; None for none.vertex_mobjectsMobjects to be vertices themselves, by vertex; None for none.
edge_typeThe class of the edges, called with each edge's ends and keywords.
partitionsFor the
"partite"layout: the vertices of each column, in order (those of none make a last column); None for none.root_vertexFor the
"tree"layout: the vertex at its top; None for none.edge_configKeywords for the edges: for all of them, and an edge's own under its pair of vertices, in place of those for all; a DiGraph's tips under
"tip_config". None for none.
Source
src/manimgx/mobjects/graph.py
vertices ¶
The vertices' mobjects, by vertex.
edges ¶
The edges' mobjects, by pair of vertices.
add_vertices ¶
Code
import manimgx as m
class GraphAddVerticesExample(m.Scene):
def construct(self) -> None:
graph = m.Graph(
[1, 2, 3],
[(1, 2), (2, 3)],
layout={1: [-4, -1, 0], 2: [0, -2, 0], 3: [4, -1, 0]},
vertex_config={"radius": 0.15},
)
self.add(graph)
top = graph.add_vertices(
4, positions={4: [0, 2.5, 0]}, vertex_config={"color": m.YELLOW}
)
self.play(m.FadeIn(top, scale=3))
self.play(m.Create(graph.add_edges((1, 4), (3, 4))))
Add vertices to the graph, without edges.
Each is made as the graph makes its vertices, with the keywords given over the graph's own, and placed at its position, or at the graph's center. A vertex already in the graph raises a ValueError.
*verticesThe new vertices: hashable values, each a vertex's name.
positionsWhere new vertices go, by vertex (default None: at the graph's center).
labelsWhether each new vertex is labeled with its name, typeset as math: True for all, or by vertex, True or a label of one's own (default False).
label_fill_colorThe color of the labels made from names (default black).
vertex_typeThe class of the new vertices (default Dot; a labeled one is a LabeledDot).
vertex_configKeywords for the new vertices, over the graph's: for all of them, and a vertex's own under its name, in place of those for all (default None: none).
vertex_mobjectsMobjects to be vertices themselves, by vertex (default None: none).
Returns A new group of the new vertices' mobjects.
Source
src/manimgx/mobjects/graph.py
remove_vertices ¶
Remove vertices from the graph, and the edges that touch them.
A vertex not in the graph raises a ValueError.
*verticesThe vertices to remove.
Returns A new group of the removed mobjects (for each vertex, its edges, then the vertex), to fade out, for instance.
Source
src/manimgx/mobjects/graph.py
add_edges ¶
Add edges to the graph, and the vertices they name that it lacks.
The missing vertices are added first, as add_vertices adds them, with the vertex keywords given; each edge is then made as the graph makes its edges, with the edge keywords given over the graph's own.
generic_graph.add_edges(*edges, edge_type=Line, edge_config=None, **kwargs)
*edgesThe new edges, each a pair of vertices.
edge_typeThe class of the new edges.
edge_configKeywords for the new edges, over the graph's: for all of them, and an edge's own under its pair of vertices, in place of those for all; None for none.
It also takes
the add_vertices keywords.
Returns A new group of the new mobjects, the vertices added and then the edges.
Source
src/manimgx/mobjects/graph.py
remove_edges ¶
Remove edges from the graph, keeping their vertices.
An edge not in the graph raises a ValueError.
*edgesThe edges to remove, each a pair of vertices.
Returns A new group of the removed edges' mobjects.
Source
src/manimgx/mobjects/graph.py
change_layout ¶
Code
import manimgx as m
class GraphChangeLayoutExample(m.Scene):
def construct(self) -> None:
graph = m.Graph(
[1, 2, 3, 4, 5, 6],
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 1), (1, 4)],
layout={v: [2 * v - 7, 0, 0] for v in range(1, 7)},
)
circle = graph.copy().change_layout("circular", layout_scale=3)
self.add(graph)
self.play(
*(graph[v].animate.move_to(circle[v]) for v in graph.vertices)
)
Lay the graph out anew: move each vertex to its place in a layout.
The vertices move at once, and the edges follow them at the next frame, as the graph's updater moves them. To animate the change, animate each vertex to its place in a changed copy (as below): the edges follow all the way.
A layout function gets a fresh NetworkX graph of the current vertices and edges. Its node, edge and graph attributes belong to that call, not to later layouts.
layoutWhere the vertices go: a layout's name, their positions, or a layout function (see GenericGraph).
layout_scaleHow far the layout reaches from the center, in scene units.
layout_configKeywords for the layout function; None for none.
partitionsFor the
"partite"layout: the vertices of each column; None for none.root_vertexFor the
"tree"layout: the vertex at its top; None for none.
Source
src/manimgx/mobjects/graph.py
from_networkx ¶
Code
import networkx as nx
import manimgx as m
class GraphFromNetworkxExample(m.Scene):
def construct(self) -> None:
petersen = nx.petersen_graph()
graph = m.Graph.from_networkx(
petersen,
layout="shell",
layout_scale=3,
layout_config={"nlist": [range(5, 10), range(5)]},
)
self.play(m.Create(graph), run_time=2)
Make a graph of a NetworkX graph's nodes and edges.
nxgraphThe NetworkX graph (a
Graph, or aDiGraph).labelsWhether each vertex is labeled with its name, typeset as math, or a label for each (default False).
label_fill_colorThe color of the labels made from names (default black).
layoutWhere the vertices go: a layout's name, their positions, or a layout function (default
"spring").layout_scaleHow far the layout reaches from the center, in scene units (default 2).
layout_configKeywords for the layout function: a
"spring"layout'sseed, … (default None: none).vertex_typeThe class of the vertices (default Dot; a labeled one is a LabeledDot).
vertex_configKeywords for the vertices: for all of them, and a vertex's own under its name, in place of those for all (default None: none).
vertex_mobjectsMobjects to be vertices themselves, by vertex (default None: none).
edge_typeThe class of the edges (default Line).
partitionsFor the
"partite"layout: the vertices of each column, in order (default None: none).root_vertexFor the
"tree"layout: the vertex at its top (default None: none).edge_configKeywords for the edges: for all of them, and an edge's own under its pair of vertices, in place of those for all (default None: none).
Returns A new graph.
Source
src/manimgx/mobjects/graph.py
update_edges ¶
Put each edge back on its vertices, where they are now: the updater a graph runs every frame, so that its edges follow its vertices.
Each kind of graph sets its edges' ends its own way: an undirected graph's from center to center, a directed graph's from outline to outline, with its tip. Only edges that are lines (Line and its kinds) follow.
graphThe mobject the updater runs for (the graph); unused.
Source
src/manimgx/mobjects/graph.py