{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Manim in Jupyter" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Working with manim in jupyter notebooks has several advantages:\n", "\n", "* code snippets and rendered outputs are close together\n", "* easy to iterate examples\n", "* easy to try different varieties of one scene in multiple cells\n", "* computation intensive code can be executed separately from the scenes\n", "* global Mobjects can be used in multiple scenes." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Simple Example" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, we need to import manim" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from manim import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we build up our scene" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%manim -v WARNING --progress_bar None -s -ql --disable_caching MyExample\n", "class MyExample(Scene):\n", " def construct(self):\n", " m= ManimBanner()\n", " self.add(m)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note, that I use the following parameters: \n", "\n", "* `-v WARNING` means that only warnings are shown in the log \n", "* `--progress_bar None` will not show the animation progress bar \n", "* `-s ` will only show the last frame \n", "* `-ql` renders in low quality \n", "* `--disable_caching` will disable the manim caching system \n", "* `MyExample` gives the scene name \n", "\n", "for rendering a video, just remove the -s flag. To lower the resolution, you can use -r 400,200 (pixel values in x and y direction)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%manim -v WARNING --progress_bar None -r 400,200 --disable_caching HelloManim\n", "class HelloManim(Scene):\n", " def construct(self):\n", " self.camera.background_color = \"#ece6e2\"\n", " banner_large = ManimBanner(dark_theme=False).scale(0.7)\n", " self.play(banner_large.create())\n", " self.play(banner_large.expand())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can define the parameters as a string `param` and call this string by the cell magic with `$param`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "param = \"-v WARNING -s -ql --disable_caching Example\"\n", "paramSMALL = \"-v WARNING -r 400,200 -s --disable_caching Example\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%manim $param\n", "class Example(Scene):\n", " def construct(self):\n", " m= ManimBanner()\n", " self.add(m)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Initializing Mobjects Outside the Class\n", "In some cases, it might be convenient to define mobjects outside the `Scene` class (e.g. for uncluttering or for speeding up the animation)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m = ManimBanner()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%manim $paramSMALL\n", "class Example(Scene):\n", " def construct(self):\n", " m.scale(0.4 )\n", " m.shift(1.5*UP)\n", " self.add(m)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Because the mobject is manipulated in the class, the next cell might show some unexpected scaling and shifting:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%manim $paramSMALL\n", "class Example(Scene):\n", " def construct(self):\n", " m.scale(0.4)\n", " m.shift(1.5*UP)\n", " self.add(m)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To aviod this, it is better to add only a copy of these mobjects to scenes, and keep the originals untouched:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m_reference = ManimBanner()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%manim $paramSMALL\n", "class Example(Scene):\n", " def construct(self):\n", " m = m_reference.copy()\n", " m.scale(0.4)\n", " m.shift(2*UP)\n", " self.add(m)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%manim $paramSMALL\n", "class Example(Scene):\n", " def construct(self):\n", " m = m_reference.copy()\n", " m.scale(0.4)\n", " m.shift(2*UP)\n", " self.add(m)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Defining Global Mobjects\n", "When you have to build complex scenes, you might want to use parts of that scene for your next scene. That is possible with global variables, which can be accessed in any other scene." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%manim $paramSMALL\n", "class Example(Scene):\n", " def construct(self):\n", " stars= VGroup()\n", " for i in range(0,20):\n", " s= Star(color= random_bright_color(), fill_opacity=1).scale(0.8)\n", " stars.add(s)\n", " stars.arrange_in_grid() \n", " self.add(stars)\n", " global favoritstar\n", " favoritstar = stars[9]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%manim $paramSMALL\n", "class Example(Scene):\n", " def construct(self):\n", " self.add(favoritstar)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Pre-Execute Slow Code\n", "In this example, calculating a random walk for 500 particles and 100000 steps takes about 4 seconds. \n", "This step can be done before the actual scene construction, which takes about 0.2 seconds. \n", "Making aesthetic changes to the scene will then become easier. \n", "Note: The `%%time` command will print the execution time of the cells." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%time\n", "np.random.seed(20)\n", "steps = np.random.choice(a=[-1, 0, 1], size=(100000,1000))\n", "stop = steps.cumsum(0)\n", "end_points= stop[-1]/stop[-1].max() \n", "end_pointsX = end_points[0:499]\n", "end_pointsY = end_points[500:-1]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%time\n", "%%manim $param\n", "class Example(Scene):\n", " def construct(self):\n", " radius= (end_pointsX*end_pointsX + end_pointsY * end_pointsY)**0.5\n", " dots = VGroup()\n", " for x,y,r in zip(end_pointsX, end_pointsY,radius):\n", " c= interpolate_color(YELLOW, RED, r)\n", " dots.add(Dot(color=c,point=[3*x,3*y,0]).scale(0.7))\n", " self.add(dots)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Installing Plugins\n", "plugins can be found at https://plugins.manim.community/" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!pip install manim-physics" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%manim -v WARNING --progress_bar None -qm --disable_caching Example\n", "\n", "from manim_physics import *\n", "\n", "class Example(SpaceScene):\n", " def construct(self):\n", " circle = Dot(radius=1).shift(1.5*LEFT+3*UP)\n", " rect = Square(color=YELLOW, fill_opacity=1)\n", " ground = Line([-4, -3.5, 0], [4, -3.5, 0])\n", " wall1 = Line([-4, -3.5, 0], [-4, 3.5, 0])\n", " wall2 = Line([4, -3.5, 0], [4, 3.5, 0])\n", " walls = VGroup(ground, wall1, wall2)\n", " self.add(walls)\n", " self.add(rect, circle)\n", " self.make_rigid_body(rect, circle)\n", " self.make_static_body(walls)\n", " self.wait(5)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.5" } }, "nbformat": 4, "nbformat_minor": 4 }