How to apply two tranformations one after the other in manimce?

563 views Asked by At

I wanted to apply two linear transformations with matrices one after the other in manimce. Here is the code for one transformation:

 from manim import *

class LT(LinearTransformationScene):
def __init__(self):
    LinearTransformationScene.__init__(
        self,
        show_coordinates=True,
        leave_ghost_vectors=True,
    )

def construct(self):
    matrix = [[1, 1], [0, 1]]
    self.apply_matrix(matrix)
    self.wait()

This works perfectly for a single transformation. But I want to apply another transformation after this. I tried using self.apply_matrix again:

from manim import *

class LT(LinearTransformationScene):
    def __init__(self):
        LinearTransformationScene.__init__(
            self,
            show_coordinates=True,
            leave_ghost_vectors=True,
        )

    def construct(self):
        matrix1 = [[1, 1], [0, 1]]
        self.apply_matrix(matrix1)
        self.wait()


    def construct(self):
        matrix2 = [[2, 1], [3, 1]]
        self.apply_matrix(matrix2)
        self.wait()

with this code, only the last matrix was rendered. What might have happened?

This must be very simple. But I have no idea- didnt found anything in the documentation or search results.Any help is greatly appreciated.


Update:

As suggested by Nils Werner, I changed LinearTransformationScene.__init__(...) to super().__init__(...) and included the two matrices in the same def construct(self):.

from manim import *

class LT(LinearTransformationScene):
    def __init__(self):
        super().__init__(
            self,
            show_coordinates=True,
            leave_ghost_vectors=True,
        )

def construct(self):
    matrix1 = [[1, 1], [0, 1]]
    self.apply_matrix(matrix1)

    matrix2 = [[2, 1], [3, 1]]
    self.apply_matrix(matrix2)

    self.wait()

But this didn't work either. Shows error:

ValueError: operands could not be broadcast together with shapes (4,3) (12,3)

Full log:

 PS C:\Python38> manim LTmul.py -pql
    Manim Community v0.11.0
    
    [10/26/21 21:24:39] INFO     Animation 0 : Using cached data (hash :                         cairo_renderer.py:110
                                 3163782288_2165879958_531335182)
    ┌─────────────────────────────── Traceback (most recent call last) ────────────────────────────────┐
    │                                                                                                  │
    │ C:\tools\Manim\Lib\site-packages\manim\cli\render\commands.py:139 in render                      │
    │                                                                                                  │
    │   136 │   │   for SceneClass in scene_classes_from_file(file):                                   │
    │   137 │   │   │   try:                                                                           │
    │   138 │   │   │   │   scene = SceneClass()                                                       │
    │ > 139 │   │   │   │   scene.render()                                                             │
    │   140 │   │   │   except Exception:                                                              │
    │   141 │   │   │   │   error_console.print_exception()                                            │
    │   142 │   │   │   │   sys.exit(1)                                                                │
    │ C:\tools\Manim\Lib\site-packages\manim\scene\scene.py:213 in render                              │
    │                                                                                                  │
    │    210 │   │   """                                                                               │
    │    211 │   │   self.setup()                                                                      │
    │    212 │   │   try:                                                                              │
    │ >  213 │   │   │   self.construct()                                                              │
    │    214 │   │   except EndSceneEarlyException:                                                    │
    │    215 │   │   │   pass                                                                          │
    │    216 │   │   except RerunSceneException as e:                                                  │
    │                                                                                                  │
    │ C:\Python38\LTmul.py:16 in construct                                                             │
    │                                                                                                  │
    │   13 │   │   self.apply_matrix(matrix1)                                                          │
    │   14 │   │                                                                                       │
    │   15 │   │   matrix2 = [[2, 2], [3, 3]]                                                          │
    │ > 16 │   │   self.apply_matrix(matrix2)                                                          │
    │   17 │   │                                                                                       │
    │   18 │   │   self.wait()                                                                         │
    │   19                                                                                             │
    │                                                                                                  │
    │ C:\tools\Manim\Lib\site-packages\manim\scene\vector_space_scene.py:1041 in apply_matrix          │
    │                                                                                                  │
    │   1038 │   │   **kwargs                                                                          │
    │   1039 │   │   │   Any valid keyword argument of self.apply_transposed_matrix()                  │
    │   1040 │   │   """                                                                               │
    │ > 1041 │   │   self.apply_transposed_matrix(np.array(matrix).T, **kwargs)                        │
    │   1042 │                                                                                         │
    │   1043 │   def apply_inverse(self, matrix, **kwargs):                                            │
    │   1044 │   │   """                                                                               │
    │                                                                                                  │
    │ C:\tools\Manim\Lib\site-packages\manim\scene\vector_space_scene.py:1077 in                       │
    │ apply_transposed_matrix                                                                          │
    │                                                                                                  │
    │   1074 │   │   │   │   [angle_of_vector(func(RIGHT)), angle_of_vector(func(UP)) - np.pi / 2],    │
    │   1075 │   │   │   )                                                                             │
    │   1076 │   │   │   kwargs["path_arc"] = net_rotation                                             │
    │ > 1077 │   │   self.apply_function(func, **kwargs)                                               │
    │   1078 │                                                                                         │
    │   1079 │   def apply_inverse_transpose(self, t_matrix, **kwargs):                                │
    │   1080 │   │   """                                                                               │
    │                                                                                                  │
    │ C:\tools\Manim\Lib\site-packages\manim\scene\vector_space_scene.py:1145 in apply_function        │
    │                                                                                                  │
    │   1142 │   │   │   + [Animation(f_mob) for f_mob in self.foreground_mobjects]                    │
    │   1143 │   │   │   + added_anims                                                                 │
    │   1144 │   │   )                                                                                 │
    │ > 1145 │   │   self.play(*anims, **kwargs)                                                       │
    │   1146                                                                                           │
    │                                                                                                  │
    │ C:\tools\Manim\Lib\site-packages\manim\scene\scene.py:888 in play                                │
    │                                                                                                  │
    │    885 │   │   │   return np.max([animation.run_time for animation in animations])               │
    │    886 │                                                                                         │
    │    887 │   def play(self, *args, **kwargs):                                                      │
    │ >  888 │   │   self.renderer.play(self, *args, **kwargs)                                         │
    │    889 │                                                                                         │
    │    890 │   def wait(self, duration=DEFAULT_WAIT_TIME, stop_condition=None):                      │
    │    891 │   │   self.play(Wait(run_time=duration, stop_condition=stop_condition))                 │
    │                                                                                                  │
    │ C:\tools\Manim\Lib\site-packages\manim\renderer\cairo_renderer.py:127 in play                    │
    │                                                                                                  │
    │   124 │   │   self.static_image = self.save_static_frame_data(scene, scene.static_mobjects)      │
    │   125 │   │                                                                                      │
    │   126 │   │   self.file_writer.begin_animation(not self.skip_animations)                         │
    │ > 127 │   │   scene.begin_animations()                                                           │
    │   128 │   │   if scene.is_current_animation_frozen_frame():                                      │
    │   129 │   │   │   self.update_frame(scene)                                                       │
    │   130 │   │   │   # self.duration stands for the total run time of all the animations.           │
    │                                                                                                  │
    │ C:\tools\Manim\Lib\site-packages\manim\scene\scene.py:961 in begin_animations                    │
    │                                                                                                  │
    │    958 │   def begin_animations(self) -> None:                                                   │
    │    959 │   │   """Start the animations of the scene."""                                          │
    │    960 │   │   for animation in self.animations:                                                 │
    │ >  961 │   │   │   animation.begin()                                                             │
    │    962 │                                                                                         │
    │    963 │   def is_current_animation_frozen_frame(self) -> bool:                                  │
    │    964 │   │   """Returns whether the current animation produces a static frame (generally a Wa  │
    │                                                                                                  │
    │ C:\tools\Manim\Lib\site-packages\manim\animation\transform.py:114 in begin                       │
    │                                                                                                  │
    │   111 │   │   │   self.mobject.align_data_and_family(self.target_copy)                           │
    │   112 │   │   else:                                                                              │
    │   113 │   │   │   self.mobject.align_data(self.target_copy)                                      │
    │ > 114 │   │   super().begin()                                                                    │
    │   115 │                                                                                          │
    │   116 │   def create_target(self) -> Mobject:                                                    │
    │   117 │   │   # Has no meaningful effect here, but may be useful                                 │
    │                                                                                                  │
    │ C:\tools\Manim\Lib\site-packages\manim\animation\animation.py:184 in begin                       │
    │                                                                                                  │
    │   181 │   │   │   # the internal updaters of self.starting_mobject,                              │
    │   182 │   │   │   # or any others among self.get_all_mobjects()                                  │
    │   183 │   │   │   self.mobject.suspend_updating()                                                │
    │ > 184 │   │   self.interpolate(0)                                                                │
    │   185 │                                                                                          │
    │   186 │   def finish(self) -> None:                                                              │
    │   187 │   │   # TODO: begin and finish should require a scene as parameter.                      │
    │                                                                                                  │
    │ C:\tools\Manim\Lib\site-packages\manim\animation\animation.py:284 in interpolate                 │
    │                                                                                                  │
    │   281 │   │   │   The relative time to set the aniamtion to, 0 meaning the start, 1 meaning      │
    │   282 │   │   │   the end.                                                                       │
    │   283 │   │   """                                                                                │
    │ > 284 │   │   self.interpolate_mobject(alpha)                                                    │
    │   285 │                                                                                          │
    │   286 │   def interpolate_mobject(self, alpha: float) -> None:                                   │
    │   287 │   │   """Interpolates the mobject of the :class:`Animation` based on alpha value.        │
    │                                                                                                  │
    │ C:\tools\Manim\Lib\site-packages\manim\animation\animation.py:299 in interpolate_mobject         │
    │                                                                                                  │
    │   296 │   │   families = list(self.get_all_families_zipped())                                    │
    │   297 │   │   for i, mobs in enumerate(families):                                                │
    │   298 │   │   │   sub_alpha = self.get_sub_alpha(alpha, i, len(families))                        │
    │ > 299 │   │   │   self.interpolate_submobject(*mobs, sub_alpha)                                  │
    │   300 │                                                                                          │
    │   301 │   def interpolate_submobject(                                                            │
    │   302 │   │   self,                                                                              │
    │                                                                                                  │
    │ C:\tools\Manim\Lib\site-packages\manim\animation\transform.py:152 in interpolate_submobject      │
    │                                                                                                  │
    │   149 │   │   target_copy: Mobject,                                                              │
    │   150 │   │   alpha: float,                                                                      │
    │   151 │   ) -> "Transform":                                                                      │
    │ > 152 │   │   submobject.interpolate(starting_submobject, target_copy, alpha, self.path_func)    │
    │   153 │   │   return self                                                                        │
    │   154                                                                                            │
    │   155                                                                                            │
    │                                                                                                  │
    │ C:\tools\Manim\Lib\site-packages\manim\mobject\mobject.py:2597 in interpolate                    │
    │                                                                                                  │
    │   2594 │   │   │   │   │                                                                         │
    │   2595 │   │   │   │   │   self.add(dotL, dotR, dotMiddle)                                       │
    │   2596 │   │   """                                                                               │
    │ > 2597 │   │   self.points = path_func(mobject1.points, mobject2.points, alpha)                  │
    │   2598 │   │   self.interpolate_color(mobject1, mobject2, alpha)                                 │
    │   2599 │   │   return self                                                                       │
    │   2600                                                                                           │
    │                                                                                                  │
    │ C:\tools\Manim\Lib\site-packages\manim\utils\paths.py:43 in path                                 │
    │                                                                                                  │
    │   40 │                                                                                           │
    │   41 │   def path(start_points, end_points, alpha):                                              │
    │   42 │   │   if arc_centers is None:                                                             │
    │ > 43 │   │   │   vects = end_points - start_points                                               │
    │   44 │   │   │   centers = start_points + 0.5 * vects                                            │
    │   45 │   │   │   if arc_angle != np.pi:                                                          │
    │   46 │   │   │   │   centers += np.cross(unit_axis, vects / 2.0) / np.tan(arc_angle / 2)         │
    └──────────────────────────────────────────────────────────────────────────────────────────────────┘
    ValueError: operands could not be broadcast together with shapes (4,3) (12,3)

2

There are 2 answers

9
Nils Werner On BEST ANSWER

Apply the two matrices in the same construct() call.

from manim import *

class LT(LinearTransformationScene):
    def __init__(self):
        super().__init__(
            self,
            show_coordinates=True,
            leave_ghost_vectors=True,
        )

    def construct(self):
        matrix1 = [[1, 1], [0, 1]]
        self.apply_matrix(matrix1)

        self.wait()

        matrix2 = [[2, 1], [3, 1]]
        self.apply_matrix(matrix2)

        self.wait()
2
Sophile On

I just needed to add a self.wait() between the matrices!!

Thanks Nils Werner for suggesting this and to add the matrices in the same construct() call.

from manim import *

class LinearTransformationSceneExample(LinearTransformationScene):
    def __init__(self):
        LinearTransformationScene.__init__(
            self,
            show_coordinates=True,
            leave_ghost_vectors=True,
    )

def construct(self):
    matrix = [[1, 1], [0, 1]]
    self.apply_matrix(matrix)
    self.wait()

    matrix2 = [[2, 1], [3, 1]]
    self.apply_matrix(matrix2)

    self.wait()