from manimlib.imports import * from old_projects.eola.chapter3 import MatrixVectorMultiplicationAbstract class OpeningQuote(Scene): def construct(self): words = TextMobject([ "It is my experience that proofs involving", "matrices", "can be shortened by 50\\% if one", "throws the matrices out." ]) words.set_width(FRAME_WIDTH - 2) words.to_edge(UP) words.split()[1].set_color(GREEN) words.split()[3].set_color(BLUE) author = TextMobject("-Emil Artin") author.set_color(YELLOW) author.next_to(words, DOWN, buff = 0.5) self.play(FadeIn(words)) self.wait(2) self.play(Write(author, run_time = 3)) self.wait() class MatrixToBlank(Scene): def construct(self): matrix = Matrix([[3, 1], [0, 2]]) arrow = Arrow(LEFT, RIGHT) matrix.to_edge(LEFT) arrow.next_to(matrix, RIGHT) matrix.add(arrow) self.play(Write(matrix)) self.wait() class ExampleTransformation(LinearTransformationScene): def construct(self): self.setup() self.apply_transposed_matrix([[3, 0], [1, 2]]) self.wait(2) class RecapTime(TeacherStudentsScene): def construct(self): self.setup() self.teacher_says("Quick recap time!") self.random_blink() self.wait() student = self.get_students()[0] everyone = self.get_mobjects() everyone.remove(student) everyone = VMobject(*everyone) self.play( ApplyMethod(everyone.fade, 0.7), ApplyMethod(student.change_mode, "confused") ) self.play(Blink(student)) self.wait() self.play(ApplyFunction( lambda m : m.change_mode("pondering").look(LEFT), student )) self.play(Blink(student)) self.wait() class DeterminedByTwoBasisVectors(LinearTransformationScene): CONFIG = { "show_basis_vectors" : False } def construct(self): self.setup() i_hat = self.add_vector([1, 0], color = X_COLOR) self.add_transformable_label( i_hat, "\\hat{\\imath}", "\\hat{\\imath}", color = X_COLOR ) j_hat = self.add_vector([0, 1], color = Y_COLOR) self.add_transformable_label( j_hat, "\\hat{\\jmath}", "\\hat{\\jmath}", color = Y_COLOR ) t_matrix = np.array([[2, 2], [-2, 1]]) matrix = t_matrix.transpose() matrix1 = np.array(matrix) matrix1[:,1] = [0, 1] matrix2 = np.dot(matrix, np.linalg.inv(matrix1)) self.wait() self.apply_transposed_matrix(matrix1.transpose()) self.apply_transposed_matrix(matrix2.transpose()) self.wait() class FollowLinearCombination(LinearTransformationScene): def construct(self): vect_coords = [-1, 2] t_matrix = np.array([[2, 2], [-2, 1]]) #Draw vectors self.setup() i_label = self.add_transformable_label( self.i_hat, "\\hat{\\imath}", animate = False, direction = "right", color = X_COLOR ) j_label = self.add_transformable_label( self.j_hat, "\\hat{\\jmath}", animate = False, direction = "right", color = Y_COLOR ) vect = self.add_vector(vect_coords) vect_array = Matrix(["x", "y"], add_background_rectangles_to_entries = True) v_equals = TexMobject(["\\vec{\\textbf{v}}", "="]) v_equals.split()[0].set_color(YELLOW) v_equals.next_to(vect_array, LEFT) vect_array.add(v_equals) vect_array.to_edge(UP, buff = 0.2) background_rect = BackgroundRectangle(vect_array) vect_array.get_entries().set_color(YELLOW) self.play(ShowCreation(background_rect), Write(vect_array)) self.add_foreground_mobject(background_rect, vect_array) #Show scaled vectors x, y = vect_array.get_entries().split() scaled_i_label = VMobject(x.copy(), i_label) scaled_j_label = VMobject(y.copy(), j_label) scaled_i = self.i_hat.copy().scale(vect_coords[0]) scaled_j = self.j_hat.copy().scale(vect_coords[1]) for mob in scaled_i, scaled_j: mob.fade(0.3) scaled_i_label_target = scaled_i_label.copy() scaled_i_label_target.arrange(buff = 0.1) scaled_i_label_target.next_to(scaled_i, DOWN) scaled_j_label_target = scaled_j_label.copy() scaled_j_label_target.arrange(buff = 0.1) scaled_j_label_target.next_to(scaled_j, LEFT) self.show_scaled_vectors(vect_array, vect_coords, i_label, j_label) self.apply_transposed_matrix(t_matrix) self.show_scaled_vectors(vect_array, vect_coords, i_label, j_label) self.record_basis_coordinates(vect_array, vect) def show_scaled_vectors(self, vect_array, vect_coords, i_label, j_label): x, y = vect_array.get_entries().split() scaled_i_label = VMobject(x.copy(), i_label.copy()) scaled_j_label = VMobject(y.copy(), j_label.copy()) scaled_i = self.i_hat.copy().scale(vect_coords[0]) scaled_j = self.j_hat.copy().scale(vect_coords[1]) for mob in scaled_i, scaled_j: mob.fade(0.3) scaled_i_label_target = scaled_i_label.copy() scaled_i_label_target.arrange(buff = 0.1) scaled_i_label_target.next_to(scaled_i.get_center(), DOWN) scaled_j_label_target = scaled_j_label.copy() scaled_j_label_target.arrange(buff = 0.1) scaled_j_label_target.next_to(scaled_j.get_center(), LEFT) self.play( Transform(self.i_hat.copy(), scaled_i), Transform(scaled_i_label, scaled_i_label_target) ) scaled_i = self.get_mobjects_from_last_animation()[0] self.play( Transform(self.j_hat.copy(), scaled_j), Transform(scaled_j_label, scaled_j_label_target) ) scaled_j = self.get_mobjects_from_last_animation()[0] self.play(*[ ApplyMethod(mob.shift, scaled_i.get_end()) for mob in (scaled_j, scaled_j_label) ]) self.wait() self.play(*list(map(FadeOut, [ scaled_i, scaled_j, scaled_i_label, scaled_j_label, ]))) def record_basis_coordinates(self, vect_array, vect): i_label = vector_coordinate_label(self.i_hat) i_label.set_color(X_COLOR) j_label = vector_coordinate_label(self.j_hat) j_label.set_color(Y_COLOR) for mob in i_label, j_label: mob.scale_in_place(0.8) background = BackgroundRectangle(mob) self.play(ShowCreation(background), Write(mob)) self.wait() x, y = vect_array.get_entries().split() pre_formula = VMobject( x, i_label, TexMobject("+"), y, j_label ) post_formula = pre_formula.copy() pre_formula.split()[2].fade(1) post_formula.arrange(buff = 0.1) post_formula.next_to(vect, DOWN) background = BackgroundRectangle(post_formula) everything = self.get_mobjects() everything.remove(vect) self.play(*[ ApplyMethod(m.fade) for m in everything ] + [ ShowCreation(background, run_time = 2, rate_func = squish_rate_func(smooth, 0.5, 1)), Transform(pre_formula.copy(), post_formula, run_time = 2), ApplyMethod(vect.set_stroke, width = 7) ]) self.wait() class MatrixVectorMultiplicationCopy(MatrixVectorMultiplicationAbstract): pass ## Here just for stage_animations.py purposes class RecapOver(TeacherStudentsScene): def construct(self): self.setup() self.teacher_says("Recap over!") class TwoSuccessiveTransformations(LinearTransformationScene): CONFIG = { "foreground_plane_kwargs" : { "x_radius" : FRAME_WIDTH, "y_radius" : FRAME_WIDTH, "secondary_line_ratio" : 0 }, } def construct(self): self.setup() self.apply_transposed_matrix([[2, 1],[1, 2]]) self.apply_transposed_matrix([[-1, -0.5],[0, -0.5]]) self.wait() class RotationThenShear(LinearTransformationScene): CONFIG = { "foreground_plane_kwargs" : { "x_radius" : FRAME_X_RADIUS, "y_radius" : FRAME_WIDTH, "secondary_line_ratio" : 0 }, } def construct(self): self.setup() rot_words = TextMobject("$90^\\circ$ rotation counterclockwise") shear_words = TextMobject("followed by a shear") rot_words.set_color(YELLOW) shear_words.set_color(PINK) VMobject(rot_words, shear_words).arrange(DOWN).to_edge(UP) for words in rot_words, shear_words: words.add_background_rectangle() self.play(Write(rot_words, run_time = 1)) self.add_foreground_mobject(rot_words) self.apply_transposed_matrix([[0, 1], [-1, 0]]) self.play(Write(shear_words, run_time = 1)) self.add_foreground_mobject(shear_words) self.apply_transposed_matrix([[1, 0], [1, 1]]) self.wait() class IntroduceIdeaOfComposition(RotationThenShear): def construct(self): self.setup() self.show_composition() matrix = self.track_basis_vectors() self.show_overall_effect(matrix) def show_composition(self): words = TextMobject([ "``Composition''", "of a", "rotation", "and a", "shear" ]) words.split()[0].set_submobject_colors_by_gradient(YELLOW, PINK, use_color_range_to = False) words.split()[2].set_color(YELLOW) words.split()[4].set_color(PINK) words.add_background_rectangle() words.to_edge(UP) self.apply_transposed_matrix([[0, 1], [-1, 0]], run_time = 2) self.apply_transposed_matrix([[1, 0], [1, 1]], run_time = 2) self.play( ApplyMethod(self.plane.fade), Write(words), Animation(self.i_hat), Animation(self.j_hat), ) self.wait() def track_basis_vectors(self): last_words = self.get_mobjects_from_last_animation()[1] words = TextMobject([ "Record where", "$\\hat{\\imath}$", "and", "$\\hat{\\jmath}$", "land:" ]) rw, i_hat, a, j_hat, l = words.split() i_hat.set_color(X_COLOR) j_hat.set_color(Y_COLOR) words.add_background_rectangle() words.next_to(last_words, DOWN) i_coords = vector_coordinate_label(self.i_hat) j_coords = vector_coordinate_label(self.j_hat) i_coords.set_color(X_COLOR) j_coords.set_color(Y_COLOR) i_background = BackgroundRectangle(i_coords) j_background = BackgroundRectangle(j_coords) matrix = Matrix(np.append( i_coords.copy().get_mob_matrix(), j_coords.copy().get_mob_matrix(), axis = 1 )) matrix.next_to(words, RIGHT, aligned_edge = UP) col1, col2 = [ VMobject(*matrix.get_mob_matrix()[:,i]) for i in (0, 1) ] matrix_background = BackgroundRectangle(matrix) self.play(Write(words)) self.wait() self.play(ShowCreation(i_background), Write(i_coords), run_time = 2) self.wait() self.play( Transform(i_background.copy(), matrix_background), Transform(i_coords.copy().get_brackets(), matrix.get_brackets()), ApplyMethod(i_coords.copy().get_entries().move_to, col1) ) self.wait() self.play(ShowCreation(j_background), Write(j_coords), run_time = 2) self.wait() self.play( ApplyMethod(j_coords.copy().get_entries().move_to, col2) ) self.wait() matrix = VMobject(matrix_background, matrix) return matrix def show_overall_effect(self, matrix): everything = self.get_mobjects() everything = list_difference_update( everything, matrix.get_family() ) self.play(*list(map(FadeOut, everything)) + [Animation(matrix)]) new_matrix = matrix.copy() new_matrix.center().to_edge(UP) self.play(Transform(matrix, new_matrix)) self.wait() self.remove(matrix) self.setup() everything = self.get_mobjects() self.play(*list(map(FadeIn, everything)) + [Animation(matrix)]) func = self.get_matrix_transformation([[1, 1], [-1, 0]]) bases = VMobject(self.i_hat, self.j_hat) new_bases = VMobject(*[ Vector(func(v.get_end()), color = v.get_color()) for v in bases.split() ]) self.play( ApplyPointwiseFunction(func, self.plane), Transform(bases, new_bases), Animation(matrix), run_time = 3 ) self.wait() class PumpVectorThroughRotationThenShear(RotationThenShear): def construct(self): self.setup() self.add_vector([2, 3]) self.apply_transposed_matrix([[0, 1], [-1, 0]], run_time = 2) self.apply_transposed_matrix([[1, 0], [1, 1]], run_time = 2) self.wait() class ExplainWhyItsMatrixMultiplication(Scene): def construct(self): vect = Matrix(["x", "y"]) vect.get_entries().set_color(YELLOW) rot_matrix = Matrix([[0, -1], [1, 0]]) rot_matrix.set_color(TEAL) shear_matrix = Matrix([[1, 1], [0, 1]]) shear_matrix.set_color(PINK) l_paren, r_paren = list(map(TexMobject, ["\\Big(", "\\Big)"])) for p in l_paren, r_paren: p.set_height(1.4*vect.get_height()) long_way = VMobject( shear_matrix, l_paren, rot_matrix, vect, r_paren ) long_way.arrange(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.set_column_colors(X_COLOR, Y_COLOR) vect_copy = vect.copy() short_way = VMobject(comp_matrix, vect_copy) short_way.arrange(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.set_color(matrix.get_color()) text.set_color(matrix.get_color()) matrix.add(brace, text) comp_matrix.split()[-1].set_submobject_colors_by_gradient(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(*list(map(Write, group))) self.wait() self.play(*list(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, 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() class MoreComplicatedExampleVisually(LinearTransformationScene): CONFIG = { "t_matrix1" : [[1, 1], [-2, 0]], "t_matrix2" : [[0, 1], [2, 0]], } def construct(self): self.setup() t_matrix1 = np.array(self.t_matrix1) t_matrix2 = np.array(self.t_matrix2) t_m1_inv = np.linalg.inv(t_matrix1.transpose()).transpose() t_m2_inv = np.linalg.inv(t_matrix2.transpose()).transpose() m1_mob, m2_mob, comp_matrix = self.get_matrices() self.play(Write(m1_mob)) self.add_foreground_mobject(m1_mob) self.wait() self.apply_transposed_matrix(t_matrix1) self.wait() self.play(Write(m1_mob.label)) self.add_foreground_mobject(m1_mob.label) self.wait() self.apply_transposed_matrix(t_m1_inv, run_time = 0) self.wait() self.play(Write(m2_mob)) self.add_foreground_mobject(m2_mob) self.wait() self.apply_transposed_matrix(t_matrix2) self.wait() self.play(Write(m2_mob.label)) self.add_foreground_mobject(m2_mob.label) self.wait() self.apply_transposed_matrix(t_m2_inv, run_time = 0) self.wait() for matrix in t_matrix1, t_matrix2: self.apply_transposed_matrix(matrix, run_time = 1) self.play(Write(comp_matrix)) self.add_foreground_mobject(comp_matrix) self.wait() self.play(*list(map(FadeOut, [ self.background_plane, self.plane, self.i_hat, self.j_hat, ])) + [ Animation(m) for m in self.foreground_mobjects ]) self.remove(self.i_hat, self.j_hat) self.wait() def get_matrices(self): m1_mob = Matrix(np.array(self.t_matrix1).transpose()) m2_mob = Matrix(np.array(self.t_matrix2).transpose()) comp_matrix = Matrix([["?", "?"], ["?", "?"]]) m1_mob.set_color(YELLOW) m2_mob.set_color(PINK) comp_matrix.get_entries().set_submobject_colors_by_gradient(YELLOW, PINK) equals = TexMobject("=") equals.next_to(comp_matrix, LEFT) comp_matrix.add(equals) m1_mob = VMobject(BackgroundRectangle(m1_mob), m1_mob) m2_mob = VMobject(BackgroundRectangle(m2_mob), m2_mob) comp_matrix = VMobject(BackgroundRectangle(comp_matrix), comp_matrix) VMobject( m2_mob, m1_mob, comp_matrix ).arrange(buff = 0.1).to_corner(UP+LEFT).shift(DOWN) for i, mob in enumerate([m1_mob, m2_mob]): brace = Brace(mob, UP) text = TexMobject("M_%d"%(i+1)) text.next_to(brace, UP) brace.add_background_rectangle() text.add_background_rectangle() brace.add(text) mob.label = brace return m1_mob, m2_mob, comp_matrix class MoreComplicatedExampleNumerically(MoreComplicatedExampleVisually): def get_result(self): return np.dot(self.t_matrix1, self.t_matrix2).transpose() def construct(self): m1_mob, m2_mob, comp_matrix = self.get_matrices() self.add(m1_mob, m2_mob, m1_mob.label, m2_mob.label, comp_matrix) result = self.get_result() col1, col2 = [ VMobject(*m1_mob.split()[1].get_mob_matrix()[:,i]) for i in (0, 1) ] col1.target_color = X_COLOR col2.target_color = Y_COLOR for col in col1, col2: circle = Circle() circle.stretch_to_fit_height(m1_mob.get_height()) circle.stretch_to_fit_width(m1_mob.get_width()/2.5) circle.set_color(col.target_color) circle.move_to(col) col.circle = circle triplets = [ (col1, "i", X_COLOR), (col2, "j", Y_COLOR), ] for i, (col, char, color) in enumerate(triplets): self.add(col) start_state = self.get_mobjects() question = TextMobject( "Where does $\\hat{\\%smath}$ go?"%char ) question.split()[-4].set_color(color) question.split()[-5].set_color(color) question.scale(1.2) question.shift(DOWN) first = TextMobject("First here") first.set_color(color) first.shift(DOWN+LEFT) first_arrow = Arrow( first, col.circle.get_bottom(), color = color ) second = TextMobject("Then to whatever this is") second.set_color(color) second.to_edge(RIGHT).shift(DOWN) m2_copy = m2_mob.copy() m2_target = m2_mob.copy() m2_target.next_to(m2_mob, DOWN, buff = 1) col_vect = Matrix(col.copy().split()) col_vect.set_color(color) col_vect.next_to(m2_target, RIGHT, buff = 0.1) second_arrow = Arrow(second, col_vect, color = color) new_m2_copy = m2_mob.copy().split()[1] intermediate = VMobject( TexMobject("="), col_vect.copy().get_entries().split()[0], Matrix(new_m2_copy.get_mob_matrix()[:,0]), TexMobject("+"), col_vect.copy().get_entries().split()[1], Matrix(new_m2_copy.get_mob_matrix()[:,1]), TexMobject("=") ) intermediate.arrange(buff = 0.1) intermediate.next_to(col_vect, RIGHT) product = Matrix(result[:,i]) product.next_to(intermediate, RIGHT) comp_col = VMobject(*comp_matrix.split()[1].get_mob_matrix()[:,i]) self.play(Write(question, run_time = 1 )) self.wait() self.play( Transform(question, first), ShowCreation(first_arrow), ShowCreation(col.circle), ApplyMethod(col.set_color, col.target_color) ) self.wait() self.play( Transform(m2_copy, m2_target, run_time = 2), ApplyMethod(col.copy().move_to, col_vect, run_time = 2), Write(col_vect.get_brackets()), Transform(first_arrow, second_arrow), Transform(question, second), ) self.wait() self.play(*list(map(FadeOut, [question, first_arrow]))) self.play(Write(intermediate)) self.wait() self.play(Write(product)) self.wait() product_entries = product.get_entries() self.play( ApplyMethod(comp_col.set_color, BLACK), ApplyMethod(product_entries.move_to, comp_col) ) self.wait() start_state.append(product_entries) self.play(*[ FadeOut(mob) for mob in self.get_mobjects() if mob not in start_state ] + [ Animation(product_entries) ]) self.wait() class GeneralMultiplication(MoreComplicatedExampleNumerically): def get_result(self): entries = list(map(TexMobject, [ "ae+bg", "af+bh", "ce+dg", "cf+dh" ])) for mob in entries: mob.split()[0].set_color(PINK) mob.split()[3].set_color(PINK) for mob in entries[0], entries[2]: mob.split()[1].set_color(X_COLOR) mob.split()[4].set_color(X_COLOR) for mob in entries[1], entries[3]: mob.split()[1].set_color(Y_COLOR) mob.split()[4].set_color(Y_COLOR) return np.array(entries).reshape((2, 2)) def get_matrices(self): m1, m2, comp = MoreComplicatedExampleNumerically.get_matrices(self) self.add(m1, m2, m1.label, m2.label, comp) m1_entries = m1.split()[1].get_entries() m2_entries = m2.split()[1].get_entries() m2_entries_target = VMobject(*[ TexMobject(char).move_to(entry).set_color(entry.get_color()) for entry, char in zip(m2_entries.split(), "abcd") ]) m1_entries_target = VMobject(*[ TexMobject(char).move_to(entry).set_color(entry.get_color()) for entry, char in zip(m1_entries.split(), "efgh") ]) words = TextMobject("This method works generally") self.play(Write(words, run_time = 2)) self.play(Transform( m1_entries, m1_entries_target, lag_ratio = 0.5 )) self.play(Transform( m2_entries, m2_entries_target, lag_ratio = 0.5 )) self.wait() new_comp = Matrix(self.get_result()) new_comp.next_to(comp.split()[1].submobjects[-1], RIGHT) new_comp.get_entries().set_color(BLACK) self.play( Transform(comp.split()[1].get_brackets(), new_comp.get_brackets()), *[ ApplyMethod(q_mark.move_to, entry) for q_mark, entry in zip( comp.split()[1].get_entries().split(), new_comp.get_entries().split() ) ] ) self.wait() self.play(FadeOut(words)) return m1, m2, comp class MoreComplicatedExampleWithJustIHat(MoreComplicatedExampleVisually): CONFIG = { "show_basis_vectors" : False, "v_coords" : [1, 0], "v_color" : X_COLOR, } def construct(self): self.setup() self.add_vector(self.v_coords, self.v_color) self.apply_transposed_matrix(self.t_matrix1) self.wait() self.apply_transposed_matrix(self.t_matrix2) self.wait() class MoreComplicatedExampleWithJustJHat(MoreComplicatedExampleWithJustIHat): CONFIG = { "v_coords" : [0, 1], "v_color" : Y_COLOR, } class RoteMatrixMultiplication(NumericalMatrixMultiplication): CONFIG = { "left_matrix" : [[-3, 1], [2, 5]], "right_matrix" : [[5, 3], [7, -3]] } class NeverForget(TeacherStudentsScene): def construct(self): self.setup() self.teacher_says("Never forget what \\\\ this represents!") self.random_blink() self.student_thinks("", student_index = 0) def warp(point): point += 2*DOWN+RIGHT return 20*point/get_norm(point) self.play(ApplyPointwiseFunction( warp, VMobject(*self.get_mobjects()) )) class AskAboutCommutativity(Scene): def construct(self): l_m1, l_m2, eq, r_m2, r_m1 = TexMobject([ "M_1", "M_2", "=", "M_2", "M_1" ]).scale(1.5).split() VMobject(l_m1, r_m1).set_color(YELLOW) VMobject(l_m2, r_m2).set_color(PINK) q_marks = TextMobject("???") q_marks.set_color(TEAL) q_marks.next_to(eq, UP) neq = TexMobject("\\neq") neq.move_to(eq) self.play(*list(map(Write, [l_m1, l_m2, eq]))) self.play( Transform(l_m1.copy(), r_m1), Transform(l_m2.copy(), r_m2), path_arc = -np.pi, run_time = 2 ) self.play(Write(q_marks)) self.wait() self.play(Transform( VMobject(eq, q_marks), VMobject(neq), lag_ratio = 0.5 )) self.wait() class ShowShear(LinearTransformationScene): CONFIG = { "title" : "Shear", "title_color" : PINK, "t_matrix" : [[1, 0], [1, 1]] } def construct(self): self.setup() title = TextMobject(self.title) title.scale(1.5).to_edge(UP) title.set_color(self.title_color) title.add_background_rectangle() self.add_foreground_mobject(title) self.wait() self.apply_transposed_matrix(self.t_matrix) self.wait() class ShowRotation(ShowShear): CONFIG = { "title" : "$90^\\circ$ rotation", "title_color" : YELLOW, "t_matrix" : [[0, 1], [-1, 0]] } class FirstShearThenRotation(LinearTransformationScene): CONFIG = { "title" : "First shear then rotation", "t_matrix1" : [[1, 0], [1, 1]], "t_matrix2" : [[0, 1], [-1, 0]], "foreground_plane_kwargs" : { "x_radius" : FRAME_WIDTH, "y_radius" : FRAME_WIDTH, "secondary_line_ratio" : 0 }, } def construct(self): self.setup() title_parts = self.title.split(" ") title = TextMobject(title_parts) for i, part in enumerate(title_parts): if part == "rotation": title.split()[i].set_color(YELLOW) elif part == "shear": title.split()[i].set_color(PINK) title.scale(1.5) self.add_title(title) self.apply_transposed_matrix(self.t_matrix1) self.apply_transposed_matrix(self.t_matrix2) self.i_hat.rotate(-0.01)##Laziness self.wait() self.write_vector_coordinates(self.i_hat, color = X_COLOR) self.wait() self.write_vector_coordinates(self.j_hat, color = Y_COLOR) self.wait() class RotationThenShear(FirstShearThenRotation): CONFIG = { "title" : "First rotation then shear", "t_matrix1" : [[0, 1], [-1, 0]], "t_matrix2" : [[1, 0], [1, 1]], } class NoticeTheLackOfComputations(TeacherStudentsScene): def construct(self): self.setup() self.teacher_says(""" Notice the lack of computations! """) self.random_blink() students = self.get_students() random.shuffle(students) unit = np.array([-0.5, 0.5]) self.play(*[ ApplyMethod( pi.change_mode, "pondering", rate_func = squish_rate_func(smooth, *np.clip(unit+0.5*i, 0, 1)) ) for i, pi in enumerate(students) ]) self.random_blink() self.wait() class AskAssociativityQuestion(Scene): def construct(self): morty = Mortimer() morty.scale(0.8) morty.to_corner(DOWN+RIGHT) morty.shift(0.5*LEFT) title = TextMobject("Associativity:") title.to_corner(UP+LEFT) lhs = TexMobject(list("(AB)C")) lp, a, b, rp, c = lhs.split() rhs = VMobject(*[m.copy() for m in (a, lp, b, c, rp)]) point = VectorizedPoint() start = VMobject(*[m.copy() for m in (point, a, b, point, c)]) for mob in lhs, rhs, start: mob.arrange(buff = 0.1) a, lp, b, c, rp = rhs.split() rhs = VMobject(lp, a, b, rp, c)##Align order to lhs eq = TexMobject("=") q_marks = TextMobject("???") q_marks.set_submobject_colors_by_gradient(TEAL_B, TEAL_D) q_marks.next_to(eq, UP) lhs.next_to(eq, LEFT) rhs.next_to(eq, RIGHT) start.move_to(lhs) self.add(morty, title) self.wait() self.play(Blink(morty)) self.play(Write(start)) self.wait() self.play(Transform(start, lhs)) self.wait() self.play( Transform(lhs, rhs, path_arc = -np.pi), Write(eq) ) self.play(Write(q_marks)) self.play(Blink(morty)) self.play(morty.change_mode, "pondering") lp, a, b, rp, c = start.split() self.show_full_matrices(morty, a, b, c, title) def show_full_matrices(self, morty, a, b, c, title): everything = self.get_mobjects() everything.remove(morty) everything.remove(title) everything = VMobject(*everything) matrices = list(map(matrix_to_mobject, [ np.array(list(m)).reshape((2, 2)) for m in ("abcd", "efgh", "ijkl") ])) VMobject(*matrices).arrange() self.play(everything.to_edge, UP) for letter, matrix in zip([a, b, c], matrices): self.play(Transform( letter.copy(), matrix, lag_ratio = 0.5 )) self.remove(*self.get_mobjects_from_last_animation()) self.add(matrix) self.wait() self.move_matrix_parentheses(morty, matrices) def move_matrix_parentheses(self, morty, matrices): m1, m2, m3 = matrices parens = TexMobject(["(", ")"]) parens.set_height(1.2*m1.get_height()) lp, rp = parens.split() state1 = VMobject( VectorizedPoint(m1.get_left()), m1, m2, VectorizedPoint(m2.get_right()), m3 ) state2 = VMobject(*[ m.copy() for m in (lp, m1, m2, rp, m3) ]) state3 = VMobject(*[ m.copy() for m in (m1, lp, m2, m3, rp) ]) for state in state2, state3: state.arrange(RIGHT, buff = 0.1) m1, lp, m2, m3, rp = state3.split() state3 = VMobject(lp, m1, m2, rp, m3) self.play(morty.change_mode, "angry") for state in state2, state3: self.play(Transform(state1, state)) self.wait() self.play(morty.change_mode, "confused") self.wait() class ThreeSuccessiveTransformations(LinearTransformationScene): CONFIG = { "t_matrices" : [ [[2, 1], [1, 2]], [[np.cos(-np.pi/6), np.sin(-np.pi/6)], [-np.sin(-np.pi/6), np.cos(-np.pi/6)]], [[1, 0], [1, 1]] ], "symbols_str" : "A(BC)", "include_background_plane" : False, } def construct(self): self.setup() symbols = TexMobject(list(self.symbols_str)) symbols.scale(1.5) symbols.to_edge(UP) a, b, c = None, None, None for mob, letter in zip(symbols.split(), self.symbols_str): if letter == "A": a = mob elif letter == "B": b = mob elif letter == "C": c = mob symbols.add_background_rectangle() self.add_foreground_mobject(symbols) brace = Brace(c, DOWN) words = TextMobject("Apply this transformation") words.add_background_rectangle() words.next_to(brace, DOWN) brace.add(words) self.play(Write(brace, run_time = 1)) self.add_foreground_mobject(brace) last = VectorizedPoint() for t_matrix, sym in zip(self.t_matrices, [c, b, a]): self.play( brace.next_to, sym, DOWN, sym.set_color, YELLOW, last.set_color, WHITE ) self.apply_transposed_matrix(t_matrix, run_time = 1) last = sym self.wait() class ThreeSuccessiveTransformationsAltParens(ThreeSuccessiveTransformations): CONFIG = { "symbols_str" : "(AB)C" } class ThreeSuccessiveTransformationsSimple(ThreeSuccessiveTransformations): CONFIG = { "symbols_str" : "ABC" } class ExplanationTrumpsProof(Scene): def construct(self): greater = TexMobject(">") greater.shift(RIGHT) explanation = TextMobject("Good explanation") explanation.set_color(BLUE) proof = TextMobject("Symbolic proof") proof.set_color(LIGHT_BROWN) explanation.next_to(greater, LEFT) proof.next_to(greater, RIGHT) explanation.get_center = lambda : explanation.get_right() proof.get_center = lambda : proof.get_left() self.play( Write(explanation), Write(greater), Write(proof), run_time = 1 ) self.play( explanation.scale_in_place, 1.5, proof.scale_in_place, 0.7 ) self.wait() class GoPlay(TeacherStudentsScene): def construct(self): self.setup() self.teacher_says("Go play!", height = 3, width = 5) self.play(*[ ApplyMethod(student.change_mode, "happy") for student in self.get_students() ]) self.random_blink() student = self.get_students()[-1] bubble = ThoughtBubble(direction = RIGHT, width = 6, height = 5) bubble.pin_to(student, allow_flipping = False) bubble.make_green_screen() self.play( ShowCreation(bubble), student.look, UP+LEFT, ) self.play(student.change_mode, "pondering") for x in range(3): self.random_blink() self.wait(2) class NextVideo(Scene): def construct(self): title = TextMobject(""" Next video: Linear transformations in three dimensions """) title.set_width(FRAME_WIDTH - 2) title.to_edge(UP) rect = Rectangle(width = 16, height = 9, color = BLUE) rect.set_height(6) rect.next_to(title, DOWN) self.add(title) self.play(ShowCreation(rect)) self.wait()