Animation engine for explanatory math videos.
—
Essential utility functions including mathematical operations, color management, rate functions, file operations, and debugging tools for animation development. These utilities provide the foundational support functions that enable smooth animation development and mathematical precision.
Fundamental mathematical and spatial constants used throughout Manim for positioning, animation, and mathematical calculations.
# Coordinate system constants
ORIGIN: np.ndarray # [0, 0, 0] - Center of coordinate system
# Direction vectors (unit vectors)
UP: np.ndarray # [0, 1, 0] - Positive y direction
DOWN: np.ndarray # [0, -1, 0] - Negative y direction
LEFT: np.ndarray # [-1, 0, 0] - Negative x direction
RIGHT: np.ndarray # [1, 0, 0] - Positive x direction
IN: np.ndarray # [0, 0, -1] - Negative z direction (into screen)
OUT: np.ndarray # [0, 0, 1] - Positive z direction (out of screen)
# Coordinate axes
X_AXIS: np.ndarray # [1, 0, 0] - X-axis unit vector
Y_AXIS: np.ndarray # [0, 1, 0] - Y-axis unit vector
Z_AXIS: np.ndarray # [0, 0, 1] - Z-axis unit vector
# Diagonal directions (combinations)
UL: np.ndarray # UP + LEFT - Upper left diagonal
UR: np.ndarray # UP + RIGHT - Upper right diagonal
DL: np.ndarray # DOWN + LEFT - Lower left diagonal
DR: np.ndarray # DOWN + RIGHT - Lower right diagonal
# Mathematical constants
PI: float # π (pi) ≈ 3.14159
TAU: float # 2π (tau) ≈ 6.28318 - full circle
DEGREES: float # π/180 - conversion factor from degrees to radians
# Size and spacing constants
DEFAULT_DOT_RADIUS: float = 0.08
DEFAULT_SMALL_DOT_RADIUS: float = 0.04
DEFAULT_DASH_LENGTH: float = 0.05
DEFAULT_ARROW_TIP_LENGTH: float = 0.35
DEFAULT_STROKE_WIDTH: float = 4
DEFAULT_FONT_SIZE: float = 48
# Buffer distances for spacing
SMALL_BUFF: float = 0.1 # Small buffer distance
MED_SMALL_BUFF: float = 0.25 # Medium-small buffer
MED_LARGE_BUFF: float = 0.5 # Medium-large buffer
LARGE_BUFF: float = 1.0 # Large buffer distance
# Default positioning buffers
DEFAULT_MOBJECT_TO_EDGE_BUFFER: float = 0.5
DEFAULT_MOBJECT_TO_MOBJECT_BUFFER: float = 0.25
# Animation timing constants
DEFAULT_POINTWISE_FUNCTION_RUN_TIME: float = 3.0
DEFAULT_WAIT_TIME: float = 1.0
# Quality settings density
DEFAULT_POINT_DENSITY_2D: float = 25
DEFAULT_POINT_DENSITY_1D: float = 250
# Font and text scaling
SCALE_FACTOR_PER_FONT_POINT: float = 0.001
# Rendering quality constants
QUALITIES: dict = {
"fourk_quality": "4k quality rendering",
"production_quality": "Production quality rendering",
"high_quality": "High quality rendering",
"medium_quality": "Medium quality rendering",
"low_quality": "Low quality rendering",
"example_quality": "Example quality rendering"
}
DEFAULT_QUALITY: str = "high_quality"
# Renderer configuration
class RendererType:
"""Enumeration of available renderer types."""
CAIRO: str = "cairo" # Cairo 2D renderer
OPENGL: str = "opengl" # OpenGL 3D renderer
# Line styling enums
class LineJointType:
"""Enumeration of line joint types for stroke rendering."""
AUTO: int = 0 # Automatic joint type selection
ROUND: int = 1 # Rounded line joints
BEVEL: int = 2 # Beveled line joints
MITER: int = 3 # Mitered line joints
class CapStyleType:
"""Enumeration of line cap styles for stroke ends."""
AUTO: int = 0 # Automatic cap style selection
ROUND: int = 1 # Rounded line caps
BUTT: int = 2 # Flat butt line caps
SQUARE: int = 3 # Square line caps
# Font weight constants
THIN: int = 100
ULTRALIGHT: int = 200
LIGHT: int = 300
SEMILIGHT: int = 350
BOOK: int = 380
NORMAL: int = 400
MEDIUM: int = 500
SEMIBOLD: int = 600
BOLD: int = 700
ULTRABOLD: int = 800
HEAVY: int = 900
ULTRAHEAVY: int = 1000
# Font style constants
ITALIC: str = "italic"
OBLIQUE: str = "oblique"
# Interface constants
SHIFT_VALUE: int = 65505 # Keyboard shift key value
CTRL_VALUE: int = 65507 # Keyboard control key value
START_X: int = 30 # Default window x position
START_Y: int = 20 # Default window y positionMathematical functions that control animation timing and easing for natural, expressive motion curves.
# Basic rate functions
def linear(t: float) -> float:
"""
Linear interpolation - constant speed throughout animation.
Parameters:
- t: Time parameter [0, 1]
Returns:
- float: Linear progress [0, 1]
"""
def smooth(t: float) -> float:
"""
Smooth S-curve interpolation using smoothstep function.
Provides smooth acceleration and deceleration with no sudden changes
in velocity at start or end.
Parameters:
- t: Time parameter [0, 1]
Returns:
- float: Smooth progress [0, 1]
"""
def rush_into(t: float) -> float:
"""
Start slow, then rapidly accelerate toward end.
Parameters:
- t: Time parameter [0, 1]
Returns:
- float: Rush-in progress [0, 1]
"""
def rush_from(t: float) -> float:
"""
Start fast, then decelerate toward end.
Parameters:
- t: Time parameter [0, 1]
Returns:
- float: Rush-from progress [0, 1]
"""
def slow_into(t: float) -> float:
"""
Gradually accelerate throughout animation.
Parameters:
- t: Time parameter [0, 1]
Returns:
- float: Slow-into progress [0, 1]
"""
def double_smooth(t: float) -> float:
"""
Extra smooth S-curve with more gradual acceleration/deceleration.
Parameters:
- t: Time parameter [0, 1]
Returns:
- float: Double-smooth progress [0, 1]
"""
def there_and_back(t: float) -> float:
"""
Go from 0 to 1 and back to 0 during animation.
Creates a motion that reaches the target at the midpoint
then returns to the starting position.
Parameters:
- t: Time parameter [0, 1]
Returns:
- float: There-and-back progress [0, 1, 0]
"""
def there_and_back_with_pause(
t: float,
pause_ratio: float = 1/3
) -> float:
"""
Go to target, pause, then return with customizable pause duration.
Parameters:
- t: Time parameter [0, 1]
- pause_ratio: Fraction of time to pause at target
Returns:
- float: Progress with pause [0, 1, pause, 0]
"""
def running_start(
t: float,
pull_factor: float = -0.5
) -> float:
"""
Start by moving backward, then accelerate forward.
Creates anticipation by initially moving in opposite direction
before accelerating toward target.
Parameters:
- t: Time parameter [0, 1]
- pull_factor: How far backward to go initially
Returns:
- float: Running start progress
"""
def wiggle(t: float, wiggles: float = 2) -> float:
"""
Oscillating motion that settles at target.
Parameters:
- t: Time parameter [0, 1]
- wiggles: Number of oscillations
Returns:
- float: Wiggling progress [0, 1]
"""
def exponential_decay(t: float) -> float:
"""
Exponentially approach target value.
Parameters:
- t: Time parameter [0, 1]
Returns:
- float: Exponential progress [0, 1)
"""
# Standard easing functions (CSS/web animation style)
# Sine easing
def ease_in_sine(t: float) -> float:
"""Sine-based ease-in curve."""
def ease_out_sine(t: float) -> float:
"""Sine-based ease-out curve."""
def ease_in_out_sine(t: float) -> float:
"""Sine-based ease-in-out curve."""
# Quadratic easing
def ease_in_quad(t: float) -> float:
"""Quadratic ease-in curve (t²)."""
def ease_out_quad(t: float) -> float:
"""Quadratic ease-out curve."""
def ease_in_out_quad(t: float) -> float:
"""Quadratic ease-in-out curve."""
# Cubic easing
def ease_in_cubic(t: float) -> float:
"""Cubic ease-in curve (t³)."""
def ease_out_cubic(t: float) -> float:
"""Cubic ease-out curve."""
def ease_in_out_cubic(t: float) -> float:
"""Cubic ease-in-out curve."""
# Quartic easing
def ease_in_quart(t: float) -> float:
"""Quartic ease-in curve (t⁴)."""
def ease_out_quart(t: float) -> float:
"""Quartic ease-out curve."""
def ease_in_out_quart(t: float) -> float:
"""Quartic ease-in-out curve."""
# Exponential easing
def ease_in_expo(t: float) -> float:
"""Exponential ease-in curve."""
def ease_out_expo(t: float) -> float:
"""Exponential ease-out curve."""
def ease_in_out_expo(t: float) -> float:
"""Exponential ease-in-out curve."""
# Circular easing
def ease_in_circ(t: float) -> float:
"""Circular ease-in curve."""
def ease_out_circ(t: float) -> float:
"""Circular ease-out curve."""
def ease_in_out_circ(t: float) -> float:
"""Circular ease-in-out curve."""
# Back easing (overshoots target)
def ease_in_back(t: float) -> float:
"""Back ease-in with overshoot."""
def ease_out_back(t: float) -> float:
"""Back ease-out with overshoot."""
def ease_in_out_back(t: float) -> float:
"""Back ease-in-out with overshoot."""
# Elastic easing (bouncing effect)
def ease_in_elastic(t: float) -> float:
"""Elastic ease-in with bouncing."""
def ease_out_elastic(t: float) -> float:
"""Elastic ease-out with bouncing."""
def ease_in_out_elastic(t: float) -> float:
"""Elastic ease-in-out with bouncing."""
# Bounce easing
def ease_in_bounce(t: float) -> float:
"""Bounce ease-in curve."""
def ease_out_bounce(t: float) -> float:
"""Bounce ease-out curve."""
def ease_in_out_bounce(t: float) -> float:
"""Bounce ease-in-out curve."""
# Rate function utilities
def squish_rate_func(
func: Callable[[float], float],
a: float = 0.4,
b: float = 0.6
) -> Callable[[float], float]:
"""
Compress rate function to operate within [a, b] interval.
Parameters:
- func: Rate function to compress
- a: Start of active interval
- b: End of active interval
Returns:
- Callable: Compressed rate function
"""
def lingering(t: float) -> float:
"""
Linger at start, then smoothly progress to end.
Parameters:
- t: Time parameter [0, 1]
Returns:
- float: Lingering progress [0, 1]
"""Comprehensive color management system with predefined colors, color space conversions, and gradient utilities.
# Color class and core functions
class ManimColor:
"""
Manim color class supporting multiple color spaces and formats.
Handles color parsing, conversion, and manipulation with support
for RGB, HSV, hex, and named colors.
"""
def __init__(color_value: str | tuple | np.ndarray) -> None:
"""
Parameters:
- color_value: Color specification (hex, name, RGB tuple, etc.)
"""
@staticmethod
def parse(color: str | ManimColor) -> ManimColor:
"""Parse color from various input formats."""
def hex() -> str:
"""Get color as hex string (#RRGGBB)."""
def rgb() -> tuple[float, float, float]:
"""Get color as RGB tuple [0,1]."""
def rgba() -> tuple[float, float, float, float]:
"""Get color as RGBA tuple [0,1]."""
def hsv() -> tuple[float, float, float]:
"""Get color as HSV tuple."""
def invert() -> ManimColor:
"""Get inverted/complementary color."""
def interpolate(other: ManimColor, alpha: float) -> ManimColor:
"""Interpolate between this color and another."""
# Core color constants (most commonly used)
WHITE: ManimColor
BLACK: ManimColor
GRAY: ManimColor
GREY: ManimColor # Alternative spelling
RED: ManimColor
GREEN: ManimColor
BLUE: ManimColor
YELLOW: ManimColor
ORANGE: ManimColor
PURPLE: ManimColor
PINK: ManimColor
BROWN: ManimColor
# Extended color palette
RED_A: ManimColor # Light red
RED_B: ManimColor # Medium red
RED_C: ManimColor # Standard red
RED_D: ManimColor # Dark red
RED_E: ManimColor # Very dark red
BLUE_A: ManimColor # Light blue
BLUE_B: ManimColor # Medium blue
BLUE_C: ManimColor # Standard blue
BLUE_D: ManimColor # Dark blue
BLUE_E: ManimColor # Very dark blue
GREEN_A: ManimColor # Light green
GREEN_B: ManimColor # Medium green
GREEN_C: ManimColor # Standard green
GREEN_D: ManimColor # Dark green
GREEN_E: ManimColor # Very dark green
# Additional standard colors
MAROON_A: ManimColor
MAROON_B: ManimColor
MAROON_C: ManimColor
MAROON_D: ManimColor
MAROON_E: ManimColor
YELLOW_A: ManimColor
YELLOW_B: ManimColor
YELLOW_C: ManimColor
YELLOW_D: ManimColor
YELLOW_E: ManimColor
TEAL_A: ManimColor
TEAL_B: ManimColor
TEAL_C: ManimColor
TEAL_D: ManimColor
TEAL_E: ManimColor
GOLD_A: ManimColor
GOLD_B: ManimColor
GOLD_C: ManimColor
GOLD_D: ManimColor
GOLD_E: ManimColor
# Color manipulation functions
def interpolate_color(
color1: ManimColor | str,
color2: ManimColor | str,
alpha: float
) -> ManimColor:
"""
Interpolate between two colors.
Parameters:
- color1: Starting color
- color2: Ending color
- alpha: Interpolation factor [0, 1]
Returns:
- ManimColor: Interpolated color
"""
def color_gradient(
colors: Sequence[ManimColor | str],
length: int
) -> list[ManimColor]:
"""
Create smooth gradient between multiple colors.
Parameters:
- colors: List of colors to interpolate between
- length: Number of colors in resulting gradient
Returns:
- list[ManimColor]: Gradient color sequence
"""
def random_color() -> ManimColor:
"""Generate random color."""
def random_bright_color() -> ManimColor:
"""Generate random bright/saturated color."""
def invert_color(color: ManimColor | str) -> ManimColor:
"""
Get inverted/complementary color.
Parameters:
- color: Color to invert
Returns:
- ManimColor: Inverted color
"""
def color_to_rgb(color: ManimColor | str) -> np.ndarray:
"""Convert color to RGB array [0,1]."""
def color_to_rgba(
color: ManimColor | str,
alpha: float = 1.0
) -> np.ndarray:
"""Convert color to RGBA array [0,1]."""
def rgb_to_color(rgb: np.ndarray) -> ManimColor:
"""Convert RGB array to ManimColor."""
def hex_to_color(hex_code: str) -> ManimColor:
"""Convert hex string to ManimColor."""
# Extended color collections
# Access additional color palettes
XKCD: module # XKCD color names (XKCD.AVOCADO, etc.)
X11: module # X11 color names
DVIPSNAMES: module # LaTeX DVIPS color names
BS381: module # British Standard colors
AS2700: module # Australian Standard colors
SVGNAMES: module # SVG/HTML color namesMathematical utilities for 3D space calculations, coordinate transformations, and geometric operations.
# Vector operations
def normalize(vect: np.ndarray) -> np.ndarray:
"""
Normalize vector to unit length.
Parameters:
- vect: Vector to normalize
Returns:
- np.ndarray: Unit vector in same direction
"""
def get_norm(vect: np.ndarray) -> float:
"""
Get length/magnitude of vector.
Parameters:
- vect: Input vector
Returns:
- float: Vector magnitude
"""
def cross(v1: np.ndarray, v2: np.ndarray) -> np.ndarray:
"""
Cross product of two 3D vectors.
Parameters:
- v1: First vector
- v2: Second vector
Returns:
- np.ndarray: Cross product vector
"""
def dot(v1: np.ndarray, v2: np.ndarray) -> float:
"""
Dot product of two vectors.
Parameters:
- v1: First vector
- v2: Second vector
Returns:
- float: Dot product scalar
"""
def angle_between_vectors(v1: np.ndarray, v2: np.ndarray) -> float:
"""
Calculate angle between two vectors in radians.
Parameters:
- v1: First vector
- v2: Second vector
Returns:
- float: Angle in radians [0, π]
"""
def angle_of_vector(vector: np.ndarray) -> float:
"""
Get angle of 2D vector from positive x-axis.
Parameters:
- vector: 2D or 3D vector (z-component ignored)
Returns:
- float: Angle in radians [-π, π]
"""
# Coordinate transformations
def spherical_to_cartesian(
radius: float,
theta: float,
phi: float
) -> np.ndarray:
"""
Convert spherical coordinates to Cartesian.
Parameters:
- radius: Radial distance
- theta: Azimuthal angle (from x-axis)
- phi: Polar angle (from z-axis)
Returns:
- np.ndarray: Cartesian coordinates [x, y, z]
"""
def cartesian_to_spherical(point: np.ndarray) -> tuple[float, float, float]:
"""
Convert Cartesian coordinates to spherical.
Parameters:
- point: Cartesian point [x, y, z]
Returns:
- tuple: (radius, theta, phi) in spherical coordinates
"""
def cylindrical_to_cartesian(
radius: float,
theta: float,
z: float
) -> np.ndarray:
"""
Convert cylindrical coordinates to Cartesian.
Parameters:
- radius: Radial distance from z-axis
- theta: Angle around z-axis
- z: Height along z-axis
Returns:
- np.ndarray: Cartesian coordinates [x, y, z]
"""
# Rotation and transformation matrices
def rotation_matrix(
angle: float,
axis: np.ndarray = OUT
) -> np.ndarray:
"""
Create rotation matrix for rotating around specified axis.
Parameters:
- angle: Rotation angle in radians
- axis: Rotation axis vector
Returns:
- np.ndarray: 3x3 rotation matrix
"""
def rotation_about_z(angle: float) -> np.ndarray:
"""Rotation matrix for rotation about z-axis."""
def z_to_vector(z: complex) -> np.ndarray:
"""Convert complex number to 2D vector."""
def complex_to_R3(z: complex) -> np.ndarray:
"""Convert complex number to 3D point [Re(z), Im(z), 0]."""
def R3_to_complex(point: np.ndarray) -> complex:
"""Convert 3D point to complex number."""
def rotate_vector(
vector: np.ndarray,
angle: float,
axis: np.ndarray = OUT
) -> np.ndarray:
"""
Rotate vector around specified axis.
Parameters:
- vector: Vector to rotate
- angle: Rotation angle in radians
- axis: Rotation axis
Returns:
- np.ndarray: Rotated vector
"""
# Geometric utilities
def line_intersection(
line1: tuple[np.ndarray, np.ndarray],
line2: tuple[np.ndarray, np.ndarray]
) -> np.ndarray:
"""
Find intersection point of two 2D lines.
Parameters:
- line1: (point1, point2) defining first line
- line2: (point1, point2) defining second line
Returns:
- np.ndarray: Intersection point
"""
def get_closest_point_on_line(
a: np.ndarray,
b: np.ndarray,
p: np.ndarray
) -> np.ndarray:
"""
Find closest point on line segment to given point.
Parameters:
- a: Line start point
- b: Line end point
- p: Reference point
Returns:
- np.ndarray: Closest point on line to p
"""
def perpendicular_bisector(
line: tuple[np.ndarray, np.ndarray]
) -> tuple[np.ndarray, np.ndarray]:
"""
Get perpendicular bisector of line segment.
Parameters:
- line: (start_point, end_point) of line segment
Returns:
- tuple: (point, direction) defining perpendicular bisector
"""
def compass_directions(n: int = 4, start_vect: np.ndarray = RIGHT) -> list[np.ndarray]:
"""
Generate n evenly spaced unit vectors around circle.
Parameters:
- n: Number of directions
- start_vect: Starting direction
Returns:
- list[np.ndarray]: List of direction vectors
"""File system utilities for handling assets, output files, and resource management.
# File operations
def guarantee_existence(path: str) -> str:
"""
Ensure directory exists, creating it if necessary.
Parameters:
- path: Directory path
Returns:
- str: Verified directory path
"""
def add_extension_if_not_present(
file_name: str,
extension: str
) -> str:
"""
Add file extension if not already present.
Parameters:
- file_name: Base filename
- extension: Extension to add (with or without dot)
Returns:
- str: Filename with extension
"""
def get_sorted_integer_files(directory: str) -> list[str]:
"""
Get list of files with integer names, sorted numerically.
Parameters:
- directory: Directory to search
Returns:
- list[str]: Sorted list of integer-named files
"""
def seek_full_path_from_defaults(
file_name: str,
default_dir: str,
extensions: list[str] = None
) -> str:
"""
Find file in default directory with optional extension matching.
Parameters:
- file_name: Base filename to search for
- default_dir: Directory to search in
- extensions: List of extensions to try
Returns:
- str: Full path to found file
"""
def open_media_file(file_path: str) -> None:
"""
Open media file with system default application.
Parameters:
- file_path: Path to media file
"""
# Path utilities
def get_manim_dir() -> str:
"""Get Manim installation directory."""
def get_downloads_dir() -> str:
"""Get user downloads directory."""
def get_output_dir() -> str:
"""Get configured output directory."""
def get_tex_dir() -> str:
"""Get directory for LaTeX files."""
def get_raster_image_dir() -> str:
"""Get directory for raster images."""
def get_vector_image_dir() -> str:
"""Get directory for vector images."""
# Asset management
def find_file(
file_name: str,
directories: list[str] = None
) -> str:
"""
Search for file in multiple directories.
Parameters:
- file_name: Name of file to find
- directories: List of directories to search
Returns:
- str: Full path to found file
"""Essential mathematical functions and utilities for calculations, interpolation, and numerical operations.
# Interpolation functions
def interpolate(start: float, end: float, alpha: float) -> float:
"""
Linear interpolation between two values.
Parameters:
- start: Starting value
- end: Ending value
- alpha: Interpolation factor [0, 1]
Returns:
- float: Interpolated value
"""
def inverse_interpolate(
start: float,
end: float,
value: float
) -> float:
"""
Find interpolation factor for given value between start and end.
Parameters:
- start: Starting value
- end: Ending value
- value: Value to find factor for
Returns:
- float: Interpolation factor
"""
def clip(value: float, min_val: float, max_val: float) -> float:
"""
Clamp value to specified range.
Parameters:
- value: Value to clamp
- min_val: Minimum allowed value
- max_val: Maximum allowed value
Returns:
- float: Clamped value
"""
def binary_search(
function: Callable[[float], float],
target: float,
lower_bound: float,
upper_bound: float,
tolerance: float = 1e-6
) -> float:
"""
Binary search for input that produces target output.
Parameters:
- function: Function to search
- target: Target output value
- lower_bound: Lower bound for search
- upper_bound: Upper bound for search
- tolerance: Accuracy tolerance
Returns:
- float: Input value producing target output
"""
# Numerical utilities
def choose(n: int, k: int) -> int:
"""
Binomial coefficient "n choose k".
Parameters:
- n: Total number of items
- k: Number to choose
Returns:
- int: Binomial coefficient
"""
def bezier(points: np.ndarray) -> Callable[[float], np.ndarray]:
"""
Create Bézier curve function from control points.
Parameters:
- points: Array of control points
Returns:
- Callable: Function mapping t∈[0,1] to curve points
"""
def partial_bezier_points(
points: np.ndarray,
a: float,
b: float
) -> np.ndarray:
"""
Get control points for partial Bézier curve.
Parameters:
- points: Original control points
- a: Start parameter [0, 1]
- b: End parameter [0, 1]
Returns:
- np.ndarray: Control points for partial curve
"""
# Array and sequence utilities
def make_smooth_bezier_curve_connections(
bezier_point_sets: list[np.ndarray]
) -> list[np.ndarray]:
"""
Connect Bézier curves smoothly by adjusting control points.
Parameters:
- bezier_point_sets: List of Bézier control point sets
Returns:
- list[np.ndarray]: Smoothly connected control point sets
"""
def get_smooth_handle_points(
points: np.ndarray
) -> tuple[np.ndarray, np.ndarray]:
"""
Generate smooth Bézier handles for curve through points.
Parameters:
- points: Points to create smooth curve through
Returns:
- tuple: (left_handles, right_handles) for smooth curve
"""Tools and utilities for debugging animations, performance monitoring, and development workflow enhancement.
# Logging and debugging
from manim import logger
logger.debug(message: str) -> None:
"""Log debug-level message."""
logger.info(message: str) -> None:
"""Log info-level message."""
logger.warning(message: str) -> None:
"""Log warning-level message."""
logger.error(message: str) -> None:
"""Log error-level message."""
# Console output (use instead of print)
from manim import console
console.print(*args, **kwargs) -> None:
"""Rich console print with formatting support."""
console.log(*args, **kwargs) -> None:
"""Rich console log with timestamp."""
# Development utilities
def get_parameters_from_function(func: Callable) -> dict:
"""Extract parameter information from function signature."""
def get_all_descendent_classes(Class: type) -> list[type]:
"""Get all classes that inherit from given class."""
def get_mobject_family_members(
mobjects: list[Mobject],
only_those_with_points: bool = False
) -> list[Mobject]:
"""
Get all mobjects including submobjects in flattened list.
Parameters:
- mobjects: List of mobjects to expand
- only_those_with_points: Whether to include only mobjects with points
Returns:
- list[Mobject]: Flattened list including all submobjects
"""
# Performance monitoring
import time
def time_function(func: Callable) -> Callable:
"""Decorator to measure function execution time."""
def profile_memory_usage(func: Callable) -> Callable:
"""Decorator to profile memory usage of function."""
# Interactive development
def interactive_embed() -> None:
"""Start interactive Python session with current scene state."""
def pause_for_interaction() -> None:
"""Pause animation for user interaction."""from manim import *
class RateFunctionExample(Scene):
def construct(self):
dot = Dot()
# Different easing styles
animations = [
dot.animate.shift(RIGHT * 2).set_rate_func(linear),
dot.animate.shift(UP * 2).set_rate_func(smooth),
dot.animate.shift(LEFT * 2).set_rate_func(there_and_back),
dot.animate.shift(DOWN * 2).set_rate_func(ease_out_bounce)
]
for anim in animations:
self.play(anim)
self.wait(0.5)class ColorExample(Scene):
def construct(self):
# Using predefined colors
circle1 = Circle(color=RED)
circle2 = Circle(color=BLUE_D)
circle3 = Circle(color=XKCD.AVOCADO)
# Color interpolation
interpolated_color = interpolate_color(RED, BLUE, 0.5)
circle4 = Circle(color=interpolated_color)
# Color gradients
gradient_colors = color_gradient([RED, GREEN, BLUE], 10)
circles = VGroup(*[
Circle(color=color, radius=0.3)
for color in gradient_colors
])
circles.arrange(RIGHT)
self.add(circles)class SpaceOpsExample(Scene):
def construct(self):
# Vector operations
v1 = np.array([1, 0, 0])
v2 = np.array([0, 1, 0])
# Cross product
cross_product = cross(v1, v2)
arrow = Arrow(ORIGIN, cross_product, color=RED)
# Angle between vectors
angle = angle_between_vectors(UP, RIGHT)
arc = Arc(angle=angle, color=YELLOW)
# Rotation
rotated_vector = rotate_vector(RIGHT, PI/4)
rotated_arrow = Arrow(ORIGIN, rotated_vector, color=GREEN)
self.add(arrow, arc, rotated_arrow)class MathUtilsExample(Scene):
def construct(self):
# Create smooth curve through points
points = np.array([
[-3, -1, 0],
[-1, 1, 0],
[1, -1, 0],
[3, 1, 0]
])
# Generate smooth Bézier curve
curve = VMobject()
curve.set_points_smoothly(points)
curve.set_stroke(YELLOW, 3)
# Mark the control points
dots = VGroup(*[Dot(p, color=RED) for p in points])
self.add(curve, dots)class DebugExample(Scene):
def construct(self):
# Enable debug logging
logger.setLevel("DEBUG")
# Time animation performance
start_time = time.time()
circle = Circle()
logger.info("Created circle")
self.play(Create(circle))
end_time = time.time()
logger.info(f"Animation took {end_time - start_time:.2f} seconds")
# Interactive debugging (uncomment for interactive use)
# self.interactive_embed()class FileOpsExample(Scene):
def construct(self):
# Ensure output directory exists
output_dir = guarantee_existence("custom_output")
# Find asset file
try:
asset_path = find_file("my_image.png", [
"assets/images",
"resources",
get_downloads_dir()
])
# Use found image
image = ImageMobject(asset_path)
self.add(image)
except FileNotFoundError:
# Fallback if image not found
text = Text("Image not found")
self.add(text)class ConstantsExample(Scene):
def construct(self):
# Use directional constants for positioning
center_dot = Dot(ORIGIN, color=WHITE)
direction_dots = VGroup(
Dot(UP, color=RED),
Dot(DOWN, color=GREEN),
Dot(LEFT, color=BLUE),
Dot(RIGHT, color=YELLOW),
Dot(UL, color=PURPLE),
Dot(UR, color=ORANGE),
Dot(DL, color=PINK),
Dot(DR, color=TEAL)
)
# Use buffer constants for spacing
text = Text("Directions").next_to(
center_dot,
UP,
buff=LARGE_BUFF
)
self.add(center_dot, direction_dots, text)Install with Tessl CLI
npx tessl i tessl/pypi-manim