Использование Manim для создания математических анимированных визуализаций

Визуализация данных помогает понять скрытые закономерности в данных, которые невозможно визуализировать невооруженным глазом. Он определяет связь между различными точками данных, корреляцию между различными функциями и целевыми переменными. Существует несколько библиотек Python, которые можно использовать для создания визуализаций.

Анимированные визуализации делают его более привлекательным и понятным для пользователя, который его просматривает. Анимации помогают показать, как данные распределяются, связываются, коррелируются и т. д. Некоторые библиотеки Python, такие как Matplotlib, Plotly и т. д., предлагают анимацию в визуализациях.

В этой статье мы поговорим о Manim — библиотеке Python с открытым исходным кодом, предназначенной для создания пояснительных математических видео/анимаций. Это помогает понять различные математические концепции с помощью анимации.

Давайте начнем…

Установка необходимых библиотек

Мы начнем с установки Manim с помощью pip. Для Manim требуется несколько зависимостей. Приведенная ниже команда установит все зависимости, а также manim.

!sudo apt update
!sudo apt install libcairo2-dev ffmpeg \
    texlive texlive-latex-extra texlive-fonts-extra \
    texlive-latex-recommended texlive-science \
    tipa libpango1.0-dev
!pip install manim
!pip install IPython --upgrade

Импорт необходимых библиотек

На этом этапе мы импортируем необходимые библиотеки и функции для создания математических визуализаций с помощью Manim.

import numpy as np
from manim import *

Создание визуализации

На этом этапе мы начнем создавать различные визуализации. Давайте начнем с некоторых основных визуализаций.

  1. От круга до квадрата
%%manim -qm -v WARNING SquareToCircle
class SquareToCircle(Scene):
    def construct(self):
        # Creating shapes
        circle = Circle()
        square = Square()
#Showing shapes
        self.play(Create(square))
        self.play(Transform(square, circle))
        self.play(FadeOut(square))

2. Создать график

%%manim -qm -v WARNING CreateGraph
class CreateGraph(Scene):
    def construct(self):
        axes = Axes(
            x_range=[-3, 3],
            y_range=[-5, 5],
            axis_config={"color": BLUE},
        )
# Create Graph
        graph = axes.get_graph(lambda x: x**2, color=WHITE)
        graph_label = axes.get_graph_label(graph, label='x^{2}')
graph2 = axes.get_graph(lambda x: x**3, color=WHITE)
        graph_label2 = axes.get_graph_label(graph2, label='x^{3}')
# Display graph
        self.play(Create(axes), Create(graph), Write(graph_label))
        self.wait(1)
        self.play(Transform(graph, graph2), Transform(graph_label, graph_label2))
        self.wait(1)

3. Объяснение логической операции

%%manim -qm -v WARNING BooleanOperations
class BooleanOperations(Scene):
    def construct(self):
        ellipse1 = Ellipse(
            width=4.0, height=5.0, fill_opacity=0.5, color=BLUE, stroke_width=10
        ).move_to(LEFT)
        ellipse2 = ellipse1.copy().set_color(color=RED).move_to(RIGHT)
        bool_ops_text = MarkupText("<u>Boolean Operation</u>").next_to(ellipse1, UP * 3)
        ellipse_group = Group(bool_ops_text, ellipse1, ellipse2).move_to(LEFT * 3)
        self.play(FadeIn(ellipse_group))
i = Intersection(ellipse1, ellipse2, color=GREEN, fill_opacity=0.5)
        self.play(i.animate.scale(0.25).move_to(RIGHT * 5 + UP * 2.5))
        intersection_text = Text("Intersection", font_size=23).next_to(i, UP)
        self.play(FadeIn(intersection_text))
u = Union(ellipse1, ellipse2, color=ORANGE, fill_opacity=0.5)
        union_text = Text("Union", font_size=23)
        self.play(u.animate.scale(0.3).next_to(i, DOWN, buff=union_text.height * 3))
        union_text.next_to(u, UP)
        self.play(FadeIn(union_text))
e = Exclusion(ellipse1, ellipse2, color=YELLOW, fill_opacity=0.5)
        exclusion_text = Text("Exclusion", font_size=23)
        self.play(e.animate.scale(0.3).next_to(u, DOWN, buff=exclusion_text.height * 3.5))
        exclusion_text.next_to(e, UP)
        self.play(FadeIn(exclusion_text))
d = Difference(ellipse1, ellipse2, color=PINK, fill_opacity=0.5)
        difference_text = Text("Difference", font_size=23)
        self.play(d.animate.scale(0.3).next_to(u, LEFT, buff=difference_text.height * 3.5))
        difference_text.next_to(d, UP)
        self.play(FadeIn(difference_text))

Все эти визуализации содержат много кода, и я объяснил каждую строку кода в виде комментариев в коде, вы можете просмотреть их и понять, как создать график и визуализировать его.

Давайте создадим несколько более сложных визуализаций.

4. Точки с трассировкой

%%manim -qm -v WARNING PointWithTrace
class PointWithTrace(Scene):
    def construct(self):
        path = VMobject()
        dot = Dot()
        path.set_points_as_corners([dot.get_center(), dot.get_center()])
        def update_path(path):
            previous_path = path.copy()
            previous_path.add_points_as_corners([dot.get_center()])
            path.become(previous_path)
        path.add_updater(update_path)
        self.add(path, dot)
        self.play(Rotating(dot, radians=PI, about_point=RIGHT, run_time=2))
        self.wait()
        self.play(dot.animate.shift(UP))
        self.play(dot.animate.shift(LEFT))
        self.wait()

5. График камеры

%%manim -qm -v WARNING FollowingGraphCamera
class FollowingGraphCamera(MovingCameraScene):
    def construct(self):
        self.camera.frame.save_state()
# create the axes and the curve
        ax = Axes(x_range=[-1, 10], y_range=[-1, 10])
        graph = ax.plot(lambda x: np.sin(x), color=BLUE, x_range=[0, 3 * PI])
# create dots based on the graph
        moving_dot = Dot(ax.i2gp(graph.t_min, graph), color=ORANGE)
        dot_1 = Dot(ax.i2gp(graph.t_min, graph))
        dot_2 = Dot(ax.i2gp(graph.t_max, graph))
self.add(ax, graph, dot_1, dot_2, moving_dot)
        self.play(self.camera.frame.animate.scale(0.5).move_to(moving_dot))
def update_curve(mob):
            mob.move_to(moving_dot.get_center())
self.camera.frame.add_updater(update_curve)
        self.play(MoveAlongPath(moving_dot, graph, rate_func=linear))
        self.camera.frame.remove_updater(update_curve)
self.play(Restore(self.camera.frame))

Попробуйте разные визуализации. Если вы обнаружите какие-либо трудности, пожалуйста, дайте мне знать в разделе ответов.

Эта статья подготовлена ​​в сотрудничестве с Пиюшем Ингале.

Перед тем, как ты уйдешь

Спасибо за прочтение! Если вы хотите связаться со мной, не стесняйтесь обращаться ко мне по адресу [email protected] или в мой профиль LinkedIn. Вы можете просмотреть мой профиль Github для различных проектов по науке о данных и руководств по пакетам. Кроме того, не стесняйтесь просматривать мой профиль и читать различные статьи, которые я написал, связанные с наукой о данных.