diff --git a/eoc/chapter7.py b/eoc/chapter7.py index abc1af87..40911aae 100644 --- a/eoc/chapter7.py +++ b/eoc/chapter7.py @@ -104,36 +104,52 @@ class ThisVideo(TeacherStudentsScene): self.change_student_modes(*["happy"]*3) self.dither(2) -class ApproachWordToLim(PiCreatureScene): +class LimitJustMeansApproach(PiCreatureScene): CONFIG = { - "dx_color" : GREEN + "dx_color" : GREEN, + "max_num_zeros" : 7, } def construct(self): limit_expression = self.get_limit_expression() - limit_expression.next_to( - self.pi_creature, LEFT, aligned_edge = UP - ) + limit_expression.shift(2*LEFT) + limit_expression.to_edge(UP) evaluated_expressions = self.get_evaluated_expressions() - evaluated_expressions.to_edge(UP) + evaluated_expressions.next_to(limit_expression, DOWN, buff = LARGE_BUFF) brace = Brace(evaluated_expressions[0][-1], DOWN) question = TextMobject("What does this ``approach''?") question.next_to(brace, DOWN) - expression = evaluated_expressions[0] - self.add(expression, brace, question) - self.change_mode("raise_right_hand") - for next_expression in evaluated_expressions[1:]: - next_expression.move_to(expression, RIGHT) - self.play(Transform(expression, next_expression)) - self.dither(0.5) - self.play( - Write(limit_expression), - self.pi_creature.change_mode, "pondering" + point = VectorizedPoint(limit_expression.get_right()) + expression = VGroup( + limit_expression[1].copy(), + point, point.copy() ) - self.play(Indicate(limit_expression[0])) + self.add(limit_expression) + self.change_mode("raise_right_hand") + for next_expression in evaluated_expressions: + next_expression.move_to(evaluated_expressions[0], RIGHT) + self.play( + Transform( + expression, next_expression, + submobject_mode = "lagged_start", + lag_factor = 1.2, + ), + self.pi_creature.look_at, next_expression[-1] + ) + if brace not in self.get_mobjects(): + self.play( + GrowFromCenter(brace), + Write(question) + ) + self.dither(0.5) self.dither(2) + def create_pi_creature(self): + self.pi_creature = Mortimer().flip() + self.pi_creature.to_corner(DOWN+LEFT) + return self.pi_creature + def get_limit_expression(self): lim = TexMobject("\\lim_", "{dx", " \\to 0}") lim.highlight_by_tex("dx", self.dx_color) @@ -144,7 +160,7 @@ class ApproachWordToLim(PiCreatureScene): def get_evaluated_expressions(self): result = VGroup() - for num_zeros in range(1, 6): + for num_zeros in range(1, self.max_num_zeros+1): dx_str = "0." + "0"*num_zeros + "1" expression = self.get_expression(dx_str) dx = float(dx_str) @@ -165,7 +181,7 @@ class ApproachWordToLim(PiCreatureScene): class RefreshOnDerivativeDefinition(GraphScene): CONFIG = { "start_x" : 2, - "dx" : 0.7, + "start_dx" : 0.7, "df_color" : YELLOW, "dx_color" : GREEN, "secant_line_color" : MAROON_B, @@ -183,11 +199,12 @@ class RefreshOnDerivativeDefinition(GraphScene): line_class = DashedLine, color = RED ) - for nudge in 0, self.dx + for nudge in 0, self.start_dx ] + nudged_x_v_line.save_state() ss_group = self.get_secant_slope_group( self.start_x, graph, - dx = self.dx, + dx = self.start_dx, dx_label = "dx", df_label = "df", df_line_color = self.df_color, @@ -204,6 +221,7 @@ class RefreshOnDerivativeDefinition(GraphScene): dx = derivative.get_part_by_tex("dx") input_x = derivative.get_part_by_tex(str(self.start_x)) derivative.move_to(self.coords_to_point(7, 4)) + derivative.save_state() deriv_brace = Brace(derivative) dx_to_0 = TexMobject("dx", "\\to 0") dx_to_0.highlight_by_tex("dx", self.dx_color) @@ -278,7 +296,7 @@ class RefreshOnDerivativeDefinition(GraphScene): self.animate_secant_slope_group_change( ss_group, - target_dx = self.dx, + target_dx = self.start_dx, run_time = 2 ) self.play(ShowCreation(nudged_x_v_line)) @@ -323,6 +341,437 @@ class RefreshOnDerivativeDefinition(GraphScene): ) self.dither(2) + #Record attributes for DiscussLowercaseDs below + digest_locals(self) + +class RantOpenAndClose(Scene): + def construct(self): + pass + +class DiscussLowercaseDs(RefreshOnDerivativeDefinition, PiCreatureScene, ZoomedScene): + CONFIG = { + "zoomed_canvas_corner" : UP+LEFT + } + def construct(self): + self.skip_superclass_anims() + self.replace_dx_terms() + self.compare_rhs_and_lhs() + self.h_is_finite() + + def skip_superclass_anims(self): + self.remove(self.pi_creature) + self.force_skipping() + RefreshOnDerivativeDefinition.construct(self) + self.revert_to_original_skipping_status() + self.animate_secant_slope_group_change( + self.ss_group, target_dx = self.start_dx, + added_anims = [ + self.nudged_x_v_line.restore, + Animation(self.ss_group.df_line) + ], + run_time = 1 + ) + everything = self.get_top_level_mobjects() + everything.remove(self.derivative) + self.play(*[ + ApplyMethod(mob.shift, 2.5*LEFT) + for mob in everything + ] + [ + FadeIn(self.pi_creature) + ]) + + def replace_dx_terms(self): + dx_list = [self.dx_to_0[0]] + dx_list += self.new_deriv.get_parts_by_tex("dx") + mover = dx_list[0] + mover_scale_val = 1.5 + mover.initial_right = mover.get_right() + + self.play( + mover.scale, mover_scale_val, + mover.next_to, self.pi_creature.get_corner(UP+LEFT), + UP, MED_SMALL_BUFF, + self.pi_creature.change_mode, "sassy", + path_arc = np.pi/2, + ) + self.blink() + self.dither() + for tex in "\\Delta x", "h": + dx_list_replacement = [ + TexMobject( + tex + ).highlight(self.dx_color).move_to(dx, DOWN) + for dx in dx_list + ] + self.play( + Transform( + VGroup(*dx_list), + VGroup(*dx_list_replacement), + ), + self.pi_creature.change_mode, "raise_right_hand" + ) + self.dither() + self.play( + mover.scale, 0.9, + mover.move_to, mover.initial_right, RIGHT, + self.pi_creature.change_mode, "happy", + ) + self.play( + self.dx_to_0.next_to, self.lim, DOWN, SMALL_BUFF, + ) + self.dither() + + def compare_rhs_and_lhs(self): + self.derivative.restore() + lhs = self.derivative + equals = TexMobject("=") + rhs = VGroup(self.lim, self.dx_to_0, self.new_deriv) + rhs.generate_target() + rhs.target.next_to(self.pi_creature, UP, MED_LARGE_BUFF) + rhs.target.to_edge(RIGHT) + equals.next_to(rhs.target, LEFT) + lhs.next_to(equals, LEFT) + + d_circles = VGroup(*[ + Circle(color = BLUE_B).replace( + lhs.get_part_by_tex(tex)[0], + stretch = True, + ).scale_in_place(1.5).rotate_in_place(-np.pi/12) + for tex in "df", "dx" + ]) + d_words = TextMobject(""" + Limit idea is + built in + """) + d_words.next_to(d_circles, DOWN) + d_words.highlight(d_circles[0].get_color()) + + lhs_rect, rhs_rect = rects = [ + Rectangle(color = GREEN_B).replace( + mob, stretch = True + ) + for mob in lhs, rhs.target + ] + for rect in rects: + rect.stretch_to_fit_width(rect.get_width()+2*MED_SMALL_BUFF) + rect.stretch_to_fit_height(rect.get_height()+2*MED_SMALL_BUFF) + formal_definition_words = TextMobject(""" + Formal derivative definition + """) + formal_definition_words.scale_to_fit_width(rhs_rect.get_width()) + formal_definition_words.next_to(rhs_rect, UP) + formal_definition_words.highlight(rhs_rect.get_color()) + formal_definition_words.add_background_rectangle() + + df = VGroup(lhs.get_part_by_tex("df")) + df_target = VGroup(*self.new_deriv.get_parts_by_tex("f")) + + self.play( + MoveToTarget(rhs), + Write(lhs), + Write(equals), + ) + self.play( + ShowCreation(d_circles, run_time = 2), + self.pi_creature.change_mode, "pondering" + ) + self.play(Write(d_words)) + self.animate_secant_slope_group_change( + self.ss_group, target_dx = 0.01, + added_anims = [ + Transform( + self.nudged_x_v_line, self.start_x_v_line, + run_time = 3 + ) + ] + ) + self.change_mode("thinking") + self.dither(2) + self.play( + ShowCreation(lhs_rect), + FadeOut(d_circles), + FadeOut(d_words), + ) + self.dither(2) + self.play( + ReplacementTransform(lhs_rect, rhs_rect), + self.pi_creature.change_mode, "raise_right_hand" + ) + self.dither(2) + self.play(ReplacementTransform( + df.copy(), df_target, + path_arc = -np.pi/2, + run_time = 2 + )) + self.dither(2) + self.play(Indicate( + VGroup(*rhs[:2]), + run_time = 2 + )) + self.dither() + + self.play(Write(formal_definition_words)) + self.play( + self.pi_creature.change_mode, "happy", + self.pi_creature.look_at, formal_definition_words + ) + self.dither(2) + + lhs.add_background_rectangle() + self.add(rhs_rect, rhs) + self.definition_group = VGroup( + lhs, equals, rhs_rect, rhs, formal_definition_words + ) + self.lhs, self.rhs, self.rhs_rect = lhs, rhs, rhs_rect + + def h_is_finite(self): + self.play( + FadeOut(self.graph_label), + self.definition_group.center, + self.definition_group.to_corner, UP+RIGHT, + self.pi_creature.change_mode, "sassy", + self.pi_creature.look_at, 4*UP + ) + self.dither() + + + words = TextMobject("No ``infinitely small''") + words.next_to( + self.definition_group, DOWN, + buff = LARGE_BUFF, + ) + arrow = Arrow(words.get_top(), self.rhs_rect.get_bottom()) + arrow.highlight(WHITE) + + h_group = VGroup( + self.rhs[1].get_part_by_tex("dx"), + *self.rhs[2].get_parts_by_tex("dx") + ) + moving_h = h_group[0] + moving_h.original_center = moving_h.get_center() + dx_group = VGroup() + for h in h_group: + dx = TexMobject("dx") + dx.highlight(h.get_color()) + dx.replace(h, dim_to_match = 1) + dx_group.add(dx) + moving_dx = dx_group[0] + + self.play(Write(words), ShowCreation(arrow)) + self.dither(2) + + self.play( + moving_h.next_to, self.pi_creature.get_corner(UP+RIGHT), UP, + self.pi_creature.change_mode, "raise_left_hand", + ) + self.dither() + moving_dx.move_to(moving_h) + h_group.save_state() + self.play(Transform( + h_group, dx_group, + path_arc = np.pi, + )) + self.dither(2) + self.play(h_group.restore, path_arc = np.pi) + self.play( + moving_h.move_to, moving_h.original_center, + self.pi_creature.change_mode, "plain" + ) + self.dither() + + self.activate_zooming() + lil_rect = self.little_rectangle + lil_rect.move_to(self.ss_group) + lil_rect.scale_in_place(3) + lil_rect.save_state() + self.dither() + self.add(self.rhs) + self.play( + lil_rect.scale_to_fit_width, + self.ss_group.dx_line.get_width()*4, + run_time = 4 + ) + self.dither() + dx = self.ss_group.dx_label + dx.save_state() + h = TexMobject("h") + h.highlight(dx.get_color()) + h.replace(dx, dim_to_match = 1) + self.play(Transform(dx, h, path_arc = np.pi)) + self.play(Indicate(dx)) + self.dither() + self.play(dx.restore, path_arc = np.pi) + self.play(lil_rect.restore, run_time = 4) + self.dither() + self.disactivate_zooming() + +class OtherViewsOfDx(TeacherStudentsScene): + def construct(self): + definition = TexMobject( + "{df", "\\over \\,", "dx}", "(", "2", ")", "=", + "\\lim", "_{h", "\\to", "0}", + "{f", "(", "2", "+", "h", ")", "-", "f", "(", "2", ")", + "\\over \\,", "h}" + ) + tex_to_color = { + "df" : YELLOW, + "f" : YELLOW, + "dx" : GREEN, + "h" : GREEN, + "2" : RED + } + for tex, color in tex_to_color.items(): + definition.highlight_by_tex(tex, color) + definition.scale(0.8) + definition.to_corner(UP+LEFT) + dx_group = VGroup(*definition.get_parts_by_tex("dx")) + h_group = VGroup(*definition.get_parts_by_tex("h")) + self.add(definition) + + statements = [ + TextMobject(*args) + for args in [ + ("Why the new \\\\ variable", "$h$", "?"), + ("$dx$", "is more $\\dots$ contentious.") + ] + ] + for statement in statements: + statement.h, statement.dx = [ + VGroup(*statement.get_parts_by_tex( + tex, substring = False + )).highlight(GREEN) + for tex in "$h$", "$dx$" + ] + + + self.force_skipping() + self.student_says( + statements[0], + student_index = 1, + target_mode = "confused" + ) + self.play(ReplacementTransform( + statements[0].h.copy(), h_group, + run_time = 2, + submobject_mode = "lagged_start", + lag_factor = 1.5, + )) + self.dither() + self.revert_to_original_skipping_status()## + self.teacher_says( + statements[1], + target_mode = "hesitant", + ) + self.play(ReplacementTransform( + statements[1].dx.copy(), dx_group, + run_time = 2 + )) + self.dither() + + + +class GraphLimitExpression(GraphScene): + CONFIG = { + "start_x" : 2, + "h_color" : GREEN, + "f_color" : YELLOW, + "start_x_color" : RED, + "graph_origin" : 3*DOWN, + "x_min" : -5, + "x_max" : 5, + "x_axis_label" : "$h$", + "x_labeled_nums" : range(-5, 6), + "y_min" : 0, + "y_max" : 20, + "y_tick_frequency" : 1, + "y_labeled_nums" : range(5, 25, 5), + "y_axis_label" : "", + } + def construct(self): + self.force_skipping() + + def func(h): + return 3*(2**2) + 3*2*h + h**2 + + self.setup_axes() + self.introduce_limit_term() + self.show_graph() + self.emphasize_non_definedness_at_0() + self.point_out_limit_point() + self.show_epsilon_delta_intuition() + self.limits_as_a_language() + + def introduce_limit_term(self): + abstract_limit = TexMobject( + "\\lim", "_{h", "\\to 0}", "=", + "{f", "(", str(self.start_x), "+", "h", ")", + "-", "f", "(", str(self.start_x), ")", + "\\over \\,", "h}", + arg_separator = "", + ) + cube_limit = TexMobject( + "\\lim", "_{h", "\\to 0}", "=", + "{(", str(self.start_x), "+", "h", ")", "^3", + "-", "(", str(self.start_x), ")", "^3", + "\\over \\,", "h}", + arg_separator = "", + ) + tex_to_color = { + "h" : self.h_color, + "f" : self.f_color, + "3" : self.f_color, + str(self.start_x) : self.start_x_color + } + for expression in abstract_limit, cube_limit: + for tex, color in tex_to_color.items(): + expression.highlight_by_tex(tex, color) + expression.next_to(ORIGIN, RIGHT, LARGE_BUFF) + expression.to_edge(UP) + + brace = Brace(VGroup(*abstract_limit[4:]), DOWN) + graph_this = brace.get_text("Graph this") + + self.revert_to_original_skipping_status() + self.add(abstract_limit) + self.play( + GrowFromCenter(brace), + Write(graph_this) + ) + self.dither() + self.play(*[ + ReplacementTransform( + VGroup(*abstract_limit.get_parts_by_tex(tex)), + VGroup(*cube_limit.get_parts_by_tex( + tex if tex is not "f" else "3" + )), + run_time = 2, + ) + for tex in [ + "lim", "h", "to", "=", "f", "(", + str(self.start_x), "+", ")", "-", "over" + ] + ]) + self.dither() + for part in cube_limit.get_parts_by_tex("2"): + self.play(Indicate(part)) + self.dither(2) + + def show_graph(self): + pass + + def emphasize_non_definedness_at_0(self): + pass + + def point_out_limit_point(self): + pass + + def show_epsilon_delta_intuition(self): + pass + + def limits_as_a_language(self): + pass + + diff --git a/scene/zoomed_scene.py b/scene/zoomed_scene.py index 216fa404..20461be4 100644 --- a/scene/zoomed_scene.py +++ b/scene/zoomed_scene.py @@ -129,7 +129,6 @@ class ZoomedScene(Scene): ) if self.zoom_activated and self.little_rectangle in moving_mobjects: # When the camera is moving, so is everything, - mobjects = self.get_mobjects() return self.get_mobjects(), [] else: return moving_mobjects, static_mobjects diff --git a/topics/characters.py b/topics/characters.py index 543729b1..b4751e30 100644 --- a/topics/characters.py +++ b/topics/characters.py @@ -413,10 +413,10 @@ class PiCreatureScene(Scene): *content, bubble_class = bubble_class, bubble_kwargs = bubble_kwargs, - target_mode = target_mode + target_mode = target_mode, + **kwargs ), - *added_anims, - **kwargs + *added_anims ) def pi_creature_says(self, pi_creature, *content, **kwargs):