What basically happens is that even adding a simple edge which I know can already be permitted since the nodes that connect it has already been created through graph.animate.add_vertices() the method still won't work. For instance initially I have vertex 1 (as shown below) with no edges whatsoever, then when I add vertices 2, and 3 for instance and add edges (1, 2) and (1, 3), it raises an error Exception: Cannot position endpoints of closed loop
Here is the code I wrote:
class Graph7(ThreeDScene):
def construct(self):
edges = []
partitions = []
c = 0
layers = [5, 4, 4, 3, 2, 3, 4, 4, 5] # the number of neurons in each layer
for n_nodes in layers:
partitions.append(list(range(c + 1, c + n_nodes + 1)))
c += n_nodes
# create the edges of neural network
for i, v in enumerate(layers[1:]):
last = sum(layers[:i+1])
for j in range(v):
for k in range(last - layers[i], last):
edges.append((k + 1, j + last + 1))
# create the nodes of the neural network
vertices = np.arange(1, sum(layers) + 1)
print(vertices)
print(edges)
# note graph nodes start from 1 in this case
# initially also our graph will just be a single node then
# progress to add more nodes
graph = Graph(
[1],
[],
layout_scale=5,
vertex_config={
'fill_color': BLUE,
'fill_opacity': 0,
'radius': 0.2,
'stroke_width': 5,
'stroke_color': WHITE
},
)
self.play(Create(graph))
# add the rest of the vertices which are from 2 to 34
self.play(graph.animate.add_vertices(*vertices[vertices > 1], vertex_config={
'fill_color': BLUE,
'fill_opacity': 0,
'radius': 0.2,
'stroke_width': 5,
'stroke_color': WHITE
}))
self.play(graph.animate.add_edges((1, 2)))
self.play(graph.animate.change_layout('partite', partitions=partitions, layout_scale=5))
self.wait(1)
And here is the full error that is shown to me:
┌─────────────────────────────── Traceback (most recent call last) ────────────────────────────────┐
│ C:\ProgramData\Anaconda3\envs\project-alexander-animations\Lib\site-packages\manim\cli\render\co │
│ mmands.py:115 in render │
│ │
│ 112 │ │ │ try: │
│ 113 │ │ │ │ with tempconfig({}): │
│ 114 │ │ │ │ │ scene = SceneClass() │
│ > 115 │ │ │ │ │ scene.render() │
│ 116 │ │ │ except Exception: │
│ 117 │ │ │ │ error_console.print_exception() │
│ 118 │ │ │ │ sys.exit(1) │
│ │
│ C:\ProgramData\Anaconda3\envs\project-alexander-animations\Lib\site-packages\manim\scene\scene.p │
│ y:223 in render │
│ │
│ 220 │ │ """ │
│ 221 │ │ self.setup() │
│ 222 │ │ try: │
│ > 223 │ │ │ self.construct() │
│ 224 │ │ except EndSceneEarlyException: │
│ 225 │ │ │ pass │
│ 226 │ │ except RerunSceneException as e: │
│ │
│ D:\Projects\To Github\project-alexander-animations\tutorial.py:931 in construct │
│ │
│ 928 │ │ │ │ 'stroke_width': 5, │
│ 929 │ │ │ │ 'stroke_color': WHITE │
│ 930 │ │ │ })) │
│ > 931 │ │ self.play(graph.animate.add_edges((35, 26))) │
│ 932 │ │ self.play(graph.animate.change_layout('partite', partitions=partitions, layout_s │
│ 933 │ │ # # self.wait(1) │
│ 934 │
│ │
│ C:\ProgramData\Anaconda3\envs\project-alexander-animations\Lib\site-packages\manim\scene\scene.p │
│ y:1082 in play │
│ │
│ 1079 │ │ │ return │
│ 1080 │ │ │
│ 1081 │ │ start_time = self.renderer.time │
│ > 1082 │ │ self.renderer.play(self, *args, **kwargs) │
│ 1083 │ │ run_time = self.renderer.time - start_time │
│ 1084 │ │ if subcaption: │
│ 1085 │ │ │ if subcaption_duration is None: │
│ │
│ C:\ProgramData\Anaconda3\envs\project-alexander-animations\Lib\site-packages\manim\renderer\cair │
│ o_renderer.py:104 in play │
│ │
│ 101 │ │ │ # In this case, as there is only a wait, it will be the length of the wait. │
│ 102 │ │ │ self.freeze_current_frame(scene.duration) │
│ 103 │ │ else: │
│ > 104 │ │ │ scene.play_internal() │
│ 105 │ │ self.file_writer.end_animation(not self.skip_animations) │
│ 106 │ │ │
│ 107 │ │ self.num_plays += 1 │
│ │
│ C:\ProgramData\Anaconda3\envs\project-alexander-animations\Lib\site-packages\manim\scene\scene.p │
│ y:1253 in play_internal │
│ │
│ 1250 │ │ │ │ break │
│ 1251 │ │ │
│ 1252 │ │ for animation in self.animations: │
│ > 1253 │ │ │ animation.finish() │
│ 1254 │ │ │ animation.clean_up_from_scene(self) │
│ 1255 │ │ if not self.renderer.skip_animations: │
│ 1256 │ │ │ self.update_mobjects(0) │
│ │
│ C:\ProgramData\Anaconda3\envs\project-alexander-animations\Lib\site-packages\manim\animation\com │
│ position.py:97 in finish │
│ │
│ 94 │ │ for anim in self.animations: │
│ 95 │ │ │ anim.finish() │
│ 96 │ │ if self.suspend_mobject_updating: │
│ > 97 │ │ │ self.group.resume_updating() │
│ 98 │ │
│ 99 │ def clean_up_from_scene(self, scene: Scene) -> None: │
│ 100 │ │ self._on_finish(scene) │
│ │
│ C:\ProgramData\Anaconda3\envs\project-alexander-animations\Lib\site-packages\manim\mobject\mobje │
│ ct.py:1114 in resume_updating │
│ │
│ 1111 │ │ if recursive: │
│ 1112 │ │ │ for submob in self.submobjects: │
│ 1113 │ │ │ │ submob.resume_updating(recursive) │
│ > 1114 │ │ self.update(dt=0, recursive=recursive) │
│ 1115 │ │ return self │
│ 1116 │ │
│ 1117 │ # Transforming operations │
│ │
│ C:\ProgramData\Anaconda3\envs\project-alexander-animations\Lib\site-packages\manim\mobject\mobje │
│ ct.py:843 in update │
│ │
│ 840 │ │ │ if "dt" in parameters: │
│ 841 │ │ │ │ updater(self, dt) │
│ 842 │ │ │ else: │
│ > 843 │ │ │ │ updater(self) │
│ 844 │ │ if recursive: │
│ 845 │ │ │ for submob in self.submobjects: │
│ 846 │ │ │ │ submob.update(dt, recursive) │
│ │
│ C:\ProgramData\Anaconda3\envs\project-alexander-animations\Lib\site-packages\manim\mobject\graph │
│ .py:1287 in update_edges │
│ │
│ 1284 │ def update_edges(self, graph): │
│ 1285 │ │ for (u, v), edge in graph.edges.items(): │
│ 1286 │ │ │ # Undirected graph has a Line edge │
│ > 1287 │ │ │ edge.put_start_and_end_on(graph[u].get_center(), graph[v].get_center()) │
│ 1288 │ │
│ 1289 │ def __repr__(self: Graph) -> str: │
│ 1290 │ │ return f"Undirected graph on {len(self.vertices)} vertices and {len(self.edges)} │
│ │
│ C:\ProgramData\Anaconda3\envs\project-alexander-animations\Lib\site-packages\manim\mobject\geome │
│ try\line.py:146 in put_start_and_end_on │
│ │
│ 143 │ │ │ self.start = start │
│ 144 │ │ │ self.end = end │
│ 145 │ │ │ self.generate_points() │
│ > 146 │ │ return super().put_start_and_end_on(start, end) │
│ 147 │ │
│ 148 │ def get_vector(self): │
│ 149 │ │ return self.get_end() - self.get_start() │
│ │
│ C:\ProgramData\Anaconda3\envs\project-alexander-animations\Lib\site-packages\manim\mobject\mobje │
│ ct.py:1669 in put_start_and_end_on │
│ │
│ 1666 │ │ curr_start, curr_end = self.get_start_and_end() │
│ 1667 │ │ curr_vect = curr_end - curr_start │
│ 1668 │ │ if np.all(curr_vect == 0): │
│ > 1669 │ │ │ raise Exception("Cannot position endpoints of closed loop") │
│ 1670 │ │ target_vect = np.array(end) - np.array(start) │
│ 1671 │ │ axis = ( │
│ 1672 │ │ │ normalize(np.cross(curr_vect, target_vect)) │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘
Exception: Cannot position endpoints of closed loop