from manimlib.imports import * from old_projects.eola.chapter1 import plane_wave_homotopy V_COLOR = YELLOW class Jennifer(PiCreature): CONFIG = { "color" : PINK, "start_corner" : DOWN+LEFT, } class You(PiCreature): CONFIG = { "color" : BLUE_E, "start_corner" : DOWN+RIGHT, "flip_at_start" : True, } def get_small_bubble(pi_creature, height = 4, width = 3): pi_center_x = pi_creature.get_center()[0] kwargs = { "height" : 4, "bubble_center_adjustment_factor" : 1./6, } bubble = ThoughtBubble(**kwargs) bubble.stretch_to_fit_width(3)##Canonical width bubble.rotate(np.pi/4) bubble.stretch_to_fit_width(width) bubble.stretch_to_fit_height(height) if pi_center_x < 0: bubble.flip() bubble.next_to(pi_creature, UP, buff = MED_SMALL_BUFF) bubble.shift_onto_screen() bubble.set_fill(BLACK, opacity = 0.8) return bubble class OpeningQuote(Scene): def construct(self): words = TextMobject( "\\centering ``Mathematics is the art of giving the \\\\", "same name ", "to ", "different things", ".''", arg_separator = " " ) words.set_color_by_tex("same name ", BLUE) words.set_color_by_tex("different things", MAROON_B) # words.set_width(FRAME_WIDTH - 2) words.to_edge(UP) author = TextMobject("-Henri Poincar\\'e.") 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(2) class LinearCombinationScene(LinearTransformationScene): CONFIG = { "include_background_plane" : False, "foreground_plane_kwargs" : { "x_radius" : FRAME_X_RADIUS, "y_radius" : FRAME_Y_RADIUS, "secondary_line_ratio" : 1 }, } def setup(self): LinearTransformationScene.setup(self) self.i_hat.label = self.get_vector_label( self.i_hat, "\\hat{\\imath}", "right" ) self.j_hat.label = self.get_vector_label( self.j_hat, "\\hat{\\jmath}", "left" ) def show_linear_combination(self, numerical_coords, basis_vectors, coord_mobs, revert_to_original = True, show_sum_vect = False, sum_vect_color = V_COLOR, ): for basis in basis_vectors: if not hasattr(basis, "label"): basis.label = VectorizedPoint() direction = np.round(rotate_vector( basis.get_end(), np.pi/2 )) basis.label.next_to(basis.get_center(), direction) basis.save_state() basis.label.save_state() if coord_mobs is None: coord_mobs = list(map(TexMobject, list(map(str, numerical_coords)))) VGroup(*coord_mobs).set_fill(opacity = 0) for coord, basis in zip(coord_mobs, basis_vectors): coord.next_to(basis.label, LEFT) for coord, basis, scalar in zip(coord_mobs, basis_vectors, numerical_coords): basis.target = basis.copy().scale(scalar) basis.label.target = basis.label.copy() coord.target = coord.copy() new_label = VGroup(coord.target, basis.label.target) new_label.arrange(aligned_edge = DOWN) new_label.move_to( basis.label, aligned_edge = basis.get_center()-basis.label.get_center() ) new_label.shift( basis.target.get_center() - basis.get_center() ) coord.target.next_to(basis.label.target, LEFT) coord.target.set_fill(basis.get_color(), opacity = 1) self.play(*list(map(MoveToTarget, [ coord, basis, basis.label ]))) self.wait() self.play(*[ ApplyMethod(m.shift, basis_vectors[0].get_end()) for m in self.get_mobjects_from_last_animation() ]) if show_sum_vect: sum_vect = Vector( basis_vectors[1].get_end(), color = sum_vect_color ) self.play(ShowCreation(sum_vect)) self.wait(2) if revert_to_original: self.play(*it.chain( [basis.restore for basis in basis_vectors], [basis.label.restore for basis in basis_vectors], [FadeOut(coord) for coord in coord_mobs], [FadeOut(sum_vect) for x in [1] if show_sum_vect], )) if show_sum_vect: return sum_vect class RemindOfCoordinates(LinearCombinationScene): CONFIG = { "vector_coords" : [3, 2] } def construct(self): self.remove(self.i_hat, self.j_hat) v = self.add_vector(self.vector_coords, color = V_COLOR) coords = self.write_vector_coordinates(v) self.show_standard_coord_meaning(*coords.get_entries().copy()) self.show_abstract_scalar_idea(*coords.get_entries().copy()) self.scale_basis_vectors(*coords.get_entries().copy()) self.list_implicit_assumptions(*coords.get_entries()) def show_standard_coord_meaning(self, x_coord, y_coord): x, y = self.vector_coords x_line = Line(ORIGIN, x*RIGHT, color = GREEN) y_line = Line(ORIGIN, y*UP, color = RED) y_line.shift(x_line.get_end()) for line, coord, direction in (x_line, x_coord, DOWN), (y_line, y_coord, LEFT): self.play( coord.set_color, line.get_color(), coord.next_to, line.get_center(), direction, ShowCreation(line), ) self.wait() self.wait() self.play(*list(map(FadeOut, [x_coord, y_coord, x_line, y_line]))) def show_abstract_scalar_idea(self, x_coord, y_coord): x_shift, y_shift = 4*LEFT, 4*RIGHT to_save = x_coord, y_coord, self.i_hat, self.j_hat for mob in to_save: mob.save_state() everything = VGroup(*self.get_mobjects()) words = TextMobject("Think of coordinates \\\\ as", "scalars") words.set_color_by_tex("scalars", YELLOW) words.to_edge(UP) x, y = self.vector_coords scaled_i = self.i_hat.copy().scale(x) scaled_j = self.j_hat.copy().scale(y) VGroup(self.i_hat, scaled_i).shift(x_shift) VGroup(self.j_hat, scaled_j).shift(y_shift) self.play( FadeOut(everything), x_coord.scale_in_place, 1.5, x_coord.move_to, x_shift + 3*UP, y_coord.scale_in_place, 1.5, y_coord.move_to, y_shift + 3*UP, Write(words) ) self.play(*list(map(FadeIn, [self.i_hat, self.j_hat]))) self.wait() self.play(Transform(self.i_hat, scaled_i)) self.play(Transform(self.j_hat, scaled_j)) self.wait() self.play( FadeOut(words), FadeIn(everything), *[mob.restore for mob in to_save] ) self.wait() def scale_basis_vectors(self, x_coord, y_coord): self.play(*list(map(Write, [self.i_hat.label, self.j_hat.label]))) self.show_linear_combination( self.vector_coords, basis_vectors = [self.i_hat, self.j_hat], coord_mobs = [x_coord, y_coord] ) def list_implicit_assumptions(self, x_coord, y_coord): everything = VGroup(*self.get_mobjects()) title = TextMobject("Implicit assumptions") h_line = Line(title.get_left(), title.get_right()) h_line.set_color(YELLOW) h_line.next_to(title, DOWN) title.add(h_line) ass1 = TextMobject("-First coordinate") ass1 = VGroup(ass1, self.i_hat.copy()) ass1.arrange(buff = MED_SMALL_BUFF) ass2 = TextMobject("-Second coordinate") ass2 = VGroup(ass2, self.j_hat.copy()) ass2.arrange(buff = MED_SMALL_BUFF) ass3 = TextMobject("-Unit of distance") group = VGroup(title, ass1, ass2, ass3) group.arrange(DOWN, aligned_edge = LEFT, buff = MED_SMALL_BUFF) group.to_corner(UP+LEFT) # VGroup(*group[1:]).shift(0.5*DOWN) for words in group: words.add_to_back(BackgroundRectangle(words)) self.play(Write(title)) self.wait() self.play( Write(ass1), ApplyFunction( lambda m : m.rotate_in_place(np.pi/6).set_color(X_COLOR), x_coord, rate_func = wiggle ) ) self.wait() self.play( Write(ass2), ApplyFunction( lambda m : m.rotate_in_place(np.pi/6).set_color(Y_COLOR), y_coord, rate_func = wiggle ) ) self.wait() self.play(Write(ass3)) self.wait(2) keepers = VGroup(*[ self.i_hat, self.j_hat, self.i_hat.label, self.j_hat.label ]) self.play( FadeOut(everything), Animation(keepers.copy()), Animation(group) ) self.wait() class NameCoordinateSystem(Scene): def construct(self): vector = Vector([3, 2]) coords = Matrix([3, 2]) arrow = TexMobject("\\Rightarrow") vector.next_to(arrow, RIGHT, buff = 0) coords.next_to(arrow, LEFT, buff = MED_LARGE_BUFF) group = VGroup(coords, arrow, vector) group.shift(2*UP) coordinate_system = TextMobject("``Coordinate system''") coordinate_system.next_to(arrow, UP, buff = LARGE_BUFF) i_hat, j_hat = Vector([1, 0]), Vector([0, 1]) i_hat.set_color(X_COLOR) j_hat.set_color(Y_COLOR) i_label = TexMobject("\\hat{\\imath}") i_label.set_color(X_COLOR) i_label.next_to(i_hat, DOWN) j_label = TexMobject("\\hat{\\jmath}") j_label.set_color(Y_COLOR) j_label.next_to(j_hat, LEFT) basis_group = VGroup(i_hat, j_hat, i_label, j_label) basis_group.shift(DOWN) basis_words = TextMobject("``Basis vectors''") basis_words.shift(basis_group.get_bottom()[1]*UP+MED_SMALL_BUFF*DOWN) self.play(Write(coords)) self.play(Write(arrow), ShowCreation(vector)) self.wait() self.play(Write(coordinate_system)) self.wait(2) self.play(Write(basis_group)) self.play(Write(basis_words)) self.wait() class WhatAboutOtherBasis(TeacherStudentsScene): def construct(self): self.teacher_says(""" \\centering What if we used different basis vectors """) self.random_blink() self.change_student_modes("pondering") self.random_blink(2) class JenniferScene(LinearCombinationScene): CONFIG = { "b1_coords" : [2, 1], "b2_coords" : [-1, 1], "foreground_plane_kwargs" : { "x_radius" : FRAME_X_RADIUS, "y_radius" : FRAME_X_RADIUS, }, } def setup(self): LinearCombinationScene.setup(self) self.remove(self.plane, self.i_hat, self.j_hat) self.jenny = Jennifer() self.you = You() self.b1 = Vector(self.b1_coords, color = X_COLOR) self.b2 = Vector(self.b2_coords, color = Y_COLOR) for i, vect in enumerate([self.b1, self.b2]): vect.label = TexMobject("\\vec{\\textbf{b}}_%d"%(i+1)) vect.label.scale(0.7) vect.label.add_background_rectangle() vect.label.set_color(vect.get_color()) self.b1.label.next_to( self.b1.get_end()*0.4, UP+LEFT, SMALL_BUFF/2 ) self.b2.label.next_to( self.b2.get_end(), DOWN+LEFT, buff = SMALL_BUFF ) self.basis_vectors = VGroup( self.b1, self.b2, self.b1.label, self.b2.label ) transform = self.get_matrix_transformation(self.cob_matrix().T) self.jenny_plane = self.plane.copy() self.jenny_plane.apply_function(transform) def cob_matrix(self): return np.array([self.b1_coords, self.b2_coords]).T def inv_cob_matrix(self): return np.linalg.inv(self.cob_matrix()) class IntroduceJennifer(JenniferScene): CONFIG = { "v_coords" : [3, 2] } def construct(self): for plane in self.plane, self.jenny_plane: plane.fade() self.introduce_jenny() self.add_basis_vectors() self.show_v_from_both_perspectives() self.how_we_label_her_basis() def introduce_jenny(self): jenny = self.jenny name = TextMobject("Jennifer") name.next_to(jenny, UP) name.shift_onto_screen() self.add(jenny) self.play( jenny.change_mode, "wave_1", jenny.look, OUT, Write(name) ) self.play( jenny.change_mode, "happy", jenny.look, UP+RIGHT, FadeOut(name) ) self.wait() def add_basis_vectors(self): words = TextMobject("Alternate basis vectors") words.shift(2.5*UP) self.play(Write(words, run_time = 2)) for vect in self.b1, self.b2: self.play( ShowCreation(vect), Write(vect.label) ) self.wait() self.play(FadeOut(words)) def show_v_from_both_perspectives(self): v = Vector(self.v_coords) jenny = self.jenny you = self.you you.coords = Matrix([3, 2]) jenny.coords = Matrix(["(5/3)", "(1/3)"]) for pi in you, jenny: pi.bubble = get_small_bubble(pi) pi.bubble.set_fill(BLACK, opacity = 0.7) pi.bubble.add_content(pi.coords) jenny.coords.scale_in_place(0.7) new_coords = [-1, 2] new_coords_mob = Matrix(new_coords) new_coords_mob.set_height(jenny.coords.get_height()) new_coords_mob.move_to(jenny.coords) for coords in you.coords, jenny.coords, new_coords_mob: for entry in coords.get_entries(): entry.add_background_rectangle() self.play(ShowCreation(v)) self.wait() self.play(*it.chain( list(map(FadeIn, [ self.plane, self.i_hat, self.j_hat, self.i_hat.label, self.j_hat.label, you ])), list(map(Animation, [jenny, v])), list(map(FadeOut, self.basis_vectors)), )) self.play( ShowCreation(you.bubble), Write(you.coords) ) self.play(you.change_mode, "speaking") self.show_linear_combination( self.v_coords, basis_vectors = [self.i_hat, self.j_hat], coord_mobs = you.coords.get_entries().copy(), ) self.play(*it.chain( list(map(FadeOut, [ self.plane, self.i_hat, self.j_hat, self.i_hat.label, self.j_hat.label, you.bubble, you.coords ])), list(map(FadeIn, [self.jenny_plane, self.basis_vectors])), list(map(Animation, [v, you, jenny])), )) self.play( ShowCreation(jenny.bubble), Write(jenny.coords), jenny.change_mode, "speaking", ) self.play(you.change_mode, "erm") self.show_linear_combination( np.dot(self.inv_cob_matrix(), self.v_coords), basis_vectors = [self.b1, self.b2], coord_mobs = jenny.coords.get_entries().copy(), ) self.play( FadeOut(v), jenny.change_mode, "plain" ) self.play( Transform(jenny.coords, new_coords_mob), Blink(jenny), ) self.hacked_show_linear_combination( new_coords, basis_vectors = [self.b1, self.b2], coord_mobs = jenny.coords.get_entries().copy(), show_sum_vect = True, ) def hacked_show_linear_combination( self, numerical_coords, basis_vectors, coord_mobs = None, show_sum_vect = False, sum_vect_color = V_COLOR, ): for coord, basis, scalar in zip(coord_mobs, basis_vectors, numerical_coords): basis.save_state() basis.label.save_state() basis.target = basis.copy().scale(scalar) basis.label.target = basis.label.copy() coord.target = coord.copy() new_label = VGroup(coord.target, basis.label.target) new_label.arrange(aligned_edge = DOWN) new_label.move_to( basis.label, aligned_edge = basis.get_center()-basis.label.get_center() ) new_label.shift( basis.target.get_center() - basis.get_center() ) coord.target.next_to(basis.label.target, LEFT) coord.target.set_fill(basis.get_color(), opacity = 1) self.play(*list(map(MoveToTarget, [ coord, basis, basis.label ]))) self.wait() self.play(*[ ApplyMethod(m.shift, basis_vectors[0].get_end()) for m in self.get_mobjects_from_last_animation() ]) if show_sum_vect: sum_vect = Vector( basis_vectors[1].get_end(), color = sum_vect_color ) self.play(ShowCreation(sum_vect)) self.wait(2) b1, b2 = basis_vectors self.jenny_plane.save_state() self.jenny.bubble.save_state() self.jenny.coords.target = self.jenny.coords.copy() self.you.bubble.add_content(self.jenny.coords.target) x, y = numerical_coords b1.target = self.i_hat.copy().scale(x) b2.target = self.j_hat.copy().scale(y) b2.target.shift(b1.target.get_end()) new_label1 = VGroup(coord_mobs[0], b1.label) new_label2 = VGroup(coord_mobs[1], b2.label) new_label1.target = new_label1.copy().next_to(b1.target, DOWN) new_label2.target = new_label2.copy().next_to(b2.target, LEFT) i_sym = TexMobject("\\hat{\\imath}").add_background_rectangle() j_sym = TexMobject("\\hat{\\jmath}").add_background_rectangle() i_sym.set_color(X_COLOR).move_to(new_label1.target[1], aligned_edge = LEFT) j_sym.set_color(Y_COLOR).move_to(new_label2.target[1], aligned_edge = LEFT) Transform(new_label1.target[1], i_sym).update(1) Transform(new_label2.target[1], j_sym).update(1) sum_vect.target = Vector(numerical_coords) self.play( Transform(self.jenny_plane, self.plane), Transform(self.jenny.bubble, self.you.bubble), self.you.change_mode, "speaking", self.jenny.change_mode, "erm", *list(map(MoveToTarget, [ self.jenny.coords, b1, b2, new_label1, new_label2, sum_vect ])) ) self.play(Blink(self.you)) self.wait() self.play(*it.chain( list(map(FadeOut, [ self.jenny.bubble, self.jenny.coords, coord_mobs, sum_vect ])), [ ApplyMethod(pi.change_mode, "plain") for pi in (self.jenny, self.you) ], [mob.restore for mob in (b1, b2, b1.label, b2.label)] )) self.jenny.bubble.restore() def how_we_label_her_basis(self): you, jenny = self.you, self.jenny b1_coords = Matrix(self.b1_coords) b2_coords = Matrix(self.b2_coords) for coords in b1_coords, b2_coords: coords.add_to_back(BackgroundRectangle(coords)) coords.scale(0.7) coords.add_to_back(BackgroundRectangle(coords)) you.bubble.add_content(coords) coords.mover = coords.copy() self.play(jenny.change_mode, "erm") self.play( ShowCreation(you.bubble), Write(b1_coords), you.change_mode, "speaking" ) self.play( b1_coords.mover.next_to, self.b1.get_end(), RIGHT, b1_coords.mover.set_color, X_COLOR ) self.play(Blink(you)) self.wait() self.play(Transform(b1_coords, b2_coords)) self.play( b2_coords.mover.next_to, self.b2.get_end(), LEFT, b2_coords.mover.set_color, Y_COLOR ) self.play(Blink(jenny)) for coords, array in (b1_coords, [1, 0]), (b2_coords, [0, 1]): mover = coords.mover array_mob = Matrix(array) array_mob.set_color(mover.get_color()) array_mob.set_height(mover.get_height()) array_mob.move_to(mover) array_mob.add_to_back(BackgroundRectangle(array_mob)) mover.target = array_mob self.play( self.jenny_plane.restore, FadeOut(self.you.bubble), FadeOut(b1_coords), self.jenny.change_mode, "speaking", self.you.change_mode, "confused", *list(map(Animation, [ self.basis_vectors, b1_coords.mover, b2_coords.mover, ])) ) self.play(MoveToTarget(b1_coords.mover)) self.play(MoveToTarget(b2_coords.mover)) self.play(Blink(self.jenny)) class SpeakingDifferentLanguages(JenniferScene): def construct(self): jenny, you = self.jenny, self.you title = TextMobject("Different languages") title.to_edge(UP) vector = Vector([3, 2]) vector.center().shift(DOWN) you.coords = Matrix([3, 2]) you.text = TextMobject("Looks to be") jenny.coords = Matrix(["5/3", "1/3"]) jenny.text = TextMobject("Non, c'est") for pi in jenny, you: pi.bubble = pi.get_bubble(SpeechBubble, width = 4.5, height = 3.5) if pi is you: pi.bubble.shift(MED_SMALL_BUFF*RIGHT) else: pi.coords.scale(0.8) pi.bubble.shift(MED_SMALL_BUFF*LEFT) pi.coords.next_to(pi.text, buff = MED_SMALL_BUFF) pi.coords.add(pi.text) pi.bubble.add_content(pi.coords) self.add(you, jenny) self.play(Write(title)) self.play( ShowCreation(vector), you.look_at, vector, jenny.look_at, vector, ) for pi in you, jenny: self.play( pi.change_mode, "speaking" if pi is you else "sassy", ShowCreation(pi.bubble), Write(pi.coords) ) self.play(Blink(pi)) self.wait() class ShowGrid(LinearTransformationScene): CONFIG = { "include_background_plane" : False, } def construct(self): self.remove(self.i_hat, self.j_hat) self.wait() self.plane.prepare_for_nonlinear_transform() self.plane.save_state() self.play(Homotopy(plane_wave_homotopy, self.plane)) self.play(self.plane.restore) for vect in self.i_hat, self.j_hat: self.play(ShowCreation(vect)) self.wait() class GridIsAConstruct(TeacherStudentsScene): def construct(self): self.teacher_says(""" \\centering The grid is just a construct """) self.change_student_modes(*["pondering"]*3) self.random_blink(2) class SpaceHasNoGrid(LinearTransformationScene): CONFIG = { "include_background_plane" : False } def construct(self): words = TextMobject("Space has no grid") words.to_edge(UP) self.play( Write(words), FadeOut(self.plane), *list(map(Animation, [self.i_hat, self.j_hat])) ) self.wait() class JennysGrid(JenniferScene): def construct(self): self.add(self.jenny) self.jenny.shift(3*RIGHT) bubble = self.jenny.get_bubble(SpeechBubble, width = 4) bubble.flip() bubble.set_fill(BLACK, opacity = 0.8) bubble.to_edge(LEFT) bubble.write(""" This grid is also just a construct """) coords = [1.5, -3] coords_mob = Matrix(coords) coords_mob.add_background_to_entries() bubble.position_mobject_inside(coords_mob) for vect in self.b1, self.b2: self.play( ShowCreation(vect), Write(vect.label) ) self.wait() self.play( ShowCreation( self.jenny_plane, run_time = 3, lag_ratio = 0.5 ), self.jenny.change_mode, "speaking", self.jenny.look_at, ORIGIN, ShowCreation(bubble), Write(bubble.content), Animation(self.basis_vectors) ) self.play(Blink(self.jenny)) self.play( FadeOut(bubble.content), FadeIn(coords_mob) ) self.show_linear_combination( numerical_coords = coords, basis_vectors = [self.b1, self.b2], coord_mobs = coords_mob.get_entries().copy(), show_sum_vect = True ) class ShowOriginOfGrid(JenniferScene): def construct(self): for plane in self.plane, self.jenny_plane: plane.fade(0.3) self.add(self.jenny_plane) self.jenny_plane.save_state() origin_word = TextMobject("Origin") origin_word.shift(2*RIGHT+2.5*UP) origin_word.add_background_rectangle() arrow = Arrow(origin_word, ORIGIN, color = RED) origin_dot = Dot(ORIGIN, radius = 0.1, color = RED) coords = Matrix([0, 0]) coords.add_to_back(BackgroundRectangle(coords)) coords.next_to(ORIGIN, DOWN+LEFT) vector = Vector([3, -2], color = PINK) self.play( Write(origin_word), ShowCreation(arrow) ) self.play(ShowCreation(origin_dot)) self.wait() self.play( Transform(self.jenny_plane, self.plane), *list(map(Animation, [origin_word, origin_dot, arrow])) ) self.wait() self.play(Write(coords)) self.wait() self.play(FadeIn(vector)) self.wait() self.play(Transform(vector, Mobject.scale(vector.copy(), 0))) self.wait() self.play( self.jenny_plane.restore, *list(map(Animation, [origin_word, origin_dot, arrow, coords])) ) for vect in self.b1, self.b2: self.play( ShowCreation(vect), Write(vect.label) ) self.wait() class AskAboutTranslation(TeacherStudentsScene): def construct(self): self.student_says( "\\centering How do you translate \\\\ between coordinate systems?", target_mode = "raise_right_hand" ) self.random_blink(3) class TranslateFromJenny(JenniferScene): CONFIG = { "coords" : [-1, 2] } def construct(self): self.add_players() self.ask_question() self.establish_coordinates() self.perform_arithmetic() def add_players(self): for plane in self.jenny_plane, self.plane: plane.fade() self.add( self.jenny_plane, self.jenny, self.you, self.basis_vectors ) self.jenny.coords = Matrix(self.coords) self.you.coords = Matrix(["?", "?"]) self.you.coords.get_entries().set_color_by_gradient(X_COLOR, Y_COLOR) for pi in self.jenny, self.you: pi.bubble = get_small_bubble(pi) pi.bubble.set_fill(BLACK, opacity = 0.8) pi.coords.scale(0.8) pi.coords.add_background_to_entries() pi.bubble.add_content(pi.coords) def ask_question(self): self.play( self.jenny.change_mode, "pondering", ShowCreation(self.jenny.bubble), Write(self.jenny.coords) ) coord_mobs = self.jenny.coords.get_entries().copy() self.basis_vectors_copy = self.basis_vectors.copy() self.basis_vectors_copy.fade(0.3) self.add(self.basis_vectors_copy, self.basis_vectors) sum_vect = self.show_linear_combination( numerical_coords = self.coords, basis_vectors = [self.b1, self.b2], coord_mobs = coord_mobs, revert_to_original = False, show_sum_vect = True, ) self.wait() everything = self.get_mobjects() for submob in self.jenny_plane.get_family(): everything.remove(submob) self.play( Transform(self.jenny_plane, self.plane), *list(map(Animation, everything)) ) self.play( self.you.change_mode, "confused", ShowCreation(self.you.bubble), Write(self.you.coords) ) self.wait() def establish_coordinates(self): b1, b2 = self.basis_vectors_copy[:2] b1_coords = Matrix(self.b1_coords).set_color(X_COLOR) b2_coords = Matrix(self.b2_coords).set_color(Y_COLOR) for coords in b1_coords, b2_coords: coords.scale(0.7) coords.add_to_back(BackgroundRectangle(coords)) b1_coords.next_to(b1.get_end(), RIGHT) b2_coords.next_to(b2.get_end(), UP) for coords in b1_coords, b2_coords: self.play(Write(coords)) self.b1_coords_mob, self.b2_coords_mob = b1_coords, b2_coords def perform_arithmetic(self): jenny_x, jenny_y = self.jenny.coords.get_entries().copy() equals, plus, equals2 = syms = list(map(TexMobject, list("=+="))) result = Matrix([-4, 1]) result.set_height(self.you.coords.get_height()) for mob in syms + [self.you.coords, self.jenny.coords, result]: mob.add_to_back(BackgroundRectangle(mob)) movers = [ self.you.coords, equals, jenny_x, self.b1_coords_mob, plus, jenny_y, self.b2_coords_mob, equals2, result ] for mover in movers: mover.target = mover.copy() mover_targets = VGroup(*[mover.target for mover in movers]) mover_targets.arrange() mover_targets.to_edge(UP) for mob in syms + [result]: mob.move_to(mob.target) mob.set_fill(BLACK, opacity = 0) mover_sets = [ [jenny_x, self.b1_coords_mob], [plus, jenny_y, self.b2_coords_mob], [self.you.coords, equals], ] for mover_set in mover_sets: self.play(*list(map(MoveToTarget, mover_set))) self.wait() self.play( MoveToTarget(equals2), Transform(self.b1_coords_mob.copy(), result.target), Transform(self.b2_coords_mob.copy(), result.target), ) self.remove(*self.get_mobjects_from_last_animation()) result = result.target self.add(equals2, result) self.wait() result_copy = result.copy() self.you.bubble.add_content(result_copy) self.play( self.you.change_mode, "hooray", Transform(result.copy(), result_copy) ) self.play(Blink(self.you)) self.wait() matrix = Matrix(np.array([self.b1_coords, self.b2_coords]).T) matrix.set_column_colors(X_COLOR, Y_COLOR) self.jenny.coords.target = self.jenny.coords.copy() self.jenny.coords.target.next_to(equals, LEFT) matrix.set_height(self.jenny.coords.get_height()) matrix.next_to(self.jenny.coords.target, LEFT) matrix.add_to_back(BackgroundRectangle(matrix)) self.play( FadeOut(self.jenny.bubble), FadeOut(self.you.coords), self.jenny.change_mode, "plain", MoveToTarget(self.jenny.coords), FadeIn(matrix) ) self.wait() class WatchChapter3(TeacherStudentsScene): def construct(self): self.teacher_says(""" You've all watched chapter 3, right? """) self.random_blink() self.play( self.get_students()[0].look, LEFT, self.get_students()[1].change_mode, "happy", self.get_students()[2].change_mode, "happy", ) self.random_blink(2) class TalkThroughChangeOfBasisMatrix(JenniferScene): def construct(self): self.add(self.plane, self.jenny, self.you) self.plane.fade() self.jenny_plane.fade() for pi in self.jenny, self.you: pi.bubble = get_small_bubble(pi) matrix = Matrix(np.array([self.b1_coords, self.b2_coords]).T) matrix.set_column_colors(X_COLOR, Y_COLOR) matrix.next_to(ORIGIN, RIGHT, buff = MED_SMALL_BUFF).to_edge(UP) b1_coords = Matrix(self.b1_coords) b1_coords.set_color(X_COLOR) b1_coords.next_to(self.b1.get_end(), RIGHT) b2_coords = Matrix(self.b2_coords) b2_coords.set_color(Y_COLOR) b2_coords.next_to(self.b2.get_end(), UP) for coords in b1_coords, b2_coords: coords.scale_in_place(0.7) basis_coords_pair = VGroup( Matrix([1, 0]).set_color(X_COLOR).scale(0.7), TexMobject(","), Matrix([0, 1]).set_color(Y_COLOR).scale(0.7), ) basis_coords_pair.arrange(aligned_edge = DOWN) self.you.bubble.add_content(basis_coords_pair) t_matrix1 = np.array([self.b1_coords, [0, 1]]) t_matrix2 = np.dot( self.cob_matrix(), np.linalg.inv(t_matrix1.T) ).T for mob in matrix, b1_coords, b2_coords: mob.rect = BackgroundRectangle(mob) mob.add_to_back(mob.rect) self.play(Write(matrix)) for vect in self.i_hat, self.j_hat: self.play( ShowCreation(vect), Write(vect.label) ) self.play( self.you.change_mode, "pondering", ShowCreation(self.you.bubble), Write(basis_coords_pair) ) self.play(Blink(self.you)) self.wait() self.add_foreground_mobject( self.jenny, self.you, self.you.bubble, basis_coords_pair, matrix ) matrix_copy = matrix.copy() matrix_copy.rect.set_fill(opacity = 0) self.apply_transposed_matrix( t_matrix1, added_anims = [ Transform(self.i_hat, self.b1), Transform(self.i_hat.label, self.b1.label), Transform(matrix_copy.rect, b1_coords.rect), Transform( matrix_copy.get_brackets(), b1_coords.get_brackets(), ), Transform( VGroup(*matrix_copy.get_mob_matrix()[:,0]), b1_coords.get_entries() ), ] ) self.remove(matrix_copy) self.add_foreground_mobject(b1_coords) matrix_copy = matrix.copy() matrix_copy.rect.set_fill(opacity = 0) self.apply_transposed_matrix( t_matrix2, added_anims = [ Transform(self.j_hat, self.b2), Transform(self.j_hat.label, self.b2.label), Transform(matrix_copy.rect, b2_coords.rect), Transform( matrix_copy.get_brackets(), b2_coords.get_brackets(), ), Transform( VGroup(*matrix_copy.get_mob_matrix()[:,1]), b2_coords.get_entries() ), ] ) self.remove(matrix_copy) self.add_foreground_mobject(b2_coords) basis_coords_pair.target = basis_coords_pair.copy() self.jenny.bubble.add_content(basis_coords_pair.target) self.wait() self.play( FadeOut(b1_coords), FadeOut(b2_coords), self.jenny.change_mode, "speaking", Transform(self.you.bubble, self.jenny.bubble), MoveToTarget(basis_coords_pair), ) class ChangeOfBasisExample(JenniferScene): CONFIG = { "v_coords" : [-1, 2] } def construct(self): self.add( self.plane, self.i_hat, self.j_hat, self.i_hat.label, self.j_hat.label, ) self.j_hat.label.next_to(self.j_hat, RIGHT) v = self.add_vector(self.v_coords) v_coords = Matrix(self.v_coords) v_coords.scale(0.8) v_coords.add_to_back(BackgroundRectangle(v_coords)) v_coords.to_corner(UP+LEFT) v_coords.add_background_to_entries() for pi in self.you, self.jenny: pi.change_mode("pondering") pi.bubble = get_small_bubble(pi) pi.bubble.add_content(v_coords.copy()) pi.add(pi.bubble, pi.bubble.content) start_words = TextMobject("How", "we", "think of") start_words.add_background_rectangle() start_group = VGroup(start_words, v_coords) start_group.arrange(buff = MED_SMALL_BUFF) start_group.next_to(self.you, LEFT, buff = 0) start_group.to_edge(UP) end_words = TextMobject("How", "Jennifer", "thinks of") end_words.add_background_rectangle() end_words.move_to(start_words, aligned_edge = RIGHT) self.play( Write(start_group), FadeIn(self.you), ) self.add_foreground_mobject(start_group, self.you) self.show_linear_combination( numerical_coords = self.v_coords, basis_vectors = [self.i_hat, self.j_hat], coord_mobs = v_coords.get_entries().copy(), ) self.play(*list(map(FadeOut, [self.i_hat.label, self.j_hat.label]))) self.apply_transposed_matrix(self.cob_matrix().T) VGroup(self.i_hat, self.j_hat).fade() self.add(self.b1, self.b2) self.play( Transform(start_words, end_words), Transform(self.you, self.jenny), *list(map(Write, [self.b1.label, self.b2.label])) ) self.play(Blink(self.you)) self.show_linear_combination( numerical_coords = self.v_coords, basis_vectors = [self.b1, self.b2], coord_mobs = v_coords.get_entries().copy(), ) class FeelsBackwards(Scene): def construct(self): matrix = Matrix(np.array([ JenniferScene.CONFIG["b1_coords"], JenniferScene.CONFIG["b2_coords"], ]).T) matrix.set_column_colors(X_COLOR, Y_COLOR) matrix.shift(UP) top_arrow = Arrow(matrix.get_left(), matrix.get_right()) bottom_arrow = top_arrow.copy().rotate(np.pi) top_arrow.next_to(matrix, UP, buff = LARGE_BUFF) bottom_arrow.next_to(matrix, DOWN, buff = LARGE_BUFF) top_arrow.set_color(BLUE) jenny_grid = TextMobject("Jennifer's grid").set_color(BLUE) our_grid = TextMobject("Our grid").set_color(BLUE) jenny_language = TextMobject("Jennifer's language") our_language = TextMobject("Our language") our_grid.next_to(top_arrow, LEFT) jenny_grid.next_to(top_arrow, RIGHT) jenny_language.next_to(bottom_arrow, RIGHT) our_language.next_to(bottom_arrow, LEFT) self.add(matrix) self.play(Write(our_grid)) self.play( ShowCreation(top_arrow), Write(jenny_grid) ) self.wait() self.play(Write(jenny_language)) self.play( ShowCreation(bottom_arrow), Write(our_language) ) self.wait() ##Swap things inverse_word = TextMobject("Inverse") inverse_word.next_to(matrix, LEFT, buff = MED_SMALL_BUFF) inverse_exponent = TexMobject("-1") inverse_exponent.next_to(matrix.get_corner(UP+RIGHT), RIGHT) self.play(*list(map(Write, [inverse_word, inverse_exponent]))) self.play( Swap(jenny_grid, our_grid), top_arrow.scale_in_place, 0.8, top_arrow.shift, 0.8*RIGHT, top_arrow.set_color, BLUE, ) self.play( Swap(jenny_language, our_language), bottom_arrow.scale_in_place, 0.8, bottom_arrow.shift, 0.8*RIGHT ) self.wait() class AskAboutOtherWayAround(TeacherStudentsScene): def construct(self): self.student_says(""" What about the other way around? """) self.random_blink(3) class RecallInverse(JenniferScene): def construct(self): numerical_t_matrix = np.array([self.b1_coords, self.b2_coords]) matrix = Matrix(numerical_t_matrix.T) matrix.add_to_back(BackgroundRectangle(matrix)) matrix.set_column_colors(X_COLOR, Y_COLOR) matrix.to_corner(UP+LEFT, buff = MED_LARGE_BUFF) # matrix.shift(MED_SMALL_BUFF*DOWN) inverse_exponent = TexMobject("-1") inverse_exponent.next_to(matrix.get_corner(UP+RIGHT), RIGHT) inverse_exponent.add_background_rectangle() brace = Brace(VGroup(matrix, inverse_exponent)) inverse_word = brace.get_text("Inverse") inverse_word.add_background_rectangle() equals = TexMobject("=") equals.add_background_rectangle() inv_matrix = Matrix([ ["1/3", "1/3"], ["-1/3", "2/3"] ]) inv_matrix.set_height(matrix.get_height()) inv_matrix.add_to_back(BackgroundRectangle(inv_matrix)) equals.next_to(matrix, RIGHT, buff = 0.7) inv_matrix.next_to(equals, RIGHT, buff = MED_SMALL_BUFF) self.add_foreground_mobject(matrix) self.apply_transposed_matrix(numerical_t_matrix) self.play( GrowFromCenter(brace), Write(inverse_word), Write(inverse_exponent) ) self.add_foreground_mobject(*self.get_mobjects_from_last_animation()) self.wait() self.apply_inverse_transpose(numerical_t_matrix) self.wait() self.play( Write(equals), Transform(matrix.copy(), inv_matrix) ) self.remove(*self.get_mobjects_from_last_animation()) self.add_foreground_mobject(equals, inv_matrix) self.wait() for mob in self.plane, self.i_hat, self.j_hat: self.add(mob.copy().fade(0.7)) self.apply_transposed_matrix(numerical_t_matrix) self.play(FadeIn(self.jenny)) self.play(self.jenny.change_mode, "speaking") #Little hacky now inv_matrix.set_column_colors(X_COLOR) self.play(*[ ApplyMethod( mob.scale_in_place, 1.2, rate_func = there_and_back ) for mob in inv_matrix.get_mob_matrix()[:,0] ]) self.wait() inv_matrix.set_column_colors(X_COLOR, Y_COLOR) self.play(*[ ApplyMethod( mob.scale_in_place, 1.2, rate_func = there_and_back ) for mob in inv_matrix.get_mob_matrix()[:,1] ]) self.wait() class WorkOutInverseComputation(Scene): def construct(self): our_vector = Matrix([3, 2]) her_vector = Matrix(["5/3", "1/3"]) matrix = Matrix([["1/3", "1/3"], ["-1/3", "2/3"]]) our_vector.set_color(BLUE_D) her_vector.set_color(MAROON_B) equals = TexMobject("=") equation = VGroup( matrix, our_vector, equals, her_vector ) for mob in equation: if isinstance(mob, Matrix): mob.set_height(2) equation.arrange() matrix_brace = Brace(matrix, UP) our_vector_brace = Brace(our_vector) her_vector_brace = Brace(her_vector, UP) matrix_text = matrix_brace.get_text(""" \\centering Inverse change of basis matrix """) our_text = our_vector_brace.get_text(""" \\centering Written in our language """) our_text.set_color(our_vector.get_color()) her_text = her_vector_brace.get_text(""" \\centering Same vector in her language """) her_text.set_color(her_vector.get_color()) for text in our_text, her_text: text.scale_in_place(0.7) self.add(our_vector) self.play( GrowFromCenter(our_vector_brace), Write(our_text) ) self.wait() self.play( FadeIn(matrix), GrowFromCenter(matrix_brace), Write(matrix_text) ) self.wait() self.play( Write(equals), Write(her_vector) ) self.play( GrowFromCenter(her_vector_brace), Write(her_text) ) self.wait() class SoThatsTranslation(TeacherStudentsScene): def construct(self): self.teacher_says("So that's translation") self.random_blink(3) class SummarizeTranslationProcess(Scene): def construct(self): self.define_matrix() self.show_translation() def define_matrix(self): matrix = Matrix([[2, -1], [1, 1]]) matrix.set_column_colors(X_COLOR, Y_COLOR) A, equals = list(map(TexMobject, list("A="))) equation = VGroup(A, equals, matrix) equation.arrange() equation.to_corner(UP+LEFT) equation.shift(RIGHT) words = TextMobject(""" Jennifer's basis vectors, written in our coordinates """) words.to_edge(LEFT) mob_matrix = matrix.get_mob_matrix() arrow1 = Arrow(words, mob_matrix[1, 0], color = X_COLOR) arrow2 = Arrow(words, mob_matrix[1, 1], color = Y_COLOR) self.add(A, equals, matrix) self.play( Write(words), *list(map(ShowCreation, [arrow1, arrow2])) ) self.A_copy = A.copy() def show_translation(self): our_vector = Matrix(["x_o", "y_o"]) her_vector = Matrix(["x_j", "y_j"]) for vector, color in (our_vector, BLUE_D), (her_vector, MAROON_B): # vector.set_height(1.5) vector.set_color(color) A = TexMobject("A") A_inv = TexMobject("A^{-1}") equals = TexMobject("=") equation = VGroup(A, her_vector, equals, our_vector) equation.arrange() equation.to_edge(RIGHT) equation.shift(0.5*UP) A_inv.next_to(our_vector, LEFT) her_words = TextMobject("Vector in her coordinates") her_words.set_color(her_vector.get_color()) her_words.scale(0.8).to_corner(UP+RIGHT) her_arrow = Arrow( her_words, her_vector, color = her_vector.get_color() ) our_words = TextMobject("Same vector in\\\\ our coordinates") our_words.set_color(our_vector.get_color()) our_words.scale(0.8).to_edge(RIGHT).shift(2*DOWN) our_words.shift_onto_screen() our_arrow = Arrow( our_words.get_top(), our_vector.get_bottom(), color = our_vector.get_color() ) self.play( Write(equation), Transform(self.A_copy, A) ) self.remove(self.A_copy) self.play( Write(her_words), ShowCreation(her_arrow) ) self.play( Write(our_words), ShowCreation(our_arrow) ) self.wait(2) self.play( VGroup(her_vector, equals).next_to, A_inv, LEFT, her_arrow.rotate_in_place, -np.pi/6, her_arrow.shift, MED_SMALL_BUFF*LEFT, Transform(A, A_inv, path_arc = np.pi) ) self.wait() class VectorsAreNotTheOnlyOnes(TeacherStudentsScene): def construct(self): self.teacher_says(""" \\centering Vectors aren't the only thing with coordinates """) self.change_student_modes("pondering", "confused", "erm") self.random_blink(3) class Prerequisites(Scene): def construct(self): title = TextMobject("Prerequisites") title.to_edge(UP) h_line = Line(LEFT, RIGHT).scale(FRAME_X_RADIUS) h_line.next_to(title, DOWN) self.add(title, h_line) prereqs = list(map(TextMobject, [ "Linear transformations", "Matrix multiplication", ])) for direction, words in zip([LEFT, RIGHT], prereqs): rect = Rectangle(height = 9, width = 16) rect.set_height(3.5) rect.next_to(ORIGIN, direction, buff = MED_SMALL_BUFF) rect.set_color(BLUE) words.next_to(rect, UP, buff = MED_SMALL_BUFF) self.play( Write(words), ShowCreation(rect) ) self.wait() class RotationExample(LinearTransformationScene): CONFIG = { "t_matrix" : [[0, 1], [-1, 0]] } def construct(self): words = TextMobject("$90^\\circ$ rotation") words.scale(1.2) words.add_background_rectangle() words.to_edge(UP) matrix = Matrix(self.t_matrix.T) matrix.set_column_colors(X_COLOR, Y_COLOR) matrix.rect = BackgroundRectangle(matrix) matrix.add_to_back(matrix.rect) matrix.next_to(words, DOWN) matrix.shift(2*RIGHT) self.play(Write(words)) self.add_foreground_mobject(words) self.wait() self.apply_transposed_matrix(self.t_matrix) self.wait() self.play( self.i_hat.rotate, np.pi/12, self.j_hat.rotate, -np.pi/12, rate_func = wiggle, run_time = 2 ) self.wait() i_coords, j_coords = coord_arrays = list(map(Matrix, self.t_matrix)) for coords, vect in zip(coord_arrays, [self.i_hat, self.j_hat]): coords.scale(0.7) coords.rect = BackgroundRectangle(coords) coords.add_to_back(coords.rect) coords.set_color(vect.get_color()) direction = UP if vect is self.j_hat else RIGHT coords.next_to(vect.get_end(), direction, buff = MED_SMALL_BUFF) self.play(Write(coords)) self.wait() self.play( Transform(i_coords.rect, matrix.rect), Transform(i_coords.get_brackets(), matrix.get_brackets()), Transform( i_coords.get_entries(), VGroup(*matrix.get_mob_matrix()[:, 0]) ), ) self.play( FadeOut(j_coords.rect), FadeOut(j_coords.get_brackets()), Transform( j_coords.get_entries(), VGroup(*matrix.get_mob_matrix()[:, 1]) ), ) self.wait() self.add_words(matrix) def add_words(self, matrix): follow_basis = TextMobject( "Follow", "our choice", "\\\\ of basis vectors" ) follow_basis.set_color_by_tex("our choice", YELLOW) follow_basis.add_background_rectangle() follow_basis.next_to( matrix, LEFT, buff = MED_SMALL_BUFF, ) record = TextMobject( "Record using \\\\", "our coordinates" ) record.set_color_by_tex("our coordinates", YELLOW) record.add_background_rectangle() record.next_to( matrix, DOWN, buff = MED_SMALL_BUFF, aligned_edge = LEFT ) self.play(Write(follow_basis)) self.wait() self.play(Write(record)) self.wait() class JennyWatchesRotation(JenniferScene): def construct(self): jenny = self.jenny self.add(self.jenny_plane.copy().fade()) self.add(self.jenny_plane) self.add(jenny) for vect in self.b1, self.b2: self.add_vector(vect) matrix = Matrix([["?", "?"], ["?", "?"]]) matrix.get_entries().set_color_by_gradient(X_COLOR, Y_COLOR) jenny.bubble = get_small_bubble(jenny) jenny.bubble.add_content(matrix) matrix.scale_in_place(0.8) self.play( jenny.change_mode, "sassy", ShowCreation(jenny.bubble), Write(matrix) ) self.play(*it.chain( [ Rotate(mob, np.pi/2, run_time = 3) for mob in (self.jenny_plane, self.b1, self.b2) ], list(map(Animation, [jenny, jenny.bubble, matrix])) )) self.play(jenny.change_mode, "pondering") self.play(Blink(jenny)) self.wait() class AksAboutTranslatingColumns(TeacherStudentsScene): def construct(self): matrix = Matrix([[0, -1], [1, 0]]) matrix.set_column_colors(X_COLOR, Y_COLOR) matrix.scale(0.7) words = TextMobject("Translate columns of") matrix.next_to(words, DOWN) words.add(matrix) self.student_says(words, student_index = 0) self.random_blink(2) student = self.get_students()[0] bubble = get_small_bubble(student) bubble.set_fill(opacity = 0) matrix.target = matrix.copy() bubble.add_content(matrix.target) self.play( Transform(student.bubble, bubble), FadeOut(student.bubble.content), MoveToTarget(matrix.copy()), student.change_mode, "pondering", ) self.remove(student.bubble) student.bubble = None self.add(bubble, matrix.target) self.random_blink() words = TextMobject( "\\centering Those columns still \\\\ represent ", "our basis", ", not ", "hers", arg_separator = "" ) words.set_color_by_tex("our basis", BLUE) words.set_color_by_tex("hers", MAROON_B) self.teacher_says(words) self.change_student_modes("erm", "pondering", "pondering") self.random_blink() class HowToTranslateAMatrix(Scene): def construct(self): self.add_title() arrays = VGroup(*list(map(Matrix, [ [["1/3", "-2/3"], ["5/3", "-1/3"]], [-1, 2], [[2, -1], [1, 1]], [[0, -1], [1, 0]], [[2, -1], [1, 1]], ]))) result, her_vector, cob_matrix, transform, inv_cob = arrays neg_1 = TexMobject("-1") neg_1.next_to(inv_cob.get_corner(UP+RIGHT), RIGHT) inv_cob.add(neg_1) arrays.arrange(LEFT) arrays.to_edge(LEFT, buff = LARGE_BUFF/2.) for array in arrays: array.brace = Brace(array) array.top_brace = Brace(VGroup(array, her_vector), UP) for array in cob_matrix, inv_cob: submobs = array.split() submobs.sort(key=lambda m: m.get_center()[0]) array.submobjects = submobs her_vector.set_color(MAROON_B) cob_matrix.set_color_by_gradient(BLUE, MAROON_B) transform.set_column_colors(X_COLOR, Y_COLOR) transform.get_brackets().set_color(BLUE) inv_cob.set_color_by_gradient(MAROON_B, BLUE) result.set_column_colors(X_COLOR, Y_COLOR) result.get_brackets().set_color(MAROON_B) final_top_brace = Brace(VGroup(cob_matrix, inv_cob), UP) brace_text_pairs = [ (her_vector.brace, ("Vector in \\\\", "Jennifer's language")), (her_vector.top_brace, ("",)), (cob_matrix.brace, ("Change of basis \\\\", "matrix")), (cob_matrix.top_brace, ("Same vector \\\\", "in", "our", "language")), (transform.brace, ("Transformation matrix \\\\", "in", "our", "language")), (transform.top_brace, ("Transformed vector \\\\", "in", "our", "language")), (inv_cob.brace, ("Inverse \\\\", "change of basis \\\\", "matrix")), (inv_cob.top_brace, ("Transformed vector \\\\", "in", "her", "language")), (final_top_brace, ("Transformation matrix \\\\", "in", "her", "language")) ] for brace, text_args in brace_text_pairs: text_args = list(text_args) text_args[0] = "\\centering " + text_args[0] text = TextMobject(*text_args) text.set_color_by_tex("our", BLUE) text.set_color_by_tex("her", MAROON_B) brace.put_at_tip(text) brace.text = text brace = her_vector.brace bottom_words = her_vector.brace.text top_brace = cob_matrix.top_brace top_words = cob_matrix.top_brace.text def introduce(array): self.play( Write(array), Transform(brace, array.brace), Transform(bottom_words, array.brace.text) ) self.wait() def echo_introduce(array): self.play( Transform(top_brace, array.top_brace), Transform(top_words, array.top_brace.text) ) self.wait() self.play(Write(her_vector)) self.play( GrowFromCenter(brace), Write(bottom_words) ) self.wait() introduce(cob_matrix) self.play( GrowFromCenter(top_brace), Write(top_words) ) self.wait() introduce(transform) echo_introduce(transform) introduce(inv_cob), echo_introduce(inv_cob) #Genearlize to single matrix v = TexMobject("\\vec{\\textbf{v}}") v.set_color(her_vector.get_color()) v.move_to(her_vector, aligned_edge = LEFT) self.play( Transform(her_vector, v), FadeOut(bottom_words), FadeOut(brace), ) self.wait() self.play( Transform(top_brace, final_top_brace), Transform(top_brace.text, final_top_brace.text), ) self.wait() equals = TexMobject("=") equals.replace(v) result.next_to(equals, RIGHT) self.play( Transform(her_vector, equals), Write(result) ) self.wait(2) everything = VGroup(*self.get_mobjects()) self.play( FadeOut(everything), result.to_corner, UP+LEFT ) self.add(result) self.wait() def add_title(self): title = TextMobject("How to translate a matrix") title.to_edge(UP) h_line = Line(LEFT, RIGHT).scale(FRAME_X_RADIUS) h_line.next_to(title, DOWN) self.add(title) self.play(ShowCreation(h_line)) self.wait() class JennyWatchesRotationWithMatrixAndVector(JenniferScene): def construct(self): self.add(self.jenny_plane.copy().fade(0.8)) self.add(self.jenny_plane, self.jenny, self.b1, self.b2) matrix = Matrix([["1/3", "-2/3"], ["5/3", "-1/3"]]) matrix.set_column_colors(X_COLOR, Y_COLOR) matrix.to_corner(UP+LEFT) vector_coords = [1, 2] vector_array = Matrix(vector_coords) vector_array.set_color(YELLOW) vector_array.next_to(matrix, RIGHT) result = Matrix([-1, 1]) equals = TexMobject("=") equals.next_to(vector_array) result.next_to(equals) for array in matrix, vector_array, result: array.add_to_back(BackgroundRectangle(array)) vector = Vector(np.dot(self.cob_matrix(), vector_coords)) self.add(matrix) self.play(Write(vector_array)) self.play(ShowCreation(vector)) self.play(Blink(self.jenny)) self.play(*it.chain( [ Rotate(mob, np.pi/2, run_time = 3) for mob in (self.jenny_plane, self.b1, self.b2, vector) ], list(map(Animation, [self.jenny, matrix, vector_array])), )) self.play( self.jenny.change_mode, "pondering", Write(equals), Write(result) ) self.play(Blink(self.jenny)) self.wait() class MathematicalEmpathy(TeacherStudentsScene): def construct(self): words = TextMobject( "\\centering An expression like", "$A^{-1} M A$", "\\\\ suggests a mathematical \\\\", "sort of empathy" ) A1, neg, one, M, A2 = words[1] As = VGroup(A1, neg, one, A2) VGroup(As, M).set_color(YELLOW) self.teacher_says(words) self.random_blink() for mob, color in (M, BLUE), (As, MAROON_B): self.play(mob.set_color, color) self.play(mob.scale_in_place, 1.2, rate_func = there_and_back) self.random_blink(2) class NextVideo(Scene): def construct(self): title = TextMobject(""" Next video: Eigenvectors and eigenvalues """) title.to_edge(UP, buff = MED_SMALL_BUFF) 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()