Animation engine for explanatory math videos with programmatic mathematical visualization capabilities
—
ManimGL provides specialized tools for visualizing matrices and linear algebra concepts through the matrix module. These components enable the creation of matrix displays, linear transformation demonstrations, and educational content around linear algebra with proper mathematical formatting and interactive capabilities.
Create visual representations of matrices with proper mathematical formatting, brackets, and element positioning for linear algebra demonstrations.
class Matrix(VMobject):
def __init__(
self,
matrix: list[list] | np.ndarray,
v_buff: float = 0.8,
h_buff: float = 1.3,
bracket_h_buff: float = MED_SMALL_BUFF,
bracket_v_buff: float = MED_SMALL_BUFF,
add_background_rectangles_to_entries: bool = False,
include_background_rectangle: bool = False,
element_to_mobject: Callable = TexText,
element_to_mobject_config: dict = {},
element_alignment_corner: np.ndarray = ORIGIN,
**kwargs
):
"""
Create a visual matrix with proper mathematical formatting.
Parameters:
- matrix: 2D array or list of lists representing matrix elements
- v_buff: Vertical spacing between matrix rows
- h_buff: Horizontal spacing between matrix columns
- bracket_h_buff: Horizontal buffer for brackets
- bracket_v_buff: Vertical buffer for brackets
- add_background_rectangles_to_entries: Add backgrounds to elements
- include_background_rectangle: Add background to entire matrix
- element_to_mobject: Function to convert elements to mobjects
- element_to_mobject_config: Configuration for element conversion
- element_alignment_corner: Alignment point for elements
"""
def get_entries(self) -> VGroup:
"""Get all matrix entries as a VGroup."""
def get_brackets(self) -> VGroup:
"""Get the matrix brackets."""
def get_mob_matrix(self) -> list[list]:
"""Get matrix elements as nested list of mobjects."""
def set_column_colors(self, *colors):
"""Set colors for matrix columns."""
def add_background_to_entries(self):
"""Add background rectangles to matrix entries."""Display vectors as column matrices with specialized formatting for vector operations and transformations.
class Vector(Matrix):
def __init__(self, vector: list | np.ndarray, **kwargs):
"""
Create a column vector display.
Parameters:
- vector: 1D array or list representing vector components
- kwargs: Additional Matrix parameters
"""
class IntegerMatrix(Matrix):
def __init__(self, matrix: list[list] | np.ndarray, **kwargs):
"""
Matrix specialized for integer entries with proper formatting.
Parameters:
- matrix: Matrix with integer entries
- kwargs: Additional Matrix parameters
"""
class DecimalMatrix(Matrix):
def __init__(
self,
matrix: list[list] | np.ndarray,
num_decimal_places: int = 2,
**kwargs
):
"""
Matrix specialized for decimal number display.
Parameters:
- matrix: Matrix with decimal entries
- num_decimal_places: Number of decimal places to display
- kwargs: Additional Matrix parameters
"""Tools for demonstrating matrix operations, transformations, and linear algebra concepts with visual feedback.
def get_det_text(
matrix: Matrix,
determinant: float | None = None,
background_rect: bool = False,
initial_scale_factor: float = 2
) -> VMobject:
"""
Create determinant notation for a matrix.
Parameters:
- matrix: Matrix object to show determinant for
- determinant: Determinant value (calculated if None)
- background_rect: Add background rectangle
- initial_scale_factor: Initial scaling for animation
Returns:
Determinant notation as VMobject
"""from manimlib import *
class BasicMatrixDemo(Scene):
def construct(self):
# Create a simple 2x2 matrix
matrix_data = [[1, 2], [3, 4]]
matrix = Matrix(matrix_data)
matrix.set_color(BLUE)
# Add title
title = Text("2×2 Matrix", font_size=36).to_edge(UP)
self.play(Write(title))
self.play(ShowCreation(matrix))
# Highlight individual elements
entries = matrix.get_entries()
for i, entry in enumerate(entries):
self.play(
entry.animate.set_color(YELLOW).scale(1.5),
run_time=0.5
)
self.play(
entry.animate.set_color(BLUE).scale(1/1.5),
run_time=0.5
)
self.wait()class LinearTransformation(Scene):
def construct(self):
# Original vector
original_vector = Vector([3, 2])
original_vector.set_color(GREEN)
original_vector.to_edge(LEFT)
# Transformation matrix
transform_matrix = Matrix([[2, 1], [0, 1]])
transform_matrix.set_color(BLUE)
# Result vector (computed)
result_data = np.array([[2, 1], [0, 1]]) @ np.array([3, 2])
result_vector = Vector(result_data)
result_vector.set_color(RED)
result_vector.to_edge(RIGHT)
# Labels
original_label = Text("Original Vector", font_size=24)
original_label.next_to(original_vector, DOWN)
matrix_label = Text("Transformation Matrix", font_size=24)
matrix_label.next_to(transform_matrix, DOWN)
result_label = Text("Transformed Vector", font_size=24)
result_label.next_to(result_vector, DOWN)
# Show transformation sequence
self.play(
ShowCreation(original_vector),
Write(original_label)
)
self.wait()
self.play(
ShowCreation(transform_matrix),
Write(matrix_label)
)
self.wait()
# Animate the transformation
equals = Text("=", font_size=48)
multiplication = VGroup(
transform_matrix,
original_vector.copy(),
equals,
result_vector
).arrange(RIGHT, buff=0.5)
self.play(
Transform(
VGroup(transform_matrix, original_vector),
multiplication[:2]
),
Write(equals),
ShowCreation(result_vector),
Write(result_label)
)
self.wait()class MatrixOperations(Scene):
def construct(self):
# Matrix addition demonstration
matrix_a = Matrix([[1, 2], [3, 4]])
matrix_a.set_color(BLUE)
matrix_b = Matrix([[5, 6], [7, 8]])
matrix_b.set_color(GREEN)
# Result matrix
result_data = [[6, 8], [10, 12]]
result_matrix = Matrix(result_data)
result_matrix.set_color(YELLOW)
# Arrange for addition
plus = Text("+", font_size=48)
equals = Text("=", font_size=48)
addition_group = VGroup(
matrix_a, plus, matrix_b, equals, result_matrix
).arrange(RIGHT, buff=0.5)
title = Text("Matrix Addition", font_size=36).to_edge(UP)
self.play(Write(title))
self.play(ShowCreation(matrix_a))
self.play(Write(plus))
self.play(ShowCreation(matrix_b))
self.wait()
# Show element-wise addition
entries_a = matrix_a.get_entries()
entries_b = matrix_b.get_entries()
for i in range(len(entries_a)):
self.play(
entries_a[i].animate.set_color(RED),
entries_b[i].animate.set_color(RED),
run_time=0.5
)
self.play(
entries_a[i].animate.set_color(BLUE),
entries_b[i].animate.set_color(GREEN),
run_time=0.3
)
self.play(Write(equals))
self.play(ShowCreation(result_matrix))
self.wait()class DeterminantDemo(Scene):
def construct(self):
# Create matrix for determinant
matrix_data = [[3, 1], [2, 4]]
matrix = Matrix(matrix_data)
matrix.set_color(BLUE)
# Calculate determinant
det_value = 3 * 4 - 1 * 2 # 10
# Show determinant notation
det_text = get_det_text(matrix, det_value)
det_text.next_to(matrix, RIGHT, buff=1)
title = Text("Determinant Calculation", font_size=36).to_edge(UP)
self.play(Write(title))
self.play(ShowCreation(matrix))
# Highlight diagonal elements
entries = matrix.get_entries()
# Main diagonal (3, 4)
main_diag = VGroup(entries[0], entries[3])
self.play(main_diag.animate.set_color(GREEN))
# Anti-diagonal (1, 2)
anti_diag = VGroup(entries[1], entries[2])
self.play(anti_diag.animate.set_color(RED))
# Show calculation
calculation = TexText(
f"det = (3)(4) - (1)(2) = 12 - 2 = {det_value}",
font_size=24
).to_edge(DOWN)
self.play(Write(calculation))
self.play(ShowCreation(det_text))
# Reset colors
self.play(entries.animate.set_color(BLUE))
self.wait()class EigenvalueDemo(Scene):
def construct(self):
# Matrix with known eigenvalues
matrix_data = [[3, 1], [0, 2]]
matrix = Matrix(matrix_data)
matrix.set_color(BLUE)
# Eigenvectors
eigenvector1 = Vector([1, 0]) # For eigenvalue 3
eigenvector1.set_color(GREEN)
eigenvector2 = Vector([1, -1]) # For eigenvalue 2
eigenvector2.set_color(RED)
# Arrange display
matrix.to_edge(LEFT)
eigen_group = VGroup(eigenvector1, eigenvector2)
eigen_group.arrange(RIGHT, buff=1).to_edge(RIGHT)
# Labels
matrix_label = Text("Matrix A", font_size=24).next_to(matrix, DOWN)
eigen_label1 = Text("λ₁ = 3", font_size=20).next_to(eigenvector1, DOWN)
eigen_label2 = Text("λ₂ = 2", font_size=20).next_to(eigenvector2, DOWN)
title = Text("Eigenvalues and Eigenvectors", font_size=32).to_edge(UP)
self.play(Write(title))
self.play(ShowCreation(matrix), Write(matrix_label))
self.wait()
# Show first eigenvector
self.play(
ShowCreation(eigenvector1),
Write(eigen_label1)
)
# Demonstrate Av₁ = λ₁v₁
equation1 = TexText(
"Av₁ = 3v₁", font_size=24
).next_to(eigenvector1, UP)
self.play(Write(equation1))
self.wait()
# Show second eigenvector
self.play(
ShowCreation(eigenvector2),
Write(eigen_label2)
)
equation2 = TexText(
"Av₂ = 2v₂", font_size=24
).next_to(eigenvector2, UP)
self.play(Write(equation2))
self.wait()from manimlib.mobject.interactive import Textbox
class InteractiveMatrix(Scene):
def setup(self):
# Create input textboxes for matrix elements
self.textboxes = []
positions = [
[-1, 0.5], [1, 0.5], # First row
[-1, -0.5], [1, -0.5] # Second row
]
for pos in positions:
textbox = Textbox(value="1", box_kwargs={"width": 0.8, "height": 0.6})
textbox.move_to(pos)
self.textboxes.append(textbox)
self.add(textbox)
def construct(self):
# Create responsive matrix display
def get_current_matrix():
try:
values = []
for i in range(0, 4, 2): # Process in pairs for 2x2
row = [
float(self.textboxes[i].get_value() or "1"),
float(self.textboxes[i+1].get_value() or "1")
]
values.append(row)
return Matrix(values)
except ValueError:
# Return identity matrix if invalid input
return Matrix([[1, 0], [0, 1]])
# Display matrix
display_matrix = get_current_matrix()
display_matrix.scale(1.5).to_edge(RIGHT)
def update_matrix(m):
new_matrix = get_current_matrix()
new_matrix.scale(1.5).to_edge(RIGHT)
m.become(new_matrix)
display_matrix.add_updater(update_matrix)
# Calculate and display determinant
det_display = Text("det = 1.0", font_size=24).to_edge(DOWN)
def update_determinant(d):
try:
a = float(self.textboxes[0].get_value() or "1")
b = float(self.textboxes[1].get_value() or "1")
c = float(self.textboxes[2].get_value() or "1")
d_val = float(self.textboxes[3].get_value() or "1")
det = a * d_val - b * c
new_text = Text(f"det = {det:.2f}", font_size=24)
new_text.to_edge(DOWN)
d.become(new_text)
except ValueError:
pass
det_display.add_updater(update_determinant)
# Labels
title = Text("Interactive Matrix Editor", font_size=32).to_edge(UP)
instruction = Text("Click boxes to edit values", font_size=20)
instruction.next_to(title, DOWN)
self.add(display_matrix, det_display, title, instruction)
self.wait(20) # Interactive exploration time# Smooth matrix transformations
def animate_matrix_transform(scene, matrix, new_data, run_time=2):
"""Animate smooth transition between matrix states."""
# Custom animation logic for matrix entries
pass
# Row operations visualization
def show_row_operation(scene, matrix, operation_type, rows, scalar=1):
"""Visualize elementary row operations."""
# Highlight affected rows and show operation
pass# Color-coded matrices for different purposes
def create_identity_matrix(size, highlight_diagonal=True):
"""Create identity matrix with diagonal highlighting."""
pass
def create_augmented_matrix(left_matrix, right_vector):
"""Create augmented matrix for solving systems."""
passThe matrix visualization module in ManimGL provides comprehensive tools for linear algebra education and demonstration, enabling clear visualization of matrix operations, transformations, and mathematical concepts with proper formatting and interactive capabilities.
Install with Tessl CLI
npx tessl i tessl/pypi-manimgldocs