manim-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -0
- package/dist/demo.mp4 +0 -0
- package/dist/index.js +65 -0
- package/dist/mcp-app.html +142 -0
- package/dist/server.js +1492 -0
- package/package.json +67 -0
- package/references/composer/SKILL.md +154 -0
- package/references/composer/references/3b1b-series-patterns.md +217 -0
- package/references/composer/references/domain-planning-guides/calculus-planning.md +188 -0
- package/references/composer/references/domain-planning-guides/linear-algebra-planning.md +169 -0
- package/references/composer/references/domain-planning-guides/ml-planning.md +286 -0
- package/references/composer/references/domain-planning-guides/number-theory-planning.md +187 -0
- package/references/composer/references/domain-planning-guides/physics-planning.md +249 -0
- package/references/composer/references/domain-planning-guides/probability-planning.md +200 -0
- package/references/composer/references/mathematical-storytelling.md +359 -0
- package/references/composer/references/narrative-patterns.md +221 -0
- package/references/composer/references/opening-patterns.md +284 -0
- package/references/composer/references/pacing-guide.md +289 -0
- package/references/composer/references/scene-archetypes.md +534 -0
- package/references/composer/references/scene-examples.md +379 -0
- package/references/composer/references/visual-techniques.md +480 -0
- package/references/composer/templates/scenes-template.md +147 -0
- package/references/manimce/SKILL.md +166 -0
- package/references/manimce/examples/3d_visualization.py +373 -0
- package/references/manimce/examples/basic_animations.py +212 -0
- package/references/manimce/examples/graph_plotting.py +401 -0
- package/references/manimce/examples/lorenz_attractor.py +172 -0
- package/references/manimce/examples/math_visualization.py +315 -0
- package/references/manimce/examples/updater_patterns.py +369 -0
- package/references/manimce/rules/3b1b-translation.md +594 -0
- package/references/manimce/rules/3d.md +254 -0
- package/references/manimce/rules/advanced-animations.md +594 -0
- package/references/manimce/rules/animation-groups.md +212 -0
- package/references/manimce/rules/animations.md +128 -0
- package/references/manimce/rules/api-pitfalls.md +89 -0
- package/references/manimce/rules/axes.md +214 -0
- package/references/manimce/rules/camera.md +208 -0
- package/references/manimce/rules/cli.md +232 -0
- package/references/manimce/rules/color-conventions.md +444 -0
- package/references/manimce/rules/colors.md +199 -0
- package/references/manimce/rules/config.md +264 -0
- package/references/manimce/rules/creation-animations.md +158 -0
- package/references/manimce/rules/graphing.md +233 -0
- package/references/manimce/rules/grouping.md +220 -0
- package/references/manimce/rules/latex.md +202 -0
- package/references/manimce/rules/lines.md +241 -0
- package/references/manimce/rules/long-form-video.md +552 -0
- package/references/manimce/rules/mathematical-domains.md +689 -0
- package/references/manimce/rules/mobjects.md +116 -0
- package/references/manimce/rules/multi-scene-composition.md +112 -0
- package/references/manimce/rules/pedagogy.md +532 -0
- package/references/manimce/rules/physics-simulations.md +610 -0
- package/references/manimce/rules/positioning.md +211 -0
- package/references/manimce/rules/scenes.md +121 -0
- package/references/manimce/rules/shapes.md +300 -0
- package/references/manimce/rules/styling.md +177 -0
- package/references/manimce/rules/text-animations.md +222 -0
- package/references/manimce/rules/text.md +189 -0
- package/references/manimce/rules/timing.md +227 -0
- package/references/manimce/rules/transform-animations.md +157 -0
- package/references/manimce/rules/updaters.md +226 -0
- package/references/manimce/templates/basic_scene.py +64 -0
- package/references/manimce/templates/camera_scene.py +100 -0
- package/references/manimce/templates/threed_scene.py +138 -0
|
@@ -0,0 +1,689 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mathematical-domains
|
|
3
|
+
description: Domain-specific patterns for visualizing different branches of mathematics in ManimCE, based on 3b1b's actual video code
|
|
4
|
+
metadata:
|
|
5
|
+
tags: linear-algebra, calculus, probability, complex-analysis, number-theory, topology, neural-networks, quantum, math
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mathematical Domain-Specific Patterns
|
|
9
|
+
|
|
10
|
+
Patterns extracted from specific 3b1b video series: Essence of Linear Algebra, Essence of Calculus, probability videos, complex analysis, prime spirals, topology, transformers series, and quantum computing.
|
|
11
|
+
|
|
12
|
+
## Linear Algebra
|
|
13
|
+
|
|
14
|
+
From `_2016/eola/` (chapters 0-11) and `_2024/linalg/eigenlecture.py`.
|
|
15
|
+
|
|
16
|
+
### Basis Vectors (Green i-hat, Red j-hat)
|
|
17
|
+
|
|
18
|
+
The canonical 3b1b convention: i-hat is GREEN, j-hat is RED, k-hat is BLUE.
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
from manim import *
|
|
22
|
+
|
|
23
|
+
X_COLOR = GREEN
|
|
24
|
+
Y_COLOR = RED
|
|
25
|
+
Z_COLOR = BLUE
|
|
26
|
+
|
|
27
|
+
class BasisVectors(Scene):
|
|
28
|
+
"""Standard EoLA basis vector setup."""
|
|
29
|
+
|
|
30
|
+
def construct(self):
|
|
31
|
+
plane = NumberPlane()
|
|
32
|
+
plane.set_stroke(BLUE_D, 1, opacity=0.4)
|
|
33
|
+
|
|
34
|
+
# Basis vectors with labels
|
|
35
|
+
i_hat = Vector([1, 0], color=X_COLOR, stroke_width=5)
|
|
36
|
+
j_hat = Vector([0, 1], color=Y_COLOR, stroke_width=5)
|
|
37
|
+
|
|
38
|
+
i_label = MathTex(r"\hat{\imath}", color=X_COLOR, font_size=36)
|
|
39
|
+
i_label.next_to(i_hat.get_end(), DOWN + RIGHT, buff=0.1)
|
|
40
|
+
j_label = MathTex(r"\hat{\jmath}", color=Y_COLOR, font_size=36)
|
|
41
|
+
j_label.next_to(j_hat.get_end(), UP + LEFT, buff=0.1)
|
|
42
|
+
|
|
43
|
+
self.play(Create(plane), run_time=2)
|
|
44
|
+
self.play(
|
|
45
|
+
GrowArrow(i_hat), Write(i_label),
|
|
46
|
+
GrowArrow(j_hat), Write(j_label),
|
|
47
|
+
)
|
|
48
|
+
self.wait()
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Grid Transformations (Linear Map Visualization)
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
class LinearTransformation(Scene):
|
|
55
|
+
"""Apply a linear transformation to the grid -- EoLA signature."""
|
|
56
|
+
|
|
57
|
+
def construct(self):
|
|
58
|
+
plane = NumberPlane()
|
|
59
|
+
i_hat = Vector([1, 0], color=X_COLOR)
|
|
60
|
+
j_hat = Vector([0, 1], color=Y_COLOR)
|
|
61
|
+
|
|
62
|
+
self.add(plane, i_hat, j_hat)
|
|
63
|
+
self.wait()
|
|
64
|
+
|
|
65
|
+
# The transformation matrix
|
|
66
|
+
matrix = [[1, 1], [-1, 1]] # Rotation + scaling
|
|
67
|
+
|
|
68
|
+
# Apply transformation to the plane and basis vectors
|
|
69
|
+
self.play(
|
|
70
|
+
ApplyMatrix(matrix, plane),
|
|
71
|
+
ApplyMatrix(matrix, i_hat),
|
|
72
|
+
ApplyMatrix(matrix, j_hat),
|
|
73
|
+
run_time=3,
|
|
74
|
+
)
|
|
75
|
+
self.wait()
|
|
76
|
+
|
|
77
|
+
# Show where basis vectors land
|
|
78
|
+
new_i_coords = MathTex(
|
|
79
|
+
r"\hat{\imath} \to", r"\begin{bmatrix} 1 \\ -1 \end{bmatrix}",
|
|
80
|
+
tex_to_color_map={r"\hat{\imath}": X_COLOR},
|
|
81
|
+
).to_corner(UL)
|
|
82
|
+
new_j_coords = MathTex(
|
|
83
|
+
r"\hat{\jmath} \to", r"\begin{bmatrix} 1 \\ 1 \end{bmatrix}",
|
|
84
|
+
tex_to_color_map={r"\hat{\jmath}": Y_COLOR},
|
|
85
|
+
).next_to(new_i_coords, DOWN, aligned_edge=LEFT)
|
|
86
|
+
|
|
87
|
+
self.play(Write(new_i_coords), Write(new_j_coords))
|
|
88
|
+
self.wait(2)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Determinant Visualization
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
class DeterminantVisualization(Scene):
|
|
95
|
+
"""Visualize determinant as area scaling factor."""
|
|
96
|
+
|
|
97
|
+
def construct(self):
|
|
98
|
+
plane = NumberPlane().set_opacity(0.3)
|
|
99
|
+
self.add(plane)
|
|
100
|
+
|
|
101
|
+
# Unit square
|
|
102
|
+
unit_square = Polygon(
|
|
103
|
+
ORIGIN, RIGHT, RIGHT + UP, UP,
|
|
104
|
+
fill_color=YELLOW, fill_opacity=0.3,
|
|
105
|
+
stroke_color=YELLOW, stroke_width=2,
|
|
106
|
+
)
|
|
107
|
+
area_label = MathTex(r"\text{Area} = 1", font_size=30)
|
|
108
|
+
area_label.move_to(unit_square)
|
|
109
|
+
|
|
110
|
+
self.play(DrawBorderThenFill(unit_square), Write(area_label))
|
|
111
|
+
self.wait()
|
|
112
|
+
|
|
113
|
+
# Transform
|
|
114
|
+
matrix = [[2, 1], [0, 3]]
|
|
115
|
+
det_value = matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]
|
|
116
|
+
|
|
117
|
+
self.play(
|
|
118
|
+
ApplyMatrix(matrix, unit_square),
|
|
119
|
+
ApplyMatrix(matrix, plane),
|
|
120
|
+
run_time=2,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
new_label = MathTex(
|
|
124
|
+
rf"\text{{Area}} = {det_value}",
|
|
125
|
+
font_size=30, color=YELLOW,
|
|
126
|
+
)
|
|
127
|
+
new_label.move_to(unit_square)
|
|
128
|
+
self.play(Transform(area_label, new_label))
|
|
129
|
+
|
|
130
|
+
# Show det formula
|
|
131
|
+
det_formula = MathTex(
|
|
132
|
+
rf"\det \begin{{bmatrix}} 2 & 1 \\ 0 & 3 \end{{bmatrix}} = {det_value}",
|
|
133
|
+
).to_edge(UP)
|
|
134
|
+
self.play(Write(det_formula))
|
|
135
|
+
self.wait(2)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Eigenvalue Tracing
|
|
139
|
+
|
|
140
|
+
From `_2024/linalg/eigenlecture.py` -- using `t2c` for color-coded eigenvalue equations.
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
class EigenvalueEquation(Scene):
|
|
144
|
+
"""Color-coded eigenvalue equation in the 3b1b style."""
|
|
145
|
+
|
|
146
|
+
def construct(self):
|
|
147
|
+
eq = MathTex(
|
|
148
|
+
r"A", r"\vec{v}", r"=", r"\lambda", r"\vec{v}",
|
|
149
|
+
tex_to_color_map={
|
|
150
|
+
r"\vec{v}": YELLOW,
|
|
151
|
+
r"\lambda": TEAL,
|
|
152
|
+
},
|
|
153
|
+
)
|
|
154
|
+
eq.scale(1.5)
|
|
155
|
+
self.play(Write(eq))
|
|
156
|
+
self.wait()
|
|
157
|
+
|
|
158
|
+
# Rearrange to characteristic equation
|
|
159
|
+
char_eq = MathTex(
|
|
160
|
+
r"\det(", r"A", r"-", r"\lambda", r"I", r") = 0",
|
|
161
|
+
tex_to_color_map={r"\lambda": TEAL},
|
|
162
|
+
)
|
|
163
|
+
char_eq.scale(1.2)
|
|
164
|
+
char_eq.next_to(eq, DOWN, buff=1.0)
|
|
165
|
+
self.play(Write(char_eq, run_time=2))
|
|
166
|
+
self.wait(2)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Calculus
|
|
170
|
+
|
|
171
|
+
From `_2017/` Essence of Calculus and related videos.
|
|
172
|
+
|
|
173
|
+
### Riemann Rectangles
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
class RiemannRectangles(Scene):
|
|
177
|
+
"""Progressive refinement of Riemann sums."""
|
|
178
|
+
|
|
179
|
+
def construct(self):
|
|
180
|
+
axes = Axes(
|
|
181
|
+
x_range=[0, 5, 1], y_range=[0, 5, 1],
|
|
182
|
+
x_length=8, y_length=5,
|
|
183
|
+
)
|
|
184
|
+
graph = axes.plot(lambda x: 0.2 * x**2, color=YELLOW)
|
|
185
|
+
graph_label = axes.get_graph_label(graph, r"f(x) = 0.2x^2")
|
|
186
|
+
|
|
187
|
+
self.play(Create(axes), Create(graph), Write(graph_label))
|
|
188
|
+
self.wait()
|
|
189
|
+
|
|
190
|
+
# Show progressively finer rectangles
|
|
191
|
+
for n_rects in [4, 8, 20, 50]:
|
|
192
|
+
rects = axes.get_riemann_rectangles(
|
|
193
|
+
graph,
|
|
194
|
+
x_range=[0, 4],
|
|
195
|
+
dx=4.0 / n_rects,
|
|
196
|
+
fill_opacity=0.5,
|
|
197
|
+
stroke_width=1,
|
|
198
|
+
stroke_color=WHITE,
|
|
199
|
+
)
|
|
200
|
+
rects.set_color_by_gradient(BLUE, GREEN)
|
|
201
|
+
|
|
202
|
+
if n_rects == 4:
|
|
203
|
+
self.play(Create(rects), run_time=1.5)
|
|
204
|
+
else:
|
|
205
|
+
self.play(Transform(rects_prev, rects), run_time=1)
|
|
206
|
+
|
|
207
|
+
rects_prev = rects
|
|
208
|
+
n_label = MathTex(f"n = {n_rects}", font_size=36)
|
|
209
|
+
n_label.to_corner(UR)
|
|
210
|
+
self.play(Write(n_label), run_time=0.5)
|
|
211
|
+
self.wait(0.5)
|
|
212
|
+
self.remove(n_label)
|
|
213
|
+
|
|
214
|
+
self.wait(2)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Secant Line to Tangent Line
|
|
218
|
+
|
|
219
|
+
```python
|
|
220
|
+
class SecantToTangent(Scene):
|
|
221
|
+
"""The derivative as limit of secant slopes."""
|
|
222
|
+
|
|
223
|
+
def construct(self):
|
|
224
|
+
axes = Axes(x_range=[-1, 5], y_range=[-1, 6], x_length=8, y_length=5)
|
|
225
|
+
graph = axes.plot(lambda x: 0.3 * x**2, color=YELLOW)
|
|
226
|
+
self.add(axes, graph)
|
|
227
|
+
|
|
228
|
+
# Fixed point
|
|
229
|
+
x0 = 2
|
|
230
|
+
dot_a = Dot(axes.i2gp(x0, graph), color=WHITE)
|
|
231
|
+
a_label = MathTex("a", font_size=30).next_to(dot_a, DL, buff=0.1)
|
|
232
|
+
self.play(FadeIn(dot_a), Write(a_label))
|
|
233
|
+
|
|
234
|
+
# Secant line that approaches tangent
|
|
235
|
+
dx_tracker = ValueTracker(2.0)
|
|
236
|
+
|
|
237
|
+
def get_secant_line():
|
|
238
|
+
dx = dx_tracker.get_value()
|
|
239
|
+
x1 = x0 + dx
|
|
240
|
+
p0 = axes.i2gp(x0, graph)
|
|
241
|
+
p1 = axes.i2gp(x1, graph)
|
|
242
|
+
slope = (p1[1] - p0[1]) / (p1[0] - p0[0]) if p1[0] != p0[0] else 0
|
|
243
|
+
line = axes.get_secant_slope_group(
|
|
244
|
+
x0, graph, dx=dx,
|
|
245
|
+
secant_line_color=BLUE,
|
|
246
|
+
secant_line_length=5,
|
|
247
|
+
)
|
|
248
|
+
return line
|
|
249
|
+
|
|
250
|
+
secant = always_redraw(get_secant_line)
|
|
251
|
+
self.add(secant)
|
|
252
|
+
|
|
253
|
+
# Animate dx shrinking
|
|
254
|
+
self.play(dx_tracker.animate.set_value(0.01), run_time=5, rate_func=smooth)
|
|
255
|
+
self.wait()
|
|
256
|
+
|
|
257
|
+
# Label as derivative
|
|
258
|
+
tangent_label = MathTex(
|
|
259
|
+
r"\text{slope} = f'(a)", font_size=36, color=BLUE,
|
|
260
|
+
).to_corner(UR)
|
|
261
|
+
self.play(Write(tangent_label))
|
|
262
|
+
self.wait(2)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Taylor Approximation
|
|
266
|
+
|
|
267
|
+
```python
|
|
268
|
+
class TaylorApproximation(Scene):
|
|
269
|
+
"""Progressive Taylor polynomial approximation."""
|
|
270
|
+
|
|
271
|
+
def construct(self):
|
|
272
|
+
axes = Axes(x_range=[-3, 3], y_range=[-2, 4], x_length=10, y_length=6)
|
|
273
|
+
original = axes.plot(np.exp, color=YELLOW, x_range=[-3, 1.5])
|
|
274
|
+
original_label = MathTex(r"e^x", color=YELLOW, font_size=36)
|
|
275
|
+
original_label.next_to(original, UR)
|
|
276
|
+
|
|
277
|
+
self.play(Create(axes), Create(original), Write(original_label))
|
|
278
|
+
self.wait()
|
|
279
|
+
|
|
280
|
+
# Taylor polynomials of increasing order
|
|
281
|
+
taylor_funcs = [
|
|
282
|
+
lambda x: 1,
|
|
283
|
+
lambda x: 1 + x,
|
|
284
|
+
lambda x: 1 + x + x**2 / 2,
|
|
285
|
+
lambda x: 1 + x + x**2 / 2 + x**3 / 6,
|
|
286
|
+
lambda x: 1 + x + x**2 / 2 + x**3 / 6 + x**4 / 24,
|
|
287
|
+
]
|
|
288
|
+
colors = [RED, GREEN, BLUE, PURPLE, ORANGE]
|
|
289
|
+
|
|
290
|
+
prev_approx = None
|
|
291
|
+
for n, (func, color) in enumerate(zip(taylor_funcs, colors)):
|
|
292
|
+
approx = axes.plot(func, color=color, x_range=[-3, 3])
|
|
293
|
+
label = MathTex(f"n = {n}", font_size=30, color=color)
|
|
294
|
+
label.to_corner(UR).shift(n * 0.4 * DOWN)
|
|
295
|
+
|
|
296
|
+
if prev_approx is None:
|
|
297
|
+
self.play(Create(approx), Write(label))
|
|
298
|
+
else:
|
|
299
|
+
self.play(
|
|
300
|
+
Transform(prev_approx, approx),
|
|
301
|
+
Write(label),
|
|
302
|
+
)
|
|
303
|
+
prev_approx = approx
|
|
304
|
+
self.wait(0.5)
|
|
305
|
+
|
|
306
|
+
self.wait(2)
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Probability
|
|
310
|
+
|
|
311
|
+
From `_2019/bayes/`, `_2023/clt/`, `_2022/convolutions/`, and `_2018/eop/`.
|
|
312
|
+
|
|
313
|
+
### Bar Charts for Distributions
|
|
314
|
+
|
|
315
|
+
```python
|
|
316
|
+
class DistributionChart(Scene):
|
|
317
|
+
"""Bar chart for probability distributions -- from CLT video."""
|
|
318
|
+
|
|
319
|
+
def construct(self):
|
|
320
|
+
axes = Axes(
|
|
321
|
+
x_range=[0, 6, 1], y_range=[0, 0.5, 0.1],
|
|
322
|
+
x_length=6, y_length=4,
|
|
323
|
+
axis_config={"include_tip": False},
|
|
324
|
+
)
|
|
325
|
+
axes.y_axis.add_numbers(font_size=20, num_decimal_places=1)
|
|
326
|
+
|
|
327
|
+
# Dice distribution
|
|
328
|
+
dist = [1/6] * 6
|
|
329
|
+
bars = VGroup()
|
|
330
|
+
for i, p in enumerate(dist):
|
|
331
|
+
bar = Rectangle(
|
|
332
|
+
width=0.7 * axes.x_axis.get_unit_size(),
|
|
333
|
+
height=p * axes.y_axis.get_unit_size(),
|
|
334
|
+
fill_color=BLUE_D, fill_opacity=0.8,
|
|
335
|
+
stroke_color=WHITE, stroke_width=1,
|
|
336
|
+
)
|
|
337
|
+
bar.move_to(axes.c2p(i + 0.5, 0), DOWN)
|
|
338
|
+
bars.add(bar)
|
|
339
|
+
bars.set_color_by_gradient(BLUE, TEAL)
|
|
340
|
+
|
|
341
|
+
# Dice face labels
|
|
342
|
+
dice_labels = VGroup(*[
|
|
343
|
+
MathTex(str(n), font_size=24).next_to(axes.c2p(n - 0.5, 0), DOWN, SMALL_BUFF)
|
|
344
|
+
for n in range(1, 7)
|
|
345
|
+
])
|
|
346
|
+
|
|
347
|
+
self.play(Create(axes))
|
|
348
|
+
self.play(
|
|
349
|
+
LaggedStartMap(GrowFromEdge, bars, edge=DOWN, lag_ratio=0.15),
|
|
350
|
+
Write(dice_labels),
|
|
351
|
+
)
|
|
352
|
+
self.wait(2)
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Bayes Diagram
|
|
356
|
+
|
|
357
|
+
```python
|
|
358
|
+
class BayesDiagram(Scene):
|
|
359
|
+
"""Visual Bayes' theorem -- area-based probability."""
|
|
360
|
+
|
|
361
|
+
def construct(self):
|
|
362
|
+
# Full rectangle = total probability space
|
|
363
|
+
full_rect = Rectangle(width=8, height=4, stroke_color=WHITE)
|
|
364
|
+
full_rect.set_fill(BLUE_E, opacity=0.3)
|
|
365
|
+
|
|
366
|
+
# Split by prior P(H)
|
|
367
|
+
prior = 0.01 # e.g., disease prevalence
|
|
368
|
+
divider_x = full_rect.get_left()[0] + prior * full_rect.width
|
|
369
|
+
v_line = Line(
|
|
370
|
+
[divider_x, full_rect.get_bottom()[1], 0],
|
|
371
|
+
[divider_x, full_rect.get_top()[1], 0],
|
|
372
|
+
color=YELLOW, stroke_width=3,
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
# H region
|
|
376
|
+
h_rect = Rectangle(
|
|
377
|
+
width=prior * full_rect.width,
|
|
378
|
+
height=full_rect.height,
|
|
379
|
+
fill_color=GREEN, fill_opacity=0.5,
|
|
380
|
+
stroke_color=WHITE,
|
|
381
|
+
)
|
|
382
|
+
h_rect.align_to(full_rect, LEFT + DOWN)
|
|
383
|
+
|
|
384
|
+
h_label = MathTex(r"P(H)", font_size=30, color=GREEN)
|
|
385
|
+
h_label.next_to(h_rect, UP)
|
|
386
|
+
|
|
387
|
+
not_h_label = MathTex(r"P(\neg H)", font_size=30, color=RED)
|
|
388
|
+
not_h_label.next_to(full_rect, UP).shift(2 * RIGHT)
|
|
389
|
+
|
|
390
|
+
self.play(DrawBorderThenFill(full_rect))
|
|
391
|
+
self.play(Create(v_line), DrawBorderThenFill(h_rect))
|
|
392
|
+
self.play(Write(h_label), Write(not_h_label))
|
|
393
|
+
self.wait(2)
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
## Complex Analysis
|
|
397
|
+
|
|
398
|
+
From `_2018/holomorphic.py`, `_2016/zeta.py`, `_2025/zeta/play.py`, and `_2025/laplace/`.
|
|
399
|
+
|
|
400
|
+
### Complex Plane Transformations
|
|
401
|
+
|
|
402
|
+
```python
|
|
403
|
+
class ComplexTransformation(Scene):
|
|
404
|
+
"""Visualize a complex function as a transformation of the plane."""
|
|
405
|
+
|
|
406
|
+
def construct(self):
|
|
407
|
+
plane = ComplexPlane(
|
|
408
|
+
x_range=[-3, 3], y_range=[-3, 3],
|
|
409
|
+
background_line_style={"stroke_opacity": 0.4},
|
|
410
|
+
)
|
|
411
|
+
plane.add_coordinate_labels(font_size=20)
|
|
412
|
+
self.add(plane)
|
|
413
|
+
|
|
414
|
+
# Label
|
|
415
|
+
func_label = MathTex(r"f(z) = z^2", font_size=40)
|
|
416
|
+
func_label.to_corner(UL)
|
|
417
|
+
func_label.set_backstroke(width=3)
|
|
418
|
+
self.play(Write(func_label))
|
|
419
|
+
self.wait()
|
|
420
|
+
|
|
421
|
+
# Apply the transformation
|
|
422
|
+
self.play(
|
|
423
|
+
plane.animate.apply_complex_function(lambda z: z**2),
|
|
424
|
+
run_time=3,
|
|
425
|
+
)
|
|
426
|
+
self.wait(2)
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Partial Sum Paths (Zeta Function Pattern)
|
|
430
|
+
|
|
431
|
+
From `_2025/zeta/play.py`:
|
|
432
|
+
|
|
433
|
+
```python
|
|
434
|
+
class ZetaPartialSums(Scene):
|
|
435
|
+
"""Visualize partial sums of a complex series as a spiral path."""
|
|
436
|
+
|
|
437
|
+
def construct(self):
|
|
438
|
+
plane = ComplexPlane(
|
|
439
|
+
x_range=[-3, 3], y_range=[-3, 3],
|
|
440
|
+
x_length=8, y_length=8,
|
|
441
|
+
)
|
|
442
|
+
plane.add_coordinate_labels(font_size=16)
|
|
443
|
+
self.add(plane)
|
|
444
|
+
|
|
445
|
+
# Partial sums of 1/n^s
|
|
446
|
+
s = complex(0.5, 14.134) # Near first zeta zero
|
|
447
|
+
partial_sums = [0]
|
|
448
|
+
for n in range(1, 100):
|
|
449
|
+
partial_sums.append(partial_sums[-1] + 1 / n**s)
|
|
450
|
+
|
|
451
|
+
# Convert to points on the plane
|
|
452
|
+
points = [plane.n2p(z) for z in partial_sums]
|
|
453
|
+
|
|
454
|
+
# Draw the path
|
|
455
|
+
path = VMobject()
|
|
456
|
+
path.set_points_smoothly(points)
|
|
457
|
+
path.set_stroke(YELLOW, 2)
|
|
458
|
+
|
|
459
|
+
# Starting dot
|
|
460
|
+
start_dot = Dot(points[0], color=GREEN)
|
|
461
|
+
end_dot = Dot(points[-1], color=RED)
|
|
462
|
+
|
|
463
|
+
self.play(FadeIn(start_dot))
|
|
464
|
+
self.play(Create(path), run_time=5)
|
|
465
|
+
self.play(FadeIn(end_dot))
|
|
466
|
+
self.wait(2)
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
## Number Theory
|
|
470
|
+
|
|
471
|
+
From `_2019/spirals.py` -- prime number spirals.
|
|
472
|
+
|
|
473
|
+
```python
|
|
474
|
+
class PrimeSpiral(Scene):
|
|
475
|
+
"""Ulam-like prime spiral visualization."""
|
|
476
|
+
|
|
477
|
+
def construct(self):
|
|
478
|
+
# Generate dots for integers 1 to N
|
|
479
|
+
N = 5000
|
|
480
|
+
dots = VGroup()
|
|
481
|
+
prime_dots = VGroup()
|
|
482
|
+
|
|
483
|
+
for n in range(1, N):
|
|
484
|
+
# Polar coordinates: angle = n, radius = sqrt(n)
|
|
485
|
+
angle = n
|
|
486
|
+
radius = np.sqrt(n) * 0.05
|
|
487
|
+
point = radius * np.array([np.cos(angle), np.sin(angle), 0])
|
|
488
|
+
dot = Dot(point, radius=0.02)
|
|
489
|
+
|
|
490
|
+
if self._is_prime(n):
|
|
491
|
+
dot.set_color(TEAL)
|
|
492
|
+
prime_dots.add(dot)
|
|
493
|
+
else:
|
|
494
|
+
dot.set_color(GREY_D)
|
|
495
|
+
dot.set_opacity(0.2)
|
|
496
|
+
dots.add(dot)
|
|
497
|
+
|
|
498
|
+
self.play(
|
|
499
|
+
LaggedStartMap(FadeIn, dots, lag_ratio=0.001),
|
|
500
|
+
run_time=5,
|
|
501
|
+
)
|
|
502
|
+
self.wait(2)
|
|
503
|
+
|
|
504
|
+
@staticmethod
|
|
505
|
+
def _is_prime(n):
|
|
506
|
+
if n < 2:
|
|
507
|
+
return False
|
|
508
|
+
for k in range(2, int(np.sqrt(n)) + 1):
|
|
509
|
+
if n % k == 0:
|
|
510
|
+
return False
|
|
511
|
+
return True
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
## Topology
|
|
515
|
+
|
|
516
|
+
From `_2020/surface_play.py`, `_2024/inscribed_rect/`.
|
|
517
|
+
|
|
518
|
+
### 3D Surface Construction
|
|
519
|
+
|
|
520
|
+
```python
|
|
521
|
+
class SurfaceVisualization(ThreeDScene):
|
|
522
|
+
"""Torus, sphere, and Mobius strip -- from surface_play.py."""
|
|
523
|
+
|
|
524
|
+
def construct(self):
|
|
525
|
+
self.set_camera_orientation(phi=70 * DEGREES, theta=-45 * DEGREES)
|
|
526
|
+
|
|
527
|
+
# Torus
|
|
528
|
+
torus = Surface(
|
|
529
|
+
lambda u, v: np.array([
|
|
530
|
+
(3 + np.cos(v)) * np.cos(u),
|
|
531
|
+
(3 + np.cos(v)) * np.sin(u),
|
|
532
|
+
np.sin(v),
|
|
533
|
+
]),
|
|
534
|
+
u_range=[0, TAU],
|
|
535
|
+
v_range=[0, TAU],
|
|
536
|
+
resolution=(30, 20),
|
|
537
|
+
)
|
|
538
|
+
torus.set_fill_by_checkerboard(BLUE_D, BLUE_E, opacity=0.8)
|
|
539
|
+
torus.scale(0.5)
|
|
540
|
+
|
|
541
|
+
self.play(Create(torus), run_time=3)
|
|
542
|
+
self.begin_ambient_camera_rotation(rate=0.2)
|
|
543
|
+
self.wait(5)
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
## Neural Networks / Machine Learning
|
|
547
|
+
|
|
548
|
+
From `_2024/transformers/` (attention, embedding, mlp, helpers).
|
|
549
|
+
|
|
550
|
+
### Weight Matrix Visualization
|
|
551
|
+
|
|
552
|
+
```python
|
|
553
|
+
class WeightMatrixViz(Scene):
|
|
554
|
+
"""Heatmap-style weight matrix -- from transformers helpers."""
|
|
555
|
+
|
|
556
|
+
def construct(self):
|
|
557
|
+
# Create matrix with color-coded entries
|
|
558
|
+
n_rows, n_cols = 6, 8
|
|
559
|
+
values = np.random.randn(n_rows, n_cols)
|
|
560
|
+
|
|
561
|
+
entries = VGroup()
|
|
562
|
+
cell_size = 0.5
|
|
563
|
+
for i in range(n_rows):
|
|
564
|
+
for j in range(n_cols):
|
|
565
|
+
val = values[i, j]
|
|
566
|
+
# value_to_color: positive=BLUE, negative=RED
|
|
567
|
+
alpha = min(abs(val) / 3, 1)
|
|
568
|
+
if val >= 0:
|
|
569
|
+
color = interpolate_color(BLUE_E, BLUE_B, alpha)
|
|
570
|
+
else:
|
|
571
|
+
color = interpolate_color(RED_E, RED_B, alpha)
|
|
572
|
+
|
|
573
|
+
cell = Square(side_length=cell_size)
|
|
574
|
+
cell.set_fill(color, opacity=0.8)
|
|
575
|
+
cell.set_stroke(WHITE, 0.5)
|
|
576
|
+
cell.move_to([j * cell_size, -i * cell_size, 0])
|
|
577
|
+
entries.add(cell)
|
|
578
|
+
|
|
579
|
+
entries.center()
|
|
580
|
+
|
|
581
|
+
# Brackets
|
|
582
|
+
left_bracket = MathTex(r"\left[", font_size=72)
|
|
583
|
+
right_bracket = MathTex(r"\right]", font_size=72)
|
|
584
|
+
left_bracket.next_to(entries, LEFT, buff=0.1)
|
|
585
|
+
right_bracket.next_to(entries, RIGHT, buff=0.1)
|
|
586
|
+
|
|
587
|
+
matrix_group = VGroup(left_bracket, entries, right_bracket)
|
|
588
|
+
|
|
589
|
+
label = MathTex(r"W_Q", font_size=36, color=YELLOW)
|
|
590
|
+
label.next_to(matrix_group, UP)
|
|
591
|
+
|
|
592
|
+
self.play(
|
|
593
|
+
FadeIn(entries, lag_ratio=0.01),
|
|
594
|
+
Write(left_bracket), Write(right_bracket),
|
|
595
|
+
Write(label),
|
|
596
|
+
run_time=2,
|
|
597
|
+
)
|
|
598
|
+
self.wait(2)
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
### Attention Arcs (from transformers/attention.py)
|
|
602
|
+
|
|
603
|
+
```python
|
|
604
|
+
class AttentionArcs(Scene):
|
|
605
|
+
"""Visualize attention patterns between words -- from 3b1b's transformer series."""
|
|
606
|
+
|
|
607
|
+
def construct(self):
|
|
608
|
+
words = ["a", "fluffy", "blue", "creature", "roamed"]
|
|
609
|
+
word_mobs = VGroup(*[Text(w, font_size=30) for w in words])
|
|
610
|
+
word_mobs.arrange(RIGHT, buff=0.6)
|
|
611
|
+
word_mobs.shift(UP)
|
|
612
|
+
|
|
613
|
+
# Word rectangles
|
|
614
|
+
rects = VGroup(*[
|
|
615
|
+
SurroundingRectangle(w, buff=0.1, stroke_color=GREY, stroke_width=1)
|
|
616
|
+
for w in word_mobs
|
|
617
|
+
])
|
|
618
|
+
|
|
619
|
+
self.play(
|
|
620
|
+
LaggedStartMap(FadeIn, word_mobs, shift=0.5 * UP, lag_ratio=0.25)
|
|
621
|
+
)
|
|
622
|
+
self.play(FadeIn(rects))
|
|
623
|
+
self.wait()
|
|
624
|
+
|
|
625
|
+
# Attention arcs: adjectives attend to their nouns
|
|
626
|
+
connections = [(1, 3), (2, 3)] # "fluffy"->creature, "blue"->creature
|
|
627
|
+
arcs = VGroup()
|
|
628
|
+
for src, tgt in connections:
|
|
629
|
+
arc = Arrow(
|
|
630
|
+
word_mobs[src].get_top(),
|
|
631
|
+
word_mobs[tgt].get_top(),
|
|
632
|
+
path_arc=-150 * DEGREES,
|
|
633
|
+
buff=0.1,
|
|
634
|
+
stroke_color=GREY_B,
|
|
635
|
+
stroke_width=2,
|
|
636
|
+
)
|
|
637
|
+
arcs.add(arc)
|
|
638
|
+
|
|
639
|
+
self.play(LaggedStartMap(Create, arcs, lag_ratio=0.3, run_time=1.5))
|
|
640
|
+
self.wait(2)
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
### Embedding Vectors
|
|
644
|
+
|
|
645
|
+
```python
|
|
646
|
+
class EmbeddingVisualization(Scene):
|
|
647
|
+
"""Token embedding as a column of colored numbers."""
|
|
648
|
+
|
|
649
|
+
def construct(self):
|
|
650
|
+
# Create a numeric embedding display
|
|
651
|
+
values = np.random.randn(10)
|
|
652
|
+
entries = VGroup()
|
|
653
|
+
for val in values:
|
|
654
|
+
alpha = min(abs(val) / 2, 1)
|
|
655
|
+
color = interpolate_color(BLUE_E, BLUE_B, alpha) if val >= 0 else \
|
|
656
|
+
interpolate_color(RED_E, RED_B, alpha)
|
|
657
|
+
dec = DecimalNumber(val, num_decimal_places=2, font_size=24)
|
|
658
|
+
dec.set_color(color)
|
|
659
|
+
entries.add(dec)
|
|
660
|
+
|
|
661
|
+
entries.arrange(DOWN, buff=0.15)
|
|
662
|
+
|
|
663
|
+
# Brackets
|
|
664
|
+
left_b = MathTex(r"\left[", font_size=60).next_to(entries, LEFT, buff=0.1)
|
|
665
|
+
right_b = MathTex(r"\right]", font_size=60).next_to(entries, RIGHT, buff=0.1)
|
|
666
|
+
|
|
667
|
+
embedding = VGroup(left_b, entries, right_b)
|
|
668
|
+
|
|
669
|
+
# Label
|
|
670
|
+
word = Text("creature", font_size=30)
|
|
671
|
+
word.next_to(embedding, UP, buff=0.5)
|
|
672
|
+
arrow = Arrow(word.get_bottom(), embedding.get_top(), buff=0.1)
|
|
673
|
+
|
|
674
|
+
self.play(Write(word))
|
|
675
|
+
self.play(GrowArrow(arrow))
|
|
676
|
+
self.play(FadeIn(embedding, shift=0.5 * DOWN))
|
|
677
|
+
self.wait(2)
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
## Best Practices by Domain
|
|
681
|
+
|
|
682
|
+
1. **Linear Algebra**: Always use GREEN for x/i-hat, RED for y/j-hat, BLUE for z/k-hat
|
|
683
|
+
2. **Calculus**: Show the geometric meaning alongside every formula
|
|
684
|
+
3. **Probability**: Use bar charts with gradient coloring (BLUE to TEAL)
|
|
685
|
+
4. **Complex Analysis**: Use ComplexPlane with `apply_complex_function()` for transformations
|
|
686
|
+
5. **Number Theory**: Polar coordinate layouts reveal hidden structure
|
|
687
|
+
6. **Topology**: Use ThreeDScene with ambient camera rotation for surfaces
|
|
688
|
+
7. **Neural Networks**: Color-code matrix entries by value (positive=BLUE, negative=RED)
|
|
689
|
+
8. **Across all domains**: Use `tex_to_color_map` / `t2c` for consistent color-coded equations
|