Skip to main content

component-design

Reusable component patterns including VGroup subclasses, helper methods, encapsulated visualizations, and always_redraw patterns.

Ir a la instalación

Datos de origen

Repositorio
choxos/MathVizAgent
Última actividad en el origen
27 de enero de 2026 a las 02:43
Idioma detectado de SKILL.md
inglés
Estrellas
1
Forks
0

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
component-design
description
Reusable component patterns including VGroup subclasses, helper methods, encapsulated visualizations, and always_redraw patterns.
# Component Design Patterns for creating reusable, well-structured Manim components. ## VGroup Subclass Pattern ### Basic Structure ```python class MyComponent(VGroup): """Reusable visualization component""" def __init__(self, param1, param2, **kwargs): super().__init__(**kwargs) # Store parameters self.param1 = param1 self.param2 = param2 # Build component self._build() def _build(self): """Construct the component's mobjects""" # Create child mobjects self.part_a = Circle(radius=self.param1) self.part_b = Square(side_length=self.param2) # Position relative to each other self.part_b.next_to(self.part_a, RIGHT) # Add to self (VGroup) self.add(self.part_a, self.part_b) ``` ### Usage ```python # Create instance component = MyComponent(1.0, 0.5) # It's a VGroup, so all VGroup methods work component.scale(0.5) component.move_to(LEFT * 2) component.set_color(BLUE) # Animate self.play(Create(component)) self.play(component.animate.shift(RIGHT * 3)) ``` ## Real-World Example: Distribution Plot ```python from scipy.stats import norm class DistributionPlot(VGroup): """Self-contained probability distribution visualization""" def __init__( self, func, # Distribution function x_range=(-3, 3), # Domain color=BLUE, show_axes=True, **kwargs ): super().__init__(**kwargs) self.func = func self.x_min, self.x_max = x_range self.color = color self._build(show_axes) def _build(self, show_axes): # Calculate y range from function x_vals = np.linspace(self.x_min, self.x_max, 100) y_vals = [self.func(x) for x in x_vals] y_max = max(y_vals) * 1.1 # Create axes self.axes = Axes( x_range=[self.x_min, self.x_max, 1], y_range=[0, y_max, y_max/4], x_length=6, y_length=4, tips=False ) # Create plot self.curve = self.axes.plot(self.func, color=self.color) # Add to component if show_axes: self.add(self.axes) self.add(self.curve) # Helper methods def get_point(self, x): """Get point on curve at x value""" return self.axes.c2p(x, self.func(x)) def get_area(self, x_start, x_end, color=None): """Get shaded area under curve""" return self.axes.get_area( self.curve, x_range=[x_start, x_end], color=color or self.color ) def get_vertical_line(self, x, color=RED): """Get vertical line from x-axis to curve""" return DashedLine( start=self.axes.c2p(x, 0), end=self.get_point(x), color=color ) ``` ### Using the Component ```python class DemoScene(Scene): def construct(self): # Create distribution dist = DistributionPlot( func=lambda x: norm.pdf(x, 0, 1), x_range=(-3, 3), color=BLUE ) self.play(Create(dist)) # Use helper methods area = dist.get_area(-1, 1, color=YELLOW) self.play(FadeIn(area)) line = dist.get_vertical_line(0) self.play(Create(line)) ``` ## Component with Dynamic Updates ### ValueTracker Integration ```python class DynamicPlot(VGroup): """Plot with dynamic parameter""" def __init__(self, initial_value=1.0, **kwargs): super().__init__(**kwargs) # Create tracker self.value_tracker = ValueTracker(initial_value) # Build static parts self.axes = Axes(x_range=[-3, 3], y_range=[0, 1]) self.add(self.axes) # Build dynamic parts self.curve = always_redraw(self._build_curve) self.add(self.curve) def _build_curve(self): """Rebuild curve based on current tracker value""" sigma = self.value_tracker.get_value() return self.axes.plot( lambda x: norm.pdf(x, 0, sigma), color=BLUE ) def set_value(self, value, **kwargs): """Animate value change""" return self.value_tracker.animate.set_value(value, **kwargs) @property def value(self): return self.value_tracker.get_value() ``` ### Usage with Animation ```python class DynamicScene(Scene): def construct(self): plot = DynamicPlot(initial_value=1.0) self.add(plot) # Animate parameter change self.play(plot.set_value(0.5), run_time=2) self.play(plot.set_value(2.0), run_time=2) ``` ## Encapsulated Coordinate System ```python class PlotSystem(VGroup): """Coordinate system with encapsulated plotting""" def __init__(self, x_range, y_range, **kwargs): super().__init__(**kwargs) self.axes = Axes( x_range=x_range, y_range=y_range, tips=False ) self.add(self.axes) self.plots = VGroup() self.add(self.plots) def c2p(self, x, y): """Convert coordinates to point""" return self.axes.c2p(x, y) def p2c(self, point): """Convert point to coordinates""" return self.axes.p2c(point) def plot(self, func, x_range=None, **kwargs): """Add a plot to the system""" plot = self.axes.plot(func, x_range=x_range, **kwargs) self.plots.add(plot) return plot def add_point(self, x, y, **kwargs): """Add a point to the system""" point = Dot(self.c2p(x, y), **kwargs) self.add(point) return point def add_data(self, data, **kwargs): """Add scatter points from data""" points = VGroup(*[ Dot(self.c2p(x, y), **kwargs) for x, y in data ]) self.add(points) return points ``` ## Component Factory Pattern ```python class ComponentFactory: """Factory for creating styled components""" # Shared configuration COLORS = { "primary": BLUE, "secondary": ORANGE, "accent": PURPLE } @classmethod def create_labeled_circle(cls, label_text, radius=0.5, color="primary"): """Create a circle with centered label""" group = VGroup() circle = Circle(radius=radius, color=cls.COLORS[color]) label = Text(label_text, font_size=24) label.move_to(circle) group.add(circle, label) return group @classmethod def create_labeled_box(cls, title, content, width=3, color="primary"): """Create a box with title and content""" group = VGroup() box = Rectangle(width=width, height=2, color=cls.COLORS[color]) title_text = Text(title, font_size=20, weight=BOLD) content_text = Text(content, font_size=16) title_text.next_to(box, UP, buff=0.1, aligned_edge=LEFT) content_text.move_to(box) group.add(box, title_text, content_text) return group ``` ## Hierarchical Components ```python class NeuralNetworkLayer(VGroup): """Single layer of neurons""" def __init__(self, n_neurons, radius=0.3, **kwargs): super().__init__(**kwargs) self.neurons = VGroup(*[ Circle(radius=radius, color=WHITE) for _ in range(n_neurons) ]).arrange(DOWN, buff=0.5) self.add(self.neurons) def get_neuron(self, index): return self.neurons[index] class NeuralNetwork(VGroup): """Complete neural network visualization""" def __init__(self, layer_sizes, **kwargs): super().__init__(**kwargs) # Create layers self.layers = VGroup(*[ NeuralNetworkLayer(size) for size in layer_sizes ]).arrange(RIGHT, buff=2) # Create connections self.connections = VGroup() for i in range(len(self.layers) - 1): layer_connections = self._connect_layers( self.layers[i], self.layers[i + 1] ) self.connections.add(layer_connections) self.add(self.connections, self.layers) def _connect_layers(self, layer1, layer2): """Create arrows between all neurons in adjacent layers""" arrows = VGroup() for n1 in layer1.neurons: for n2 in layer2.neurons: arrow = Arrow( n1.get_right(), n2.get_left(), buff=0.05, stroke_width=1 ) arrows.add(arrow) return arrows ``` ## Best Practices ### 1. Single Responsibility Each component should do one thing well: ```python # Good: Focused component class AxisLabels(VGroup): """Just handles axis labels""" pass # Bad: Doing too much class PlotWithLabelsAndLegendAndTitle(VGroup): pass ``` ### 2. Configurable Defaults ```python class FlexibleComponent(VGroup): DEFAULT_COLOR = BLUE DEFAULT_SIZE = 1.0 def __init__(self, color=None, size=None, **kwargs): super().__init__(**kwargs) self.color = color or self.DEFAULT_COLOR self.size = size or self.DEFAULT_SIZE ``` ### 3. Helper Methods ```python class PlotComponent(VGroup): def get_point_at(self, x): """Get point on plot at x value""" pass def highlight_region(self, x1, x2): """Highlight a region of the plot""" pass def add_annotation(self, x, text): """Add text annotation at x""" pass ``` ### 4. Clean Naming ```python # Public attributes: no underscore self.axes self.curve # Private/internal: leading underscore self._temp_points self._cached_values # Methods: verbs for actions def get_area(self, ...): def create_label(self, ...): def update_curve(self, ...): ``` ### 5. Documentation ```python class WellDocumentedComponent(VGroup): """Brief description of component. Longer description explaining use case and behavior. Args: param1: Description of param1 param2: Description of param2 Attributes: axes: The underlying Axes object curve: The plotted curve Example: >>> comp = WellDocumentedComponent(1.0, "label") >>> self.play(Create(comp)) """ ```
Ver en GitHub