agentsclimarketplace

Component design

Skill choxos/MathVizAgent/plugins/mathviz/skills/component-design

Install
npx -y skills add choxos/MathVizAgent --skill component-design

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

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

SKILL.md

10.3 KB, as published. Nobody here has run it

Component Design

Patterns for creating reusable, well-structured Manim components.

VGroup Subclass Pattern

Basic Structure

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

# 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

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

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

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

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

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

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

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:

# Good: Focused component
class AxisLabels(VGroup):
    """Just handles axis labels"""
    pass

# Bad: Doing too much
class PlotWithLabelsAndLegendAndTitle(VGroup):
    pass

2. Configurable Defaults

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

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

# 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

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))
    """

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.