Exemple #1
0
    def series_of_videos(self, chapters):
        icon = SVGMobject("video_icon")
        icon.center()
        icon.scale_to_fit_width(2 * SPACE_WIDTH / 12.)
        icon.set_stroke(color=WHITE, width=0)
        icons = [icon.copy() for chapter in chapters.split()]
        colors = Color(BLUE_A).range_to(BLUE_D, len(icons))
        for icon, color in zip(icons, colors):
            icon.set_fill(color, opacity=1)
        icons = VMobject(*icons)
        icons.arrange_submobjects(RIGHT)
        icons.to_edge(LEFT)
        icons.shift(UP)

        randy = Randolph()
        randy.to_corner()
        bubble = randy.get_bubble()
        new_icons = icons.copy().scale(0.2)
        bubble.position_mobject_inside(new_icons)

        self.play(Transform(
            chapters,
            icons,
            path_arc=np.pi / 2,
        ))
        self.clear()
        self.add(icons)
        self.play(FadeIn(randy))
        self.play(Blink(randy))
        self.wait()
        self.play(ShowCreation(bubble), Transform(icons, new_icons))
        self.remove(icons)
        bubble.make_green_screen()
        self.wait()
Exemple #2
0
    def handle_mathy(self, creatures):
        self.fade_all_but(creatures, 2)
        physy, compy, mathy = creatures

        v_color = YELLOW 
        w_color = BLUE
        sum_color = GREEN

        v_arrow = Vector([1, 1])
        w_arrow = Vector([2, 1])
        w_arrow.shift(v_arrow.get_end())
        sum_arrow = Vector(w_arrow.get_end())
        arrows = VMobject(v_arrow, w_arrow, sum_arrow)
        arrows.scale(0.7)
        arrows.to_edge(LEFT, buff = 2)

        v_array = matrix_to_mobject([3, -5])
        w_array = matrix_to_mobject([2, 1])
        sum_array = matrix_to_mobject(["3+2", "-5+1"])
        arrays = VMobject(
            v_array, TexMobject("+"), w_array, TexMobject("="), sum_array
        )
        arrays.arrange_submobjects(RIGHT)
        arrays.scale(0.75)
        arrays.to_edge(RIGHT).shift(UP)

        v_sym = TexMobject("\\vec{\\textbf{v}}")
        w_sym = TexMobject("\\vec{\\textbf{w}}")
        syms = VMobject(v_sym, TexMobject("+"), w_sym)
        syms.arrange_submobjects(RIGHT)
        syms.center().shift(2*UP)

        statement = TextMobject("We'll ignore him \\\\ for now")
        statement.highlight(PINK)
        statement.scale_to_fit_width(arrays.get_width())
        statement.next_to(arrays, DOWN, buff = 1.5)
        circle = Circle()
        circle.shift(syms.get_bottom())

        VMobject(v_arrow, v_array, v_sym).highlight(v_color)
        VMobject(w_arrow, w_array, w_sym).highlight(w_color)
        VMobject(sum_arrow, sum_array).highlight(sum_color)

        self.play(
            Write(syms), Write(arrays),
            ShowCreation(arrows, submobject_mode = "one_at_a_time"),
            ApplyMethod(mathy.change_mode, "pondering"),
            run_time = 2
        )
        self.play(Blink(mathy))
        self.add_scaling(arrows, syms, arrays)
        self.play(Write(statement))
        self.play(ApplyMethod(mathy.change_mode, "sad"))
        self.dither()
        self.play(
            ShowCreation(circle),
            ApplyMethod(mathy.change_mode, "plain")
        )
        self.dither()
Exemple #3
0
    def handle_mathy(self, creatures):
        self.fade_all_but(creatures, 2)
        physy, compy, mathy = creatures

        v_color = YELLOW 
        w_color = BLUE
        sum_color = GREEN

        v_arrow = Vector([1, 1])
        w_arrow = Vector([2, 1])
        w_arrow.shift(v_arrow.get_end())
        sum_arrow = Vector(w_arrow.get_end())
        arrows = VMobject(v_arrow, w_arrow, sum_arrow)
        arrows.scale(0.7)
        arrows.to_edge(LEFT, buff = 2)

        v_array = matrix_to_mobject([3, -5])
        w_array = matrix_to_mobject([2, 1])
        sum_array = matrix_to_mobject(["3+2", "-5+1"])
        arrays = VMobject(
            v_array, TexMobject("+"), w_array, TexMobject("="), sum_array
        )
        arrays.arrange_submobjects(RIGHT)
        arrays.scale(0.75)
        arrays.to_edge(RIGHT).shift(UP)

        v_sym = TexMobject("\\vec{\\textbf{v}}")
        w_sym = TexMobject("\\vec{\\textbf{w}}")
        syms = VMobject(v_sym, TexMobject("+"), w_sym)
        syms.arrange_submobjects(RIGHT)
        syms.center().shift(2*UP)

        statement = TextMobject("We'll ignore him \\\\ for now")
        statement.highlight(PINK)
        statement.scale_to_fit_width(arrays.get_width())
        statement.next_to(arrays, DOWN, buff = 1.5)
        circle = Circle()
        circle.shift(syms.get_bottom())

        VMobject(v_arrow, v_array, v_sym).highlight(v_color)
        VMobject(w_arrow, w_array, w_sym).highlight(w_color)
        VMobject(sum_arrow, sum_array).highlight(sum_color)

        self.play(
            Write(syms), Write(arrays),
            ShowCreation(arrows, submobject_mode = "one_at_a_time"),
            ApplyMethod(mathy.change_mode, "pondering"),
            run_time = 2
        )
        self.play(Blink(mathy))
        self.add_scaling(arrows, syms, arrays)
        self.play(Write(statement))
        self.play(ApplyMethod(mathy.change_mode, "sad"))
        self.wait()
        self.play(
            ShowCreation(circle),
            ApplyMethod(mathy.change_mode, "plain")
        )
        self.wait()
Exemple #4
0
    def construct(self):
        v = TexMobject(self.v_str)
        v.highlight(YELLOW)
        eq = TexMobject("=")
        coords = Matrix(["x", "y", "z"])
        eq2 = eq.copy()
        if self.post_transform:
            L, l_paren, r_paren = map(TexMobject, "L()")
            parens = VMobject(l_paren, r_paren)
            parens.scale(2)
            parens.stretch_to_fit_height(
                coords.get_height()
            )
            VMobject(L, l_paren, coords, r_paren).arrange_submobjects(buff = 0.1)
            coords.submobjects = [L, l_paren] + coords.submobjects + [r_paren]

        lin_comb = VMobject(*map(TexMobject, [
            "x", self.i_str, "+",
            "y", self.j_str, "+",
            "z", self.k_str,
        ]))
        lin_comb.arrange_submobjects(
            RIGHT, buff = 0.1, 
            aligned_edge = ORIGIN if self.post_transform else DOWN
        )
        lin_comb_parts = np.array(lin_comb.split())
        new_x, new_y, new_z = lin_comb_parts[[0, 3, 6]]
        i, j, k = lin_comb_parts[[1, 4, 7]]
        plusses = lin_comb_parts[[2, 5]]
        i.highlight(X_COLOR)
        j.highlight(Y_COLOR)
        k.highlight(Z_COLOR)

        everything = VMobject(v, eq, coords, eq2, lin_comb)
        everything.arrange_submobjects(buff = 0.2)
        everything.scale_to_fit_width(2*SPACE_WIDTH - 1)
        everything.to_edge(DOWN)
        if not self.post_transform:
            lin_comb.shift(0.35*UP)

        self.play(*map(Write, [v, eq, coords]))
        self.dither()
        self.play(
            Transform(
                coords.get_entries().copy(),
                VMobject(new_x, new_y, new_z),
                path_arc = -np.pi,
                submobject_mode = "lagged_start"
            ),
            Write(VMobject(*[eq2, i, j, k] + list(plusses))),
            run_time = 3
        )
        self.dither()
Exemple #5
0
    def construct(self):
        icon = SVGMobject("video_icon")
        icon.center()
        icon.scale_to_fit_width(2 * SPACE_WIDTH / 12.)
        icon.set_stroke(color=WHITE, width=0)
        icon.set_fill(WHITE, opacity=1)
        icons = VMobject(*[icon.copy() for x in range(10)])
        icons.submobject_gradient_highlight(BLUE_A, BLUE_D)
        icons.arrange_submobjects(RIGHT)
        icons.to_edge(LEFT)

        self.play(FadeIn(icons, submobject_mode="lagged_start"), run_time=3)
        self.wait()
Exemple #6
0
 def construct(self):
     title = TextMobject("Questions to ponder")
     title.highlight(YELLOW).to_edge(UP)
     self.add(title)
     questions = VMobject(*map(TextMobject, [
         "1. Can you visualize these transformations?",
         "2. Can you represent them with matrices?",
         "3. How many rows and columns?",
         "4. When can you multiply these matrices?",
     ]))
     questions.arrange_submobjects(DOWN, buff=1, aligned_edge=LEFT)
     questions.to_edge(LEFT)
     for question in questions.split():
         self.play(Write(question, run_time=1))
         self.wait()
Exemple #7
0
 def construct(self):
     title = TextMobject("Questions to ponder")
     title.highlight(YELLOW).to_edge(UP)
     self.add(title)
     questions = VMobject(*map(TextMobject, [
         "1. Can you visualize these transformations?",
         "2. Can you represent them with matrices?",
         "3. How many rows and columns?",
         "4. When can you multiply these matrices?",
     ]))
     questions.arrange_submobjects(DOWN, buff = 1, aligned_edge = LEFT)
     questions.to_edge(LEFT)
     for question in questions.split():
         self.play(Write(question, run_time = 1))
         self.dither()
Exemple #8
0
    def construct(self):
        icon = SVGMobject("video_icon")
        icon.center()
        icon.scale_to_fit_width(2*SPACE_WIDTH/12.)
        icon.set_stroke(color = WHITE, width = 0)
        icon.set_fill(WHITE, opacity = 1)
        icons = VMobject(*[icon.copy() for x in range(10)])
        icons.submobject_gradient_highlight(BLUE_A, BLUE_D)
        icons.arrange_submobjects(RIGHT)
        icons.to_edge(LEFT)

        self.play(
            FadeIn(icons, submobject_mode = "lagged_start"),
            run_time = 3
        )
        self.dither()
Exemple #9
0
    def construct(self):
        i_to = TexMobject("\\hat{\\imath} \\to").highlight(X_COLOR)
        j_to = TexMobject("\\hat{\\jmath} \\to").highlight(Y_COLOR)
        k_to = TexMobject("\\hat{k} \\to").highlight(Z_COLOR)
        i_array = Matrix(self.col1)
        j_array = Matrix(self.col2)
        k_array = Matrix(self.col3)
        everything = VMobject(
            i_to,
            i_array,
            TexMobject("=").highlight(BLACK),
            j_to,
            j_array,
            TexMobject("=").highlight(BLACK),
            k_to,
            k_array,
            TexMobject("=").highlight(BLACK),
        )
        everything.arrange_submobjects(RIGHT, buff=0.1)
        everything.scale_to_fit_width(2 * SPACE_WIDTH - 1)
        everything.to_edge(DOWN)

        i_array.highlight(X_COLOR)
        j_array.highlight(Y_COLOR)
        k_array.highlight(Z_COLOR)
        arrays = [i_array, j_array, k_array]
        matrix = Matrix(
            reduce(lambda a1, a2: np.append(a1, a2, axis=1),
                   [m.copy().get_mob_matrix() for m in arrays]))
        matrix.to_edge(DOWN)

        start_entries = reduce(op.add,
                               map(lambda a: a.get_entries().split(), arrays))
        target_entries = matrix.get_mob_matrix().transpose().flatten()
        start_l_bracket = i_array.get_brackets().split()[0]
        start_r_bracket = k_array.get_brackets().split()[1]
        start_brackets = VMobject(start_l_bracket, start_r_bracket)
        target_bracketes = matrix.get_brackets()

        for mob in everything.split():
            self.play(Write(mob, run_time=1))
        self.wait()
        self.play(
            FadeOut(everything),
            Transform(VMobject(*start_entries), VMobject(*target_entries)),
            Transform(start_brackets, target_bracketes))
        self.wait()
Exemple #10
0
    def construct(self):
        i_to = TexMobject("\\hat{\\imath} \\to").highlight(X_COLOR)
        j_to = TexMobject("\\hat{\\jmath} \\to").highlight(Y_COLOR)
        k_to = TexMobject("\\hat{k} \\to").highlight(Z_COLOR)
        i_array = Matrix(self.col1)
        j_array = Matrix(self.col2)
        k_array = Matrix(self.col3)
        everything = VMobject(
            i_to, i_array, TexMobject("=").highlight(BLACK),
            j_to, j_array, TexMobject("=").highlight(BLACK),
            k_to, k_array, TexMobject("=").highlight(BLACK),
        )
        everything.arrange_submobjects(RIGHT, buff = 0.1)
        everything.scale_to_fit_width(2*SPACE_WIDTH-1)
        everything.to_edge(DOWN)

        i_array.highlight(X_COLOR)
        j_array.highlight(Y_COLOR)
        k_array.highlight(Z_COLOR)
        arrays = [i_array, j_array, k_array]
        matrix = Matrix(reduce(
            lambda a1, a2 : np.append(a1, a2, axis = 1),
            [m.copy().get_mob_matrix() for m in arrays]
        ))
        matrix.to_edge(DOWN)

        start_entries = reduce(op.add, map(
            lambda a : a.get_entries().split(),
            arrays
        ))
        target_entries = matrix.get_mob_matrix().transpose().flatten()
        start_l_bracket = i_array.get_brackets().split()[0]
        start_r_bracket = k_array.get_brackets().split()[1]
        start_brackets = VMobject(start_l_bracket, start_r_bracket)
        target_bracketes = matrix.get_brackets()

        for mob in everything.split():
            self.play(Write(mob, run_time = 1))
        self.dither()
        self.play(
            FadeOut(everything),
            Transform(VMobject(*start_entries), VMobject(*target_entries)),
            Transform(start_brackets, target_bracketes)
        )
        self.dither()
Exemple #11
0
    def construct(self):
        icons = [VideoIcon() for x in range(10)]
        colors = Color(BLUE_A).range_to(BLUE_D, len(icons))
        for icon, color in zip(icons, colors):
            icon.set_fill(color, opacity=1)
        icons = VMobject(*icons)
        icons.arrange_submobjects(RIGHT)
        icons.to_edge(LEFT)
        icons.shift(UP)
        icons = icons.split()

        def rate_func_creator(offset):
            return lambda a: min(max(2 * (a - offset), 0), 1)

        self.play(*[
            FadeIn(icon, run_time=5, rate_func=rate_func_creator(offset))
            for icon, offset in zip(icons, np.linspace(0, 0.5, len(icons)))
        ])
        self.wait()
Exemple #12
0
    def show_matrix(self):
        for vect, char in zip([self.i_hat, self.j_hat], ["i", "j"]):
            vect.words = TextMobject("$\\hat\\%smath$ lands on" % char,
                                     str(int(vect.get_end()[0])))
            direction = UP if vect is self.i_hat else DOWN
            vect.words.next_to(vect.get_end(), direction, buff=LARGE_BUFF)
            vect.words.highlight(vect.get_color())
        matrix = Matrix([[1, 2]])
        matrix_words = TextMobject("Transformation matrix: ")
        matrix_group = VMobject(matrix_words, matrix)
        matrix_group.arrange_submobjects(buff=MED_SMALL_BUFF)
        matrix_group.to_edge(UP)
        entries = matrix.get_entries()

        self.play(Write(matrix_words), Write(matrix.get_brackets()))
        for i, vect in enumerate([self.i_hat, self.j_hat]):
            self.play(vect.rotate, np.pi / 12, rate_func=wiggle)
            self.play(Write(vect.words))
            self.dither()
            self.play(vect.words[1].copy().move_to, entries[i])
            self.dither()
Exemple #13
0
    def cs_conception(self, creatures):
        self.fade_all_but(creatures, 1)
        physy, compy, mathy = creatures

        title = TextMobject("Vectors $\\Leftrightarrow$ lists of numbers")
        title.to_edge(UP)

        vectors = VMobject(*map(matrix_to_mobject, [
            [2, 1],
            [5, 0, 0, -3],
            [2.3, -7.1, 0.1],
        ]))
        vectors.arrange_submobjects(RIGHT, buff=1)
        vectors.to_edge(LEFT)

        self.play(ApplyMethod(compy.change_mode, "sassy"),
                  Write(title, run_time=1))
        self.play(Write(vectors))
        self.dither()
        self.play(ApplyMethod(compy.change_mode, "pondering"))
        self.house_example(vectors, title)
        self.restore_creatures(creatures)
Exemple #14
0
    def construct(self):
        icons = [VideoIcon() for x in range(10)]
        colors = Color(BLUE_A).range_to(BLUE_D, len(icons))
        for icon, color in zip(icons, colors):
            icon.set_fill(color, opacity = 1)
        icons = VMobject(*icons)
        icons.arrange_submobjects(RIGHT)
        icons.to_edge(LEFT)
        icons.shift(UP)
        icons = icons.split()

        def rate_func_creator(offset):
            return lambda a : min(max(2*(a-offset), 0), 1)
        self.play(*[
            FadeIn(
                icon, 
                run_time = 5,
                rate_func = rate_func_creator(offset)
            )
            for icon, offset in zip(icons, np.linspace(0, 0.5, len(icons)))
        ])
        self.dither()
Exemple #15
0
    def show_matrix(self):
        for vect, char in zip([self.i_hat, self.j_hat], ["i", "j"]):
            vect.words = TextMobject(
                "$\\hat\\%smath$ lands on"%char,
                str(int(vect.get_end()[0]))
            )
            direction = UP if vect is self.i_hat else DOWN
            vect.words.next_to(vect.get_end(), direction, buff = LARGE_BUFF)
            vect.words.highlight(vect.get_color())
        matrix = Matrix([[1, 2]])
        matrix_words = TextMobject("Transformation matrix: ")
        matrix_group = VMobject(matrix_words, matrix)
        matrix_group.arrange_submobjects(buff = MED_SMALL_BUFF)
        matrix_group.to_edge(UP)
        entries = matrix.get_entries()

        self.play(Write(matrix_words), Write(matrix.get_brackets()))
        for i, vect in enumerate([self.i_hat, self.j_hat]):
            self.play(vect.rotate, np.pi/12, rate_func = wiggle)
            self.play(Write(vect.words))
            self.dither()
            self.play(vect.words[1].copy().move_to, entries[i])
            self.dither()
Exemple #16
0
    def cs_conception(self, creatures):
        self.fade_all_but(creatures, 1)
        physy, compy, mathy = creatures

        title = TextMobject("Vectors $\\Leftrightarrow$ lists of numbers")
        title.to_edge(UP)

        vectors = VMobject(*map(matrix_to_mobject, [
            [2, 1],
            [5, 0, 0, -3],
            [2.3, -7.1, 0.1],
        ]))
        vectors.arrange_submobjects(RIGHT, buff = 1)
        vectors.to_edge(LEFT)

        self.play(
            ApplyMethod(compy.change_mode, "sassy"),
            Write(title, run_time = 1)
        )
        self.play(Write(vectors))
        self.dither()
        self.play(ApplyMethod(compy.change_mode, "pondering"))
        self.house_example(vectors, title)
        self.restore_creatures(creatures)
Exemple #17
0
    def series_of_videos(self, chapters):
        icon = SVGMobject("video_icon")
        icon.center()
        icon.scale_to_fit_width(2*SPACE_WIDTH/12.)
        icon.set_stroke(color = WHITE, width = 0)
        icons = [icon.copy() for chapter in chapters.split()]
        colors = Color(BLUE_A).range_to(BLUE_D, len(icons))
        for icon, color in zip(icons, colors):
            icon.set_fill(color, opacity = 1)
        icons = VMobject(*icons)
        icons.arrange_submobjects(RIGHT)
        icons.to_edge(LEFT)
        icons.shift(UP)

        randy = Randolph()
        randy.to_corner()
        bubble = randy.get_bubble()
        new_icons = icons.copy().scale(0.2)
        bubble.position_mobject_inside(new_icons)

        self.play(Transform(
            chapters, icons,
            path_arc = np.pi/2,
        ))
        self.clear()
        self.add(icons)
        self.play(FadeIn(randy))
        self.play(Blink(randy))
        self.dither()
        self.play(
            ShowCreation(bubble),
            Transform(icons, new_icons)
        )
        self.remove(icons)
        bubble.make_green_screen()
        self.dither()
Exemple #18
0
    def construct(self):
        vect = Matrix(["x", "y"])
        vect.get_entries().highlight(YELLOW)

        rot_matrix = Matrix([[0, -1], [1, 0]])
        rot_matrix.highlight(TEAL)
        shear_matrix = Matrix([[1, 1], [0, 1]])
        shear_matrix.highlight(PINK)
        l_paren, r_paren = map(TexMobject, ["\\Big(", "\\Big)"])
        for p in l_paren, r_paren:
            p.scale_to_fit_height(1.4*vect.get_height())
        long_way = VMobject(
            shear_matrix, l_paren, rot_matrix, vect, r_paren
        )
        long_way.arrange_submobjects(buff = 0.1)
        long_way.to_edge(LEFT).shift(UP)

        equals = TexMobject("=").next_to(long_way, RIGHT)

        comp_matrix = Matrix([[1, -1], [1, 0]])
        comp_matrix.highlight_columns(X_COLOR, Y_COLOR)
        vect_copy = vect.copy()
        short_way = VMobject(comp_matrix, vect_copy)
        short_way.arrange_submobjects(buff = 0.1)
        short_way.next_to(equals, RIGHT)

        pairs = [
            (rot_matrix, "Rotation"), 
            (shear_matrix, "Shear"),
            (comp_matrix, "Composition"),
        ]
        for matrix, word in pairs:
            brace = Brace(matrix)
            text = TextMobject(word).next_to(brace, DOWN)
            brace.highlight(matrix.get_color())
            text.highlight(matrix.get_color())
            matrix.add(brace, text)
        comp_matrix.split()[-1].submobject_gradient_highlight(TEAL, PINK)

        self.add(vect)
        groups = [
            [rot_matrix], 
            [l_paren, r_paren, shear_matrix],
            [equals, comp_matrix, vect_copy],
        ]
        for group in groups:
            self.play(*map(Write, group))
            self.dither()
        self.play(*map(FadeOut, [l_paren, r_paren, vect, vect_copy]))
        comp_matrix.add(equals)
        matrices = VMobject(shear_matrix, rot_matrix, comp_matrix)
        self.play(ApplyMethod(
            matrices.arrange_submobjects, buff = 0.1,
            aligned_edge = UP
        ))
        self.dither()

        arrow = Arrow(rot_matrix.get_right(), shear_matrix.get_left())
        arrow.shift((rot_matrix.get_top()[1]+0.2)*UP)
        words = TextMobject("Read right to left")
        words.submobjects.reverse()
        words.next_to(arrow, UP)
        functions = TexMobject("f(g(x))")
        functions.next_to(words, UP)

        self.play(ShowCreation(arrow))
        self.play(Write(words))
        self.dither()
        self.play(Write(functions))
        self.dither()
Exemple #19
0
    def construct(self):
        vect = Matrix(["x", "y"])
        vect.get_entries().highlight(YELLOW)

        rot_matrix = Matrix([[0, -1], [1, 0]])
        rot_matrix.highlight(TEAL)
        shear_matrix = Matrix([[1, 1], [0, 1]])
        shear_matrix.highlight(PINK)
        l_paren, r_paren = map(TexMobject, ["\\Big(", "\\Big)"])
        for p in l_paren, r_paren:
            p.scale_to_fit_height(1.4 * vect.get_height())
        long_way = VMobject(shear_matrix, l_paren, rot_matrix, vect, r_paren)
        long_way.arrange_submobjects(buff=0.1)
        long_way.to_edge(LEFT).shift(UP)

        equals = TexMobject("=").next_to(long_way, RIGHT)

        comp_matrix = Matrix([[1, -1], [1, 0]])
        comp_matrix.highlight_columns(X_COLOR, Y_COLOR)
        vect_copy = vect.copy()
        short_way = VMobject(comp_matrix, vect_copy)
        short_way.arrange_submobjects(buff=0.1)
        short_way.next_to(equals, RIGHT)

        pairs = [
            (rot_matrix, "Rotation"),
            (shear_matrix, "Shear"),
            (comp_matrix, "Composition"),
        ]
        for matrix, word in pairs:
            brace = Brace(matrix)
            text = TextMobject(word).next_to(brace, DOWN)
            brace.highlight(matrix.get_color())
            text.highlight(matrix.get_color())
            matrix.add(brace, text)
        comp_matrix.split()[-1].submobject_gradient_highlight(TEAL, PINK)

        self.add(vect)
        groups = [
            [rot_matrix],
            [l_paren, r_paren, shear_matrix],
            [equals, comp_matrix, vect_copy],
        ]
        for group in groups:
            self.play(*map(Write, group))
            self.wait()
        self.play(*map(FadeOut, [l_paren, r_paren, vect, vect_copy]))
        comp_matrix.add(equals)
        matrices = VMobject(shear_matrix, rot_matrix, comp_matrix)
        self.play(
            ApplyMethod(matrices.arrange_submobjects,
                        buff=0.1,
                        aligned_edge=UP))
        self.wait()

        arrow = Arrow(rot_matrix.get_right(), shear_matrix.get_left())
        arrow.shift((rot_matrix.get_top()[1] + 0.2) * UP)
        words = TextMobject("Read right to left")
        words.submobjects.reverse()
        words.next_to(arrow, UP)
        functions = TexMobject("f(g(x))")
        functions.next_to(words, UP)

        self.play(ShowCreation(arrow))
        self.play(Write(words))
        self.wait()
        self.play(Write(functions))
        self.wait()