Files
manim/old_projects/eoc/chapter6.py
2018-08-15 17:30:24 -07:00

2728 lines
82 KiB
Python

from big_ol_pile_of_manim_imports import *
SPACE_UNIT_TO_PLANE_UNIT = 0.75
class Chapter6OpeningQuote(OpeningQuote):
CONFIG = {
"quote" : [
"Do not ask whether a ",
"statement is true until",
"you know what it means."
],
"author" : "Errett Bishop"
}
class ThisWasConfusing(TeacherStudentsScene):
def construct(self):
words = TextMobject("Implicit differentiation")
words.move_to(self.get_teacher().get_corner(UP+LEFT), DOWN+RIGHT)
words.set_fill(opacity = 0)
self.play(
self.get_teacher().change_mode, "raise_right_hand",
words.set_fill, None, 1,
words.shift, 0.5*UP
)
self.change_student_modes(
*["confused"]*3,
look_at_arg = words,
added_anims = [Animation(self.get_teacher())]
)
self.wait()
self.play(
self.get_teacher().change_mode, "confused",
self.get_teacher().look_at, words,
)
self.wait(3)
class SlopeOfCircleExample(ZoomedScene):
CONFIG = {
"plane_kwargs" : {
"x_radius" : FRAME_X_RADIUS/SPACE_UNIT_TO_PLANE_UNIT,
"y_radius" : FRAME_Y_RADIUS/SPACE_UNIT_TO_PLANE_UNIT,
"space_unit_to_x_unit" : SPACE_UNIT_TO_PLANE_UNIT,
"space_unit_to_y_unit" : SPACE_UNIT_TO_PLANE_UNIT,
},
"example_point" : (3, 4),
"circle_radius" : 5,
"circle_color" : YELLOW,
"example_color" : MAROON_B,
"zoom_factor" : 20,
"zoomed_canvas_corner" : UP+LEFT,
"zoomed_canvas_corner_buff" : MED_SMALL_BUFF,
}
def construct(self):
self.setup_plane()
self.introduce_circle()
self.talk_through_pythagorean_theorem()
self.draw_example_slope()
self.show_perpendicular_radius()
self.show_dx_and_dy()
self.write_slope_as_dy_dx()
self.point_out_this_is_not_a_graph()
self.perform_implicit_derivative()
self.show_final_slope()
def setup_plane(self):
self.plane = NumberPlane(**self.plane_kwargs)
self.plane.main_lines.fade()
self.plane.add(self.plane.get_axis_labels())
self.plane.add_coordinates()
self.add(self.plane)
def introduce_circle(self):
circle = Circle(
radius = self.circle_radius*SPACE_UNIT_TO_PLANE_UNIT,
color = self.circle_color,
)
equation = TexMobject("x^2 + y^2 = 5^2")
equation.add_background_rectangle()
equation.next_to(
circle.point_from_proportion(1./8),
UP+RIGHT
)
equation.to_edge(RIGHT)
self.play(ShowCreation(circle, run_time = 2))
self.play(Write(equation))
self.wait()
self.circle = circle
self.circle_equation = equation
def talk_through_pythagorean_theorem(self):
point = self.plane.num_pair_to_point(self.example_point)
x_axis_point = point[0]*RIGHT
dot = Dot(point, color = self.example_color)
x_line = Line(ORIGIN, x_axis_point, color = GREEN)
y_line = Line(x_axis_point, point, color = RED)
radial_line = Line(ORIGIN, point, color = self.example_color)
lines = VGroup(radial_line, x_line, y_line)
labels = VGroup()
self.play(ShowCreation(dot))
for line, tex in zip(lines, "5xy"):
label = TexMobject(tex)
label.set_color(line.get_color())
label.add_background_rectangle()
label.next_to(
line.get_center(),
rotate_vector(UP, line.get_angle()),
buff = SMALL_BUFF
)
self.play(
ShowCreation(line),
Write(label)
)
labels.add(label)
full_group = VGroup(dot, lines, labels)
start_angle = angle_of_vector(point)
end_angle = np.pi/12
spatial_radius = get_norm(point)
def update_full_group(group, alpha):
dot, lines, labels = group
angle = interpolate(start_angle, end_angle, alpha)
new_point = spatial_radius*rotate_vector(RIGHT, angle)
new_x_axis_point = new_point[0]*RIGHT
dot.move_to(new_point)
radial_line, x_line, y_line = lines
x_line.put_start_and_end_on(ORIGIN, new_x_axis_point)
y_line.put_start_and_end_on(new_x_axis_point, new_point)
radial_line.put_start_and_end_on(ORIGIN, new_point)
for line, label in zip(lines, labels):
label.next_to(
line.get_center(),
rotate_vector(UP, line.get_angle()),
buff = SMALL_BUFF
)
return group
self.play(UpdateFromAlphaFunc(
full_group, update_full_group,
rate_func = there_and_back,
run_time = 5,
))
self.wait(2)
#Move labels to equation
movers = labels.copy()
pairs = list(zip(
[movers[1], movers[2], movers[0]],
self.circle_equation[1][0:-1:3]
))
self.play(*[
ApplyMethod(m1.replace, m2)
for m1, m2 in pairs
])
self.wait()
self.play(*list(map(FadeOut, [lines, labels, movers])))
self.remove(full_group)
self.add(dot)
self.wait()
self.example_point_dot = dot
def draw_example_slope(self):
point = self.example_point_dot.get_center()
line = Line(ORIGIN, point)
line.set_color(self.example_color)
line.rotate(np.pi/2)
line.scale(2)
line.move_to(point)
word = TextMobject("Slope?")
word.next_to(line.get_start(), UP, aligned_edge = LEFT)
word.add_background_rectangle()
coords = TexMobject("(%d, %d)"%self.example_point)
coords.add_background_rectangle()
coords.scale(0.7)
coords.next_to(point, LEFT)
coords.shift(SMALL_BUFF*DOWN)
coords.set_color(self.example_color)
self.play(GrowFromCenter(line))
self.play(Write(word))
self.wait()
self.play(Write(coords))
self.wait()
self.tangent_line = line
self.slope_word = word
self.example_point_coords_mob = coords
def show_perpendicular_radius(self):
point = self.example_point_dot.get_center()
radial_line = Line(ORIGIN, point, color = RED)
perp_mark = VGroup(
Line(UP, UP+RIGHT),
Line(UP+RIGHT, RIGHT),
)
perp_mark.scale(0.2)
perp_mark.set_stroke(width = 2)
perp_mark.rotate(radial_line.get_angle()+np.pi)
perp_mark.shift(point)
self.play(ShowCreation(radial_line))
self.play(ShowCreation(perp_mark))
self.wait()
self.play(Indicate(perp_mark))
self.wait()
morty = Mortimer().flip().to_corner(DOWN+LEFT)
self.play(FadeIn(morty))
self.play(PiCreatureBubbleIntroduction(
morty, "Suppose you \\\\ don't know this.",
))
to_fade =self.get_mobjects_from_last_animation()
self.play(Blink(morty))
self.wait()
self.play(*list(map(FadeOut, to_fade)))
self.play(*list(map(FadeOut, [radial_line, perp_mark])))
self.wait()
def show_dx_and_dy(self):
dot = self.example_point_dot
point = dot.get_center()
step_vect = rotate_vector(point, np.pi/2)
step_length = 1./self.zoom_factor
step_vect *= step_length/get_norm(step_vect)
step_line = Line(ORIGIN, LEFT)
step_line.set_color(WHITE)
brace = Brace(step_line, DOWN)
step_text = brace.get_text("Step", buff = SMALL_BUFF)
step_group = VGroup(step_line, brace, step_text)
step_group.rotate(angle_of_vector(point) - np.pi/2)
step_group.scale(1./self.zoom_factor)
step_group.shift(point)
interim_point = step_line.get_corner(UP+RIGHT)
dy_line = Line(point, interim_point)
dx_line = Line(interim_point, point+step_vect)
dy_line.set_color(RED)
dx_line.set_color(GREEN)
for line, tex in (dx_line, "dx"), (dy_line, "dy"):
label = TexMobject(tex)
label.scale(1./self.zoom_factor)
next_to_vect = np.round(
rotate_vector(DOWN, line.get_angle())
)
label.next_to(
line, next_to_vect,
buff = MED_SMALL_BUFF/self.zoom_factor
)
label.set_color(line.get_color())
line.label = label
self.activate_zooming()
self.little_rectangle.move_to(step_line.get_center())
self.little_rectangle.save_state()
self.little_rectangle.scale_in_place(self.zoom_factor)
self.wait()
self.play(
self.little_rectangle.restore,
dot.scale_in_place, 1./self.zoom_factor,
run_time = 2
)
self.wait()
self.play(ShowCreation(step_line))
self.play(GrowFromCenter(brace))
self.play(Write(step_text))
self.wait()
for line in dy_line, dx_line:
self.play(ShowCreation(line))
self.play(Write(line.label))
self.wait()
self.wait()
self.step_group = step_group
self.dx_line = dx_line
self.dy_line = dy_line
def write_slope_as_dy_dx(self):
slope_word = self.slope_word
new_slope_word = TextMobject("Slope =")
new_slope_word.add_background_rectangle()
new_slope_word.next_to(ORIGIN, RIGHT)
new_slope_word.shift(slope_word.get_center()[1]*UP)
dy_dx = TexMobject("\\frac{dy}{dx}")
VGroup(*dy_dx[:2]).set_color(RED)
VGroup(*dy_dx[-2:]).set_color(GREEN)
dy_dx.next_to(new_slope_word, RIGHT)
dy_dx.add_background_rectangle()
self.play(Transform(slope_word, new_slope_word))
self.play(Write(dy_dx))
self.wait()
self.dy_dx = dy_dx
def point_out_this_is_not_a_graph(self):
equation = self.circle_equation
x = equation[1][0]
y = equation[1][3]
brace = Brace(equation, DOWN)
brace_text = brace.get_text(
"Not $y = f(x)$",
buff = SMALL_BUFF
)
brace_text.set_color(RED)
alt_brace_text = brace.get_text("Implicit curve")
for text in brace_text, alt_brace_text:
text.add_background_rectangle()
text.to_edge(RIGHT, buff = MED_SMALL_BUFF)
new_circle = self.circle.copy()
new_circle.set_color(BLUE)
self.play(
GrowFromCenter(brace),
Write(brace_text)
)
self.wait()
self.play(Indicate(x))
self.wait()
self.play(Indicate(y))
self.wait()
self.play(Transform(brace_text, alt_brace_text))
self.wait()
self.play(
ShowCreation(new_circle, run_time = 2),
Animation(brace_text)
)
self.play(new_circle.set_stroke, None, 0)
self.wait()
self.play(*list(map(FadeOut, [brace, brace_text])))
self.wait()
def perform_implicit_derivative(self):
equation = self.circle_equation
morty = Mortimer()
morty.flip()
morty.next_to(ORIGIN, LEFT)
morty.to_edge(DOWN, buff = SMALL_BUFF)
q_marks = TexMobject("???")
q_marks.next_to(morty, UP)
rect = Rectangle(
width = FRAME_X_RADIUS - SMALL_BUFF,
height = FRAME_Y_RADIUS - SMALL_BUFF,
stroke_width = 0,
fill_color = BLACK,
fill_opacity = 0.8,
)
rect.to_corner(DOWN+RIGHT, buff = 0)
derivative = TexMobject("2x\\,dx + 2y\\,dy = 0")
dx = VGroup(*derivative[2:4])
dy = VGroup(*derivative[7:9])
dx.set_color(GREEN)
dy.set_color(RED)
self.play(
FadeIn(rect),
FadeIn(morty),
equation.next_to, ORIGIN, DOWN, MED_LARGE_BUFF,
equation.shift, FRAME_X_RADIUS*RIGHT/2,
)
self.play(
morty.change_mode, "confused",
morty.look_at, equation
)
self.play(Blink(morty))
derivative.next_to(equation, DOWN)
derivative.shift(
equation[1][-3].get_center()[0]*RIGHT - \
derivative[-2].get_center()[0]*RIGHT
)
#Differentiate
self.play(
morty.look_at, derivative[0],
*[
ReplacementTransform(
equation[1][i].copy(),
derivative[j],
)
for i, j in (1, 0), (0, 1)
]
)
self.play(Write(dx, run_time = 1))
self.wait()
self.play(*[
ReplacementTransform(
equation[1][i].copy(),
derivative[j],
)
for i, j in (2, 4), (3, 6), (4, 5)
])
self.play(Write(dy, run_time = 1))
self.play(Blink(morty))
self.play(*[
ReplacementTransform(
equation[1][i].copy(),
derivative[j],
)
for i, j in (-3, -2), (-2, -1), (-1, -1)
])
self.wait()
#React
self.play(morty.change_mode, "erm")
self.play(Blink(morty))
self.play(Write(q_marks))
self.wait()
self.play(Indicate(dx), morty.look_at, dx)
self.play(Indicate(dy), morty.look_at, dy)
self.wait()
self.play(
morty.change_mode, "shruggie",
FadeOut(q_marks)
)
self.play(Blink(morty))
self.play(
morty.change_mode, "pondering",
morty.look_at, derivative,
)
#Rearrange
x, y, eq = np.array(derivative)[[1, 6, 9]]
final_form = TexMobject(
"\\frac{dy}{dx} = \\frac{-x}{y}"
)
new_dy = VGroup(*final_form[:2])
new_dx = VGroup(*final_form[3:5])
new_dy.set_color(dy.get_color())
new_dx.set_color(dx.get_color())
new_dy.add(final_form[2])
new_x = VGroup(*final_form[6:8])
new_y = VGroup(*final_form[8:10])
new_eq = final_form[5]
final_form.next_to(derivative, DOWN)
final_form.shift((eq.get_center()[0]-new_eq.get_center()[0])*RIGHT)
self.play(*[
ReplacementTransform(
mover.copy(), target,
run_time = 2,
path_arc = np.pi/2,
)
for mover, target in [
(dy, new_dy),
(dx, new_dx),
(eq, new_eq),
(x, new_x),
(y, new_y)
]
] + [
morty.look_at, final_form
])
self.wait(2)
self.morty = morty
self.neg_x_over_y = VGroup(*final_form[6:])
def show_final_slope(self):
morty = self.morty
dy_dx = self.dy_dx
coords = self.example_point_coords_mob
x, y = coords[1][1].copy(), coords[1][3].copy()
frac = self.neg_x_over_y.copy()
frac.generate_target()
eq = TexMobject("=")
eq.add_background_rectangle()
eq.next_to(dy_dx, RIGHT)
frac.target.next_to(eq, RIGHT)
frac.target.shift(SMALL_BUFF*DOWN)
rect = BackgroundRectangle(frac.target)
self.play(
FadeIn(rect),
MoveToTarget(frac),
Write(eq),
morty.look_at, rect,
run_time = 2,
)
self.wait()
self.play(FocusOn(coords), morty.look_at, coords)
self.play(Indicate(coords))
scale_factor = 1.4
self.play(
x.scale, scale_factor,
x.set_color, GREEN,
x.move_to, frac[1],
FadeOut(frac[1]),
y.scale, scale_factor,
y.set_color, RED,
y.move_to, frac[3], DOWN,
y.shift, SMALL_BUFF*UP,
FadeOut(frac[3]),
morty.look_at, frac,
run_time = 2
)
self.wait()
self.play(Blink(morty))
class NameImplicitDifferentation(TeacherStudentsScene):
def construct(self):
title = TextMobject("``Implicit differentiation''")
equation = TexMobject("x^2", "+", "y^2", "=", "5^2")
derivative = TexMobject(
"2x\\,dx", "+", "2y\\,dy", "=", "0"
)
VGroup(*derivative[0][2:]).set_color(GREEN)
VGroup(*derivative[2][2:]).set_color(RED)
arrow = Arrow(ORIGIN, DOWN, buff = SMALL_BUFF)
group = VGroup(title, equation, arrow, derivative)
group.arrange_submobjects(DOWN)
group.to_edge(UP)
self.add(title, equation)
self.play(
self.get_teacher().change_mode, "raise_right_hand",
ShowCreation(arrow)
)
self.change_student_modes(
*["confused"]*3,
look_at_arg = derivative,
added_anims = [ReplacementTransform(equation.copy(), derivative)]
)
self.wait(2)
self.teacher_says(
"Don't worry...",
added_anims = [
group.scale, 0.7,
group.to_corner, UP+LEFT,
]
)
self.change_student_modes(*["happy"]*3)
self.wait(3)
class Ladder(VMobject):
CONFIG = {
"height" : 4,
"width" : 1,
"n_rungs" : 7,
}
def generate_points(self):
left_line, right_line = [
Line(ORIGIN, self.height*UP).shift(self.width*vect/2.0)
for vect in (LEFT, RIGHT)
]
rungs = [
Line(
left_line.point_from_proportion(a),
right_line.point_from_proportion(a),
)
for a in np.linspace(0, 1, 2*self.n_rungs+1)[1:-1:2]
]
self.add(left_line, right_line, *rungs)
self.center()
class RelatedRatesExample(ThreeDScene):
CONFIG = {
"start_x" : 3.0,
"start_y" : 4.0,
"wall_dimensions" : [0.3, 5, 5],
"wall_color" : color_gradient([GREY_BROWN, BLACK], 4)[1],
"wall_center" : 1.5*LEFT+0.5*UP,
}
def construct(self):
self.introduce_ladder()
self.write_related_rates()
self.measure_ladder()
self.slide_ladder()
self.ponder_question()
self.write_equation()
self.isolate_x_of_t()
self.discuss_lhs_as_function()
self.let_dt_pass()
self.take_derivative_of_rhs()
self.take_derivative_of_lhs()
self.bring_back_velocity_arrows()
self.replace_terms_in_final_form()
self.write_final_solution()
def introduce_ladder(self):
ladder = Ladder(height = self.get_ladder_length())
wall = Prism(
dimensions = self.wall_dimensions,
fill_color = self.wall_color,
fill_opacity = 1,
)
wall.rotate(np.pi/12, UP)
wall.shift(self.wall_center)
ladder.generate_target()
ladder.fallen = ladder.copy()
ladder.target.rotate(self.get_ladder_angle(), LEFT)
ladder.fallen.rotate(np.pi/2, LEFT)
for ladder_copy in ladder.target, ladder.fallen:
ladder_copy.rotate(-5*np.pi/12, UP)
ladder_copy.next_to(wall, LEFT, 0, DOWN)
ladder_copy.shift(0.8*RIGHT) ##BAD!
self.play(
ShowCreation(ladder, run_time = 2)
)
self.wait()
self.play(
DrawBorderThenFill(wall),
MoveToTarget(ladder),
run_time = 2
)
self.wait()
self.ladder = ladder
def write_related_rates(self):
words = TextMobject("Related rates")
words.to_corner(UP+RIGHT)
self.play(Write(words))
self.wait()
self.related_rates_words = words
def measure_ladder(self):
ladder = self.ladder
ladder_brace = self.get_ladder_brace(ladder)
x_and_y_lines = self.get_x_and_y_lines(ladder)
x_line, y_line = x_and_y_lines
y_label = TexMobject("%dm"%int(self.start_y))
y_label.next_to(y_line, LEFT, buff = SMALL_BUFF)
y_label.set_color(y_line.get_color())
x_label = TexMobject("%dm"%int(self.start_x))
x_label.next_to(x_line, UP)
x_label.set_color(x_line.get_color())
self.play(Write(ladder_brace))
self.wait()
self.play(ShowCreation(y_line), Write(y_label))
self.wait()
self.play(ShowCreation(x_line), Write(x_label))
self.wait(2)
self.play(*list(map(FadeOut, [x_label, y_label])))
self.ladder_brace = ladder_brace
self.x_and_y_lines = x_and_y_lines
self.numerical_x_and_y_labels = VGroup(x_label, y_label)
def slide_ladder(self):
ladder = self.ladder
brace = self.ladder_brace
x_and_y_lines = self.x_and_y_lines
x_line, y_line = x_and_y_lines
down_arrow, left_arrow = [
Arrow(ORIGIN, vect, color = YELLOW, buff = 0)
for vect in (DOWN, LEFT)
]
down_arrow.shift(y_line.get_start()+MED_SMALL_BUFF*RIGHT)
left_arrow.shift(x_line.get_start()+SMALL_BUFF*DOWN)
# speed_label = TexMobject("1 \\text{m}/\\text{s}")
speed_label = TexMobject("1 \\frac{\\text{m}}{\\text{s}}")
speed_label.next_to(down_arrow, RIGHT, buff = SMALL_BUFF)
q_marks = TexMobject("???")
q_marks.next_to(left_arrow, DOWN, buff = SMALL_BUFF)
added_anims = [
UpdateFromFunc(brace, self.update_brace),
UpdateFromFunc(x_and_y_lines, self.update_x_and_y_lines),
Animation(down_arrow),
]
self.play(ShowCreation(down_arrow))
self.play(Write(speed_label))
self.let_ladder_fall(ladder, *added_anims)
self.wait()
self.reset_ladder(ladder, *added_anims)
self.play(ShowCreation(left_arrow))
self.play(Write(q_marks))
self.wait()
self.let_ladder_fall(ladder, *added_anims)
self.wait()
self.reset_ladder(ladder, *added_anims)
self.wait()
self.dy_arrow = down_arrow
self.dy_label = speed_label
self.dx_arrow = left_arrow
self.dx_label = q_marks
def ponder_question(self):
randy = Randolph(mode = "pondering")
randy.flip()
randy.to_corner(DOWN+RIGHT)
self.play(FadeIn(randy))
self.play(Blink(randy))
self.wait()
self.play(
randy.change_mode, "confused",
randy.look_at, self.ladder.get_top()
)
self.play(randy.look_at, self.ladder.get_bottom())
self.play(randy.look_at, self.ladder.get_top())
self.play(Blink(randy))
self.wait()
self.play(PiCreatureSays(
randy, "Give names"
))
self.play(Blink(randy))
self.play(*list(map(FadeOut, [
randy, randy.bubble, randy.bubble.content
])))
def write_equation(self):
self.x_and_y_labels = self.get_x_and_y_labels()
x_label, y_label = self.x_and_y_labels
equation = TexMobject(
"x(t)", "^2", "+", "y(t)", "^2", "=", "5^2"
)
equation[0].set_color(GREEN)
equation[3].set_color(RED)
equation.next_to(self.related_rates_words, DOWN, buff = MED_LARGE_BUFF)
equation.to_edge(RIGHT, buff = LARGE_BUFF)
self.play(Write(y_label))
self.wait()
self.let_ladder_fall(
self.ladder,
y_label.shift, self.start_y*DOWN/2,
*self.get_added_anims_for_ladder_fall()[:-1],
rate_func = lambda t : 0.2*there_and_back(t),
run_time = 3
)
self.play(FocusOn(x_label))
self.play(Write(x_label))
self.wait(2)
self.play(
ReplacementTransform(x_label.copy(), equation[0]),
ReplacementTransform(y_label.copy(), equation[3]),
Write(VGroup(*np.array(equation)[[1, 2, 4, 5, 6]]))
)
self.wait(2)
self.let_ladder_fall(
self.ladder,
*self.get_added_anims_for_ladder_fall(),
rate_func = there_and_back,
run_time = 6
)
self.wait()
self.equation = equation
def isolate_x_of_t(self):
alt_equation = TexMobject(
"x(t)", "=", "\\big(5^2", "-", "y(t)", "^2 \\big)", "^{1/2}",
)
alt_equation[0].set_color(GREEN)
alt_equation[4].set_color(RED)
alt_equation.next_to(self.equation, DOWN, buff = MED_LARGE_BUFF)
alt_equation.to_edge(RIGHT)
randy = Randolph()
randy.next_to(
alt_equation, DOWN,
buff = MED_LARGE_BUFF,
aligned_edge = LEFT,
)
randy.look_at(alt_equation)
find_dx_dt = TexMobject("\\text{Find } \\,", "\\frac{dx}{dt}")
find_dx_dt.next_to(randy, RIGHT, aligned_edge = UP)
find_dx_dt[1].set_color(GREEN)
self.play(FadeIn(randy))
self.play(
randy.change_mode, "raise_right_hand",
randy.look_at, alt_equation,
*[
ReplacementTransform(
self.equation[i].copy(),
alt_equation[j],
path_arc = np.pi/2,
run_time = 3,
rate_func = squish_rate_func(
smooth, j/12.0, (j+6)/12.0
)
)
for i, j in enumerate([0, 6, 3, 4, 5, 1, 2])
]
)
self.play(Blink(randy))
self.wait()
self.play(
Write(find_dx_dt),
randy.change_mode, "pondering",
randy.look_at, find_dx_dt,
)
self.let_ladder_fall(
self.ladder, *self.get_added_anims_for_ladder_fall(),
run_time = 8,
rate_func = there_and_back
)
self.play(*list(map(FadeOut, [
randy, find_dx_dt, alt_equation
])))
self.wait()
def discuss_lhs_as_function(self):
equation = self.equation
lhs = VGroup(*equation[:5])
brace = Brace(lhs, DOWN)
function_of_time = brace.get_text(
"Function of time"
)
constant_words = TextMobject(
"""that happens to
be constant"""
)
constant_words.set_color(YELLOW)
constant_words.next_to(function_of_time, DOWN)
derivative = TexMobject(
"\\frac{d\\left(x(t)^2 + y(t)^2 \\right)}{dt}"
)
derivative.next_to(equation, DOWN, buff = MED_LARGE_BUFF)
derivative.shift( ##Align x terms
equation[0][0].get_center()[0]*RIGHT-\
derivative[2].get_center()[0]*RIGHT
)
derivative_interior = lhs.copy()
derivative_interior.move_to(VGroup(*derivative[2:13]))
derivative_scaffold = VGroup(
*list(derivative[:2])+list(derivative[13:])
)
self.play(
GrowFromCenter(brace),
Write(function_of_time)
)
self.wait()
self.play(Write(constant_words))
self.let_ladder_fall(
self.ladder, *self.get_added_anims_for_ladder_fall(),
run_time = 6,
rate_func = lambda t : 0.5*there_and_back(t)
)
self.wait()
self.play(*list(map(FadeOut, [
brace, constant_words, function_of_time
])))
self.play(
ReplacementTransform(lhs.copy(), derivative_interior),
Write(derivative_scaffold),
)
self.wait()
self.derivative = VGroup(
derivative_scaffold, derivative_interior
)
def let_dt_pass(self):
dt_words = TextMobject("After", "$dt$", "seconds...")
dt_words.to_corner(UP+LEFT)
dt = dt_words[1]
dt.set_color(YELLOW)
dt_brace = Brace(dt, buff = SMALL_BUFF)
dt_brace_text = dt_brace.get_text("Think 0.01", buff = SMALL_BUFF)
dt_brace_text.set_color(dt.get_color())
shadow_ladder = self.ladder.copy()
shadow_ladder.fade(0.5)
x_line, y_line = self.x_and_y_lines
y_top = y_line.get_start()
x_left = x_line.get_start()
self.play(Write(dt_words, run_time = 2))
self.play(
GrowFromCenter(dt_brace),
Write(dt_brace_text, run_time = 2)
)
self.play(*list(map(FadeOut, [
self.dy_arrow, self.dy_label,
self.dx_arrow, self.dx_label,
])))
self.add(shadow_ladder)
self.let_ladder_fall(
self.ladder, *self.get_added_anims_for_ladder_fall(),
rate_func = lambda t : 0.1*smooth(t),
run_time = 1
)
new_y_top = y_line.get_start()
new_x_left = x_line.get_start()
dy_line = Line(y_top, new_y_top)
dy_brace = Brace(dy_line, RIGHT, buff = SMALL_BUFF)
dy_label = dy_brace.get_text("$dy$", buff = SMALL_BUFF)
dy_label.set_color(RED)
dx_line = Line(x_left, new_x_left)
dx_brace = Brace(dx_line, DOWN, buff = SMALL_BUFF)
dx_label = dx_brace.get_text("$dx$")
dx_label.set_color(GREEN)
VGroup(dy_line, dx_line).set_color(YELLOW)
for line, brace, label in (dy_line, dy_brace, dy_label), (dx_line, dx_brace, dx_label):
self.play(
ShowCreation(line),
GrowFromCenter(brace),
Write(label),
run_time = 1
)
self.wait()
self.play(Indicate(self.derivative[1]))
self.wait()
self.dy_group = VGroup(dy_line, dy_brace, dy_label)
self.dx_group = VGroup(dx_line, dx_brace, dx_label)
self.shadow_ladder = shadow_ladder
def take_derivative_of_rhs(self):
derivative = self.derivative
equals_zero = TexMobject("= 0")
equals_zero.next_to(derivative)
rhs = self.equation[-1]
self.play(Write(equals_zero))
self.wait()
self.play(FocusOn(rhs))
self.play(Indicate(rhs))
self.wait()
self.reset_ladder(
self.ladder,
*self.get_added_anims_for_ladder_fall()+[
Animation(self.dy_group),
Animation(self.dx_group),
],
rate_func = there_and_back,
run_time = 3
)
self.wait()
self.equals_zero = equals_zero
def take_derivative_of_lhs(self):
derivative_scaffold, equation = self.derivative
equals_zero_copy = self.equals_zero.copy()
lhs_derivative = TexMobject(
"2", "x(t)", "\\frac{dx}{dt}", "+",
"2", "y(t)", "\\frac{dy}{dt}",
)
lhs_derivative[1].set_color(GREEN)
VGroup(*lhs_derivative[2][:2]).set_color(GREEN)
lhs_derivative[5].set_color(RED)
VGroup(*lhs_derivative[6][:2]).set_color(RED)
lhs_derivative.next_to(
derivative_scaffold, DOWN,
aligned_edge = RIGHT,
buff = MED_LARGE_BUFF
)
equals_zero_copy.next_to(lhs_derivative, RIGHT)
pairs = [
(0, 1), (1, 0), #x^2 -> 2x
(2, 3), (3, 5), (4, 4), #+y^2 -> +2y
]
def perform_replacement(index_pairs):
self.play(*[
ReplacementTransform(
equation[i].copy(), lhs_derivative[j],
path_arc = np.pi/2,
run_time = 2
)
for i, j in index_pairs
])
perform_replacement(pairs[:2])
self.play(Write(lhs_derivative[2]))
self.wait()
self.play(Indicate(
VGroup(
*list(lhs_derivative[:2])+\
list(lhs_derivative[2][:2])
),
run_time = 2
))
self.play(Indicate(VGroup(*lhs_derivative[2][3:])))
self.wait(2)
perform_replacement(pairs[2:])
self.play(Write(lhs_derivative[6]))
self.wait()
self.play(FocusOn(self.equals_zero))
self.play(ReplacementTransform(
self.equals_zero.copy(),
equals_zero_copy
))
self.wait(2)
lhs_derivative.add(equals_zero_copy)
self.lhs_derivative = lhs_derivative
def bring_back_velocity_arrows(self):
dx_dy_group = VGroup(self.dx_group, self.dy_group)
arrow_group = VGroup(
self.dy_arrow, self.dy_label,
self.dx_arrow, self.dx_label,
)
ladder_fall_args = [self.ladder] + self.get_added_anims_for_ladder_fall()
self.reset_ladder(*ladder_fall_args + [
FadeOut(dx_dy_group),
FadeOut(self.derivative),
FadeOut(self.equals_zero),
self.lhs_derivative.shift, 2*UP,
])
self.remove(self.shadow_ladder)
self.play(FadeIn(arrow_group))
self.let_ladder_fall(*ladder_fall_args)
self.wait()
self.reset_ladder(*ladder_fall_args)
self.wait()
def replace_terms_in_final_form(self):
x_label, y_label = self.x_and_y_labels
num_x_label, num_y_label = self.numerical_x_and_y_labels
new_lhs_derivative = TexMobject(
"2", "(%d)"%int(self.start_x), "\\frac{dx}{dt}", "+",
"2", "(%d)"%int(self.start_y), "(-1)",
"= 0"
)
new_lhs_derivative[1].set_color(GREEN)
VGroup(*new_lhs_derivative[2][:2]).set_color(GREEN)
new_lhs_derivative[5].set_color(RED)
new_lhs_derivative.next_to(
self.lhs_derivative, DOWN,
buff = MED_LARGE_BUFF,
aligned_edge = RIGHT
)
def fill_in_equation_part(*indices):
self.play(*[
ReplacementTransform(
self.lhs_derivative[i].copy(),
new_lhs_derivative[i],
run_time = 2
)
for i in indices
])
self.play(FadeOut(y_label), FadeIn(num_y_label))
fill_in_equation_part(3, 4, 5)
self.play(FadeOut(x_label), FadeIn(num_x_label))
for indices in [(0, 1), (6,), (2, 7)]:
fill_in_equation_part(*indices)
self.wait()
self.wait()
self.new_lhs_derivative = new_lhs_derivative
def write_final_solution(self):
solution = TexMobject(
"\\frac{dx}{dt} = \\frac{4}{3}"
)
for i in 0, 1, -1:
solution[i].set_color(GREEN)
solution[-3].set_color(RED)
solution.next_to(
self.new_lhs_derivative, DOWN,
buff = MED_LARGE_BUFF,
aligned_edge = RIGHT
)
box = Rectangle(color = YELLOW)
box.replace(solution)
box.scale_in_place(1.5)
self.play(Write(solution))
self.wait()
self.play(ShowCreation(box))
self.wait()
#########
def get_added_anims_for_ladder_fall(self):
return [
UpdateFromFunc(self.ladder_brace, self.update_brace),
UpdateFromFunc(self.x_and_y_lines, self.update_x_and_y_lines),
UpdateFromFunc(self.x_and_y_labels, self.update_x_and_y_labels),
]
def let_ladder_fall(self, ladder, *added_anims, **kwargs):
kwargs["run_time"] = kwargs.get("run_time", self.start_y)
kwargs["rate_func"] = kwargs.get("rate_func", None)
self.play(
Transform(ladder, ladder.fallen),
*added_anims,
**kwargs
)
def reset_ladder(self, ladder, *added_anims, **kwargs):
kwargs["run_time"] = kwargs.get("run_time", 2)
self.play(
Transform(ladder, ladder.target),
*added_anims,
**kwargs
)
def update_brace(self, brace):
Transform(
brace, self.get_ladder_brace(self.ladder)
).update(1)
return brace
def update_x_and_y_lines(self, x_and_y_lines):
Transform(
x_and_y_lines,
self.get_x_and_y_lines(self.ladder)
).update(1)
return x_and_y_lines
def update_x_and_y_labels(self, x_and_y_labels):
Transform(
x_and_y_labels,
self.get_x_and_y_labels()
).update(1)
return x_and_y_labels
def get_ladder_brace(self, ladder):
vect = rotate_vector(LEFT, -self.get_ladder_angle())
brace = Brace(ladder, vect)
length_string = "%dm"%int(self.get_ladder_length())
length_label = brace.get_text(
length_string, use_next_to = False
)
brace.add(length_label)
brace.length_label = length_label
return brace
def get_x_and_y_labels(self):
x_line, y_line = self.x_and_y_lines
x_label = TexMobject("x(t)")
x_label.set_color(x_line.get_color())
x_label.next_to(x_line, DOWN, buff = SMALL_BUFF)
y_label = TexMobject("y(t)")
y_label.set_color(y_line.get_color())
y_label.next_to(y_line, LEFT, buff = SMALL_BUFF)
return VGroup(x_label, y_label)
def get_x_and_y_lines(self, ladder):
bottom_point, top_point = np.array(ladder[1].get_start_and_end())
interim_point = top_point[0]*RIGHT + bottom_point[1]*UP
interim_point += SMALL_BUFF*DOWN
y_line = Line(top_point, interim_point)
y_line.set_color(RED)
x_line = Line(bottom_point, interim_point)
x_line.set_color(GREEN)
return VGroup(x_line, y_line)
def get_ladder_angle(self):
if hasattr(self, "ladder"):
c1 = self.ladder.get_corner(UP+RIGHT)
c2 = self.ladder.get_corner(DOWN+LEFT)
vect = c1-c2
return np.pi/2 - angle_of_vector(vect)
else:
return np.arctan(self.start_x/self.start_y)
def get_ladder_length(self):
return get_norm([self.start_x, self.start_y])
class LightweightLadderScene(RelatedRatesExample):
CONFIG = {
"skip_animations" : True
}
def construct(self):
self.introduce_ladder()
self.measure_ladder()
self.add(self.numerical_x_and_y_labels)
class LightweightCircleExample(SlopeOfCircleExample):
CONFIG = {
"skip_animations" : True,
"plane_kwargs" : {
"x_radius" : 5,
"y_radius" : 5,
"space_unit_to_x_unit" : SPACE_UNIT_TO_PLANE_UNIT,
"space_unit_to_y_unit" : SPACE_UNIT_TO_PLANE_UNIT,
},
}
def construct(self):
self.setup_plane()
self.introduce_circle()
self.talk_through_pythagorean_theorem()
self.draw_example_slope()
self.remove(self.circle_equation)
self.remove(self.slope_word)
self.example_point_coords_mob.scale(
1.5, about_point = self.example_point_coords_mob.get_corner(UP+RIGHT)
)
self.plane.axis_labels[0].shift(3*LEFT)
class CompareLadderAndCircle(PiCreatureScene, ThreeDScene):
def construct(self):
self.introduce_both_scenes()
self.show_derivatives()
self.comment_on_ladder_derivative()
self.comment_on_circle_derivative()
def introduce_both_scenes(self):
ladder_scene = LightweightLadderScene()
ladder_mobs = VGroup(*ladder_scene.get_top_level_mobjects())
circle_scene = LightweightCircleExample()
circle_mobs = VGroup(*circle_scene.get_top_level_mobjects())
for mobs, vect in (ladder_mobs, LEFT), (circle_mobs, RIGHT):
mobs.set_height(FRAME_Y_RADIUS-MED_LARGE_BUFF)
mobs.next_to(
self.pi_creature.get_corner(UP+vect), UP,
buff = SMALL_BUFF,
aligned_edge = -vect
)
ladder_mobs.save_state()
ladder_mobs.fade(1)
ladder_mobs.rotate_in_place(np.pi/3, UP)
self.play(
self.pi_creature.change_mode, "raise_right_hand",
self.pi_creature.look_at, ladder_mobs,
ApplyMethod(ladder_mobs.restore, run_time = 2)
)
self.play(
self.pi_creature.change_mode, "raise_left_hand",
self.pi_creature.look_at, circle_mobs,
Write(circle_mobs, run_time = 2)
)
self.wait(2)
self.play(
circle_mobs.to_edge, RIGHT,
ladder_mobs.to_edge, LEFT,
)
def show_derivatives(self):
equation = TexMobject(
"x", "^2", "+", "y", "^2", "= 5^2"
)
derivative = TexMobject(
"2", "x", "dx", "+", "2", "y", "dy", "=0"
)
self.color_equations(equation, derivative)
equation.to_edge(UP)
equation.shift(MED_LARGE_BUFF*LEFT)
derivative.next_to(equation, DOWN, buff = MED_LARGE_BUFF)
self.play(
Write(equation),
self.pi_creature.change_mode, "plain",
self.pi_creature.look_at, equation
)
self.wait()
self.play(*[
ReplacementTransform(
equation[i].copy(), derivative[j],
path_arc = np.pi/2
)
for i, j in enumerate([1, 0, 3, 5, 4, 7])
]+[
Write(derivative[j])
for j in (2, 6)
])
self.play(
self.pi_creature.change_mode, "pondering",
self.pi_creature.look_at, derivative
)
self.wait()
self.equation = equation
self.derivative = derivative
def comment_on_ladder_derivative(self):
equation = self.equation
derivative = self.derivative
time_equation = TexMobject(
"x(t)", "^2", "+", "y(t)", "^2", "= 5^2"
)
time_derivative = TexMobject(
"2", "x(t)", "\\frac{dx}{dt}", "+",
"2", "y(t)", "\\frac{dy}{dt}", "=0"
)
self.color_equations(time_equation, time_derivative)
time_equation.move_to(equation)
time_derivative.move_to(derivative, UP)
brace = Brace(time_derivative)
brace_text = brace.get_text("A rate")
equation.save_state()
derivative.save_state()
self.play(Transform(equation, time_equation))
self.wait()
self.play(Transform(derivative, time_derivative))
self.wait()
self.play(GrowFromCenter(brace))
self.play(Write(brace_text))
self.change_mode("hooray")
self.wait(2)
self.play(
equation.restore,
derivative.restore,
FadeOut(brace),
FadeOut(brace_text),
self.pi_creature.change_mode, "confused"
)
self.wait()
def comment_on_circle_derivative(self):
derivative = self.derivative
dx = derivative.get_part_by_tex("dx")
dy = derivative.get_part_by_tex("dy")
for mob in dx, dy:
brace = Brace(mob)
brace.next_to(mob[0], DOWN, buff = SMALL_BUFF, aligned_edge = LEFT)
text = brace.get_text("No $dt$", buff = SMALL_BUFF)
text.set_color(YELLOW)
self.play(
GrowFromCenter(brace),
Write(text)
)
self.wait()
self.play(
self.pi_creature.change_mode, "pondering",
self.pi_creature.look, DOWN+LEFT
)
self.wait(2)
#######
def create_pi_creature(self):
self.pi_creature = Mortimer().to_edge(DOWN)
return self.pi_creature
def color_equations(self, equation, derivative):
for mob in equation[0], derivative[1]:
mob.set_color(GREEN)
for mob in equation[3], derivative[5]:
mob.set_color(RED)
class TwoVariableFunctionAndDerivative(SlopeOfCircleExample):
CONFIG = {
"zoomed_canvas_corner" : DOWN+RIGHT,
"zoomed_canvas_frame_shape" : (3, 4),
}
def construct(self):
self.setup_plane()
self.write_equation()
self.show_example_point()
self.shift_example_point((4, 4))
self.shift_example_point((3, 3))
self.shift_example_point(self.example_point)
self.take_derivative_symbolically()
self.show_dx_dy_step()
self.plug_in_example_values()
self.ask_about_equalling_zero()
self.show_tangent_step()
self.point_out_equalling_zero()
self.show_tangent_line()
def write_equation(self):
equation = TexMobject("x", "^2", "+", "y", "^2")
equation.add_background_rectangle()
brace = Brace(equation, UP, buff = SMALL_BUFF)
s_expression = self.get_s_expression("x", "y")
s_rect, s_of_xy = s_expression
s, xy = s_of_xy
s_expression.next_to(brace, UP, buff = SMALL_BUFF)
group = VGroup(equation, s_expression, brace)
group.shift(FRAME_WIDTH*LEFT/3)
group.to_edge(UP, buff = MED_SMALL_BUFF)
s.save_state()
s.next_to(brace, UP)
self.play(Write(equation))
self.play(GrowFromCenter(brace))
self.play(Write(s))
self.wait()
self.play(
FadeIn(s_rect),
s.restore,
GrowFromCenter(xy)
)
self.wait()
self.equation = equation
self.s_expression = s_expression
def show_example_point(self):
point = self.plane.num_pair_to_point(self.example_point)
dot = Dot(point, color = self.example_color)
new_s_expression = self.get_s_expression(*self.example_point)
new_s_expression.next_to(dot, UP+RIGHT, buff = 0)
new_s_expression.set_color(self.example_color)
equals_25 = TexMobject("=%d"%int(get_norm(self.example_point)**2))
equals_25.set_color(YELLOW)
equals_25.next_to(new_s_expression, RIGHT, align_using_submobjects = True)
equals_25.add_background_rectangle()
circle = Circle(
radius = self.circle_radius*self.plane.space_unit_to_x_unit,
color = self.circle_color,
)
self.play(
ReplacementTransform(
self.s_expression.copy(),
new_s_expression
),
ShowCreation(dot)
)
self.play(ShowCreation(circle), Animation(dot))
self.play(Write(equals_25))
self.wait()
self.example_point_dot = dot
self.example_point_label = VGroup(
new_s_expression, equals_25
)
def shift_example_point(self, coords):
point = self.plane.num_pair_to_point(coords)
s_expression = self.get_s_expression(*coords)
s_expression.next_to(point, UP+RIGHT, buff = SMALL_BUFF)
s_expression.set_color(self.example_color)
result = coords[0]**2 + coords[1]**2
rhs = TexMobject("=%d"%int(result))
rhs.add_background_rectangle()
rhs.set_color(YELLOW)
rhs.next_to(s_expression, RIGHT, align_using_submobjects = True)
point_label = VGroup(s_expression, rhs)
self.play(
self.example_point_dot.move_to, point,
Transform(self.example_point_label, point_label)
)
self.wait(2)
def take_derivative_symbolically(self):
equation = self.equation
derivative = TexMobject(
"dS =", "2", "x", "\\,dx", "+", "2", "y", "\\,dy",
)
derivative[2].set_color(GREEN)
derivative[6].set_color(RED)
derivative.next_to(equation, DOWN, buff = MED_LARGE_BUFF)
derivative.add_background_rectangle()
derivative.to_edge(LEFT)
self.play(*[
FadeIn(derivative[0])
]+[
ReplacementTransform(
self.s_expression[1][0].copy(),
derivative[1][0],
)
]+[
Write(derivative[1][j])
for j in (3, 7)
])
self.play(*[
ReplacementTransform(
equation[1][i].copy(), derivative[1][j],
path_arc = np.pi/2,
run_time = 2,
rate_func = squish_rate_func(smooth, (j-1)/12., (j+6)/12.)
)
for i, j in enumerate([2, 1, 4, 6, 5])
])
self.wait(2)
self.derivative = derivative
def show_dx_dy_step(self):
dot = self.example_point_dot
s_label = self.example_point_label
rhs = s_label[-1]
s_label.remove(rhs)
point = dot.get_center()
vect = 2*LEFT + DOWN
new_point = point + vect*0.6/self.zoom_factor
interim_point = new_point[0]*RIGHT + point[1]*UP
dx_line = Line(point, interim_point, color = GREEN)
dy_line = Line(interim_point, new_point, color = RED)
for line, tex, vect in (dx_line, "dx", UP), (dy_line, "dy", LEFT):
label = TexMobject(tex)
label.set_color(line.get_color())
label.next_to(line, vect, buff = SMALL_BUFF)
label.add_background_rectangle()
label.scale(
1./self.zoom_factor,
about_point = line.get_center()
)
line.label = label
self.activate_zooming()
lil_rect = self.little_rectangle
lil_rect.move_to(dot)
lil_rect.shift(0.05*lil_rect.get_width()*LEFT)
lil_rect.shift(0.2*lil_rect.get_height()*DOWN)
lil_rect.save_state()
lil_rect.set_height(FRAME_Y_RADIUS - MED_LARGE_BUFF)
lil_rect.move_to(s_label, UP)
lil_rect.shift(MED_SMALL_BUFF*UP)
self.wait()
self.play(
FadeOut(rhs),
dot.scale, 1./self.zoom_factor, point,
s_label.scale, 1./self.zoom_factor, point,
lil_rect.restore,
run_time = 2
)
self.wait()
for line in dx_line, dy_line:
self.play(ShowCreation(line))
self.play(Write(line.label, run_time = 1))
self.wait()
new_dot = Dot(color = dot.get_color())
new_s_label = self.get_s_expression(
"%d + dx"%int(self.example_point[0]),
"%d + dy"%int(self.example_point[1]),
)
new_dot.set_height(dot.get_height())
new_dot.move_to(new_point)
new_s_label.set_height(s_label.get_height())
new_s_label.scale(0.8)
new_s_label.next_to(
new_dot, DOWN,
buff = SMALL_BUFF/self.zoom_factor,
aligned_edge = LEFT
)
new_s_label.shift(MED_LARGE_BUFF*LEFT/self.zoom_factor)
new_s_label.set_color(self.example_color)
VGroup(*new_s_label[1][1][3:5]).set_color(GREEN)
VGroup(*new_s_label[1][1][-3:-1]).set_color(RED)
self.play(ShowCreation(new_dot))
self.play(Write(new_s_label))
self.wait()
ds = self.derivative[1][0]
self.play(FocusOn(ds))
self.play(Indicate(ds))
self.wait()
self.tiny_step_group = VGroup(
dx_line, dx_line.label,
dy_line, dy_line.label,
s_label, new_s_label, new_dot
)
def plug_in_example_values(self):
deriv_example = TexMobject(
"dS =", "2", "(3)", "\\,(-0.02)", "+", "2", "(4)", "\\,(-0.01)",
)
deriv_example[2].set_color(GREEN)
deriv_example[6].set_color(RED)
deriv_example.add_background_rectangle()
deriv_example.scale(0.8)
deriv_example.next_to(ORIGIN, UP, buff = SMALL_BUFF)
deriv_example.to_edge(LEFT, buff = MED_SMALL_BUFF)
def add_example_parts(*indices):
self.play(*[
ReplacementTransform(
self.derivative[1][i].copy(),
deriv_example[1][i],
run_time = 2
)
for i in indices
])
self.play(FadeIn(deriv_example[0]))
add_example_parts(0)
self.wait()
add_example_parts(1, 2, 4, 5, 6)
self.wait(2)
add_example_parts(3)
self.wait()
add_example_parts(7)
self.wait()
#React
randy = Randolph()
randy.next_to(ORIGIN, LEFT)
randy.to_edge(DOWN)
self.play(FadeIn(randy))
self.play(
randy.change_mode, "pondering",
randy.look_at, deriv_example.get_left()
)
self.play(Blink(randy))
self.play(randy.look_at, deriv_example.get_right())
self.wait()
self.play(
Indicate(self.equation),
randy.look_at, self.equation
)
self.play(Blink(randy))
self.play(
randy.change_mode, "thinking",
randy.look_at, self.big_rectangle
)
self.wait(2)
self.play(PiCreatureSays(
randy, "Approximately",
target_mode = "sassy"
))
self.wait()
self.play(RemovePiCreatureBubble(randy))
self.play(randy.look_at, deriv_example)
self.play(FadeOut(deriv_example))
self.wait()
self.randy = randy
def ask_about_equalling_zero(self):
dot = self.example_point_dot
randy = self.randy
equals_zero = TexMobject("=0")
equals_zero.set_color(YELLOW)
equals_zero.add_background_rectangle()
equals_zero.next_to(self.derivative, RIGHT)
self.play(
Write(equals_zero),
randy.change_mode, "confused",
randy.look_at, equals_zero
)
self.wait()
self.play(Blink(randy))
self.play(
randy.change_mode, "plain",
randy.look_at, self.big_rectangle,
)
self.play(
FadeOut(self.tiny_step_group),
self.little_rectangle.move_to, dot,
)
self.wait()
self.equals_zero = equals_zero
def show_tangent_step(self):
dot = self.example_point_dot
randy = self.randy
point = dot.get_center()
step_vect = rotate_vector(point, np.pi/2)/get_norm(point)
new_point = point + step_vect/self.zoom_factor
interim_point = point[0]*RIGHT + new_point[1]*UP
new_dot = dot.copy().move_to(new_point)
step_line = Line(point, new_point, color = WHITE)
dy_line = Line(point, interim_point, color = RED)
dx_line = Line(interim_point, new_point, color = GREEN)
s_label = TexMobject("S = 25")
s_label.set_color(self.example_color)
s_label.next_to(
point, DOWN,
buff = MED_LARGE_BUFF,
aligned_edge = RIGHT
)
s_label.scale(1./self.zoom_factor, about_point = point)
arrow1, arrow2 = [
Arrow(
s_label.get_top(), mob,
preserve_tip_size_when_scaling = False,
color = self.example_color,
buff = SMALL_BUFF/self.zoom_factor,
tip_length = 0.15/self.zoom_factor
)
for mob in (dot, new_dot)
]
for line, tex, vect in (dy_line, "dy", RIGHT), (dx_line, "dx", UP):
label = TexMobject(tex)
label.set_color(line.get_color())
label.next_to(line, vect)
label.scale(
1./self.zoom_factor,
about_point = line.get_center()
)
line.label = label
self.play(ShowCreation(line))
self.play(Write(label))
self.play(ShowCreation(new_dot))
self.play(
randy.change_mode, "pondering",
randy.look_at, self.big_rectangle
)
self.play(Blink(randy))
self.wait()
self.play(Write(s_label))
self.play(ShowCreation(arrow1))
self.wait()
self.play(ReplacementTransform(arrow1.copy(), arrow2))
self.wait(2)
def point_out_equalling_zero(self):
derivative = self.derivative
equals_zero = self.equals_zero
randy = self.randy
self.play(
FocusOn(equals_zero),
self.randy.look_at, equals_zero
)
self.play(Indicate(equals_zero, color = RED))
self.play(Blink(randy))
self.play(randy.change_mode, "happy")
self.play(randy.look_at, self.big_rectangle)
self.wait(2)
def show_tangent_line(self):
randy = self.randy
point = self.example_point_dot.get_center()
line = Line(ORIGIN, 5*RIGHT)
line.rotate(angle_of_vector(point)+np.pi/2)
line.move_to(point)
self.play(PiCreatureSays(
randy, "Approximately...",
))
self.play(Blink(randy))
self.play(RemovePiCreatureBubble(randy))
self.play(
GrowFromCenter(line),
randy.look_at, line
)
self.wait(2)
self.play(
self.little_rectangle.scale_in_place, self.zoom_factor/2,
run_time = 4,
rate_func = there_and_back
)
self.wait(2)
############
def get_s_expression(self, x, y):
result = TexMobject("S", "(%s, %s)"%(str(x), str(y)))
result.add_background_rectangle()
return result
class TryOtherExamples(TeacherStudentsScene):
def construct(self):
formula = TexMobject("\\sin(x)y^2 = x")
formula.next_to(
self.get_teacher().get_corner(UP+LEFT), UP,
buff = MED_LARGE_BUFF,
aligned_edge = RIGHT
)
self.teacher_says(
"""Nothing special
about $x^2 + y^2 = 25$"""
)
self.wait()
self.play(RemovePiCreatureBubble(
self.get_teacher(),
target_mode = "raise_right_hand"
))
self.play(Write(formula, run_time = 1))
self.change_student_modes(*["pondering"]*3)
self.wait(2)
self.play(formula.to_corner, UP+LEFT)
self.wait()
class AlternateExample(ZoomedScene):
CONFIG = {
"example_color" : MAROON_B,
"zoom_factor" : 10,
"zoomed_canvas_corner" : DOWN+RIGHT,
"zoomed_canvas_frame_shape" : (3, 4),
}
def construct(self):
self.add_plane()
self.draw_graph()
self.emphasize_meaning_of_points()
self.zoom_in()
self.show_tiny_step()
self.ask_about_derivatives()
self.differentiate_lhs()
self.differentiate_rhs()
self.put_step_on_curve()
self.emphasize_equality()
self.manipulate_to_find_dy_dx()
def add_plane(self):
formula = TexMobject("\\sin(x)y^2 = x")
formula.to_corner(UP+LEFT)
formula.add_background_rectangle()
plane = NumberPlane(
space_unit_to_x_unit = 0.75,
x_radius = FRAME_WIDTH,
)
plane.fade()
plane.add_coordinates()
self.add(formula)
self.play(Write(plane, run_time = 2), Animation(formula))
self.wait()
self.plane = plane
self.formula = formula
self.lhs = VGroup(*formula[1][:8])
self.rhs = VGroup(formula[1][-1])
def draw_graph(self):
graphs = VGroup(*[
FunctionGraph(
lambda x : u*np.sqrt(x/np.sin(x)),
num_steps = 200,
x_min = x_min+0.1,
x_max = x_max-0.1,
)
for u in [-1, 1]
for x_min, x_max in [
(-4*np.pi, -2*np.pi),
(-np.pi, np.pi),
(2*np.pi, 4*np.pi),
]
])
graphs.stretch(self.plane.space_unit_to_x_unit, dim = 0)
self.play(
ShowCreation(
graphs,
run_time = 3,
submobject_mode = "all_at_once"
),
Animation(self.formula)
)
self.wait()
self.graphs = graphs
def emphasize_meaning_of_points(self):
graph = self.graphs[4]
dot = Dot(color = self.example_color)
label = TexMobject("(x, y)")
label.add_background_rectangle()
label.set_color(self.example_color)
def update_dot(dot, alpha):
prop = interpolate(0.9, 0.1, alpha)
point = graph.point_from_proportion(prop)
dot.move_to(point)
return dot
def update_label(label):
point = dot.get_center()
vect = np.array(point)/get_norm(point)
vect[0] *= 2
vect[1] *= -1
label.move_to(
point + vect*0.4*label.get_width()
)
update_dot(dot, 0)
update_label(label)
self.play(
ShowCreation(dot),
Write(label),
run_time = 1
)
self.play(
UpdateFromAlphaFunc(dot, update_dot),
UpdateFromFunc(label, update_label),
run_time = 3,
)
self.wait()
self.play(*[
ApplyMethod(
label[1][i].copy().move_to, self.formula[1][j],
run_time = 3,
rate_func = squish_rate_func(smooth, count/6., count/6.+2./3)
)
for count, (i, j) in enumerate([(1, 4), (1, 9), (3, 6)])
])
movers = self.get_mobjects_from_last_animation()
self.wait()
self.play(
UpdateFromAlphaFunc(dot, update_dot),
UpdateFromFunc(label, update_label),
run_time = 3,
rate_func = lambda t : 1-smooth(t)
)
self.wait()
self.play(*[
ApplyMethod(mover.set_fill, None, 0, remover = True)
for mover in movers
])
self.dot = dot
self.label = label
def zoom_in(self):
dot = self.dot
label = self.label
self.activate_zooming()
self.little_rectangle.scale(self.zoom_factor)
self.little_rectangle.move_to(dot)
self.wait()
for mob in VGroup(dot, label), self.little_rectangle:
self.play(
ApplyMethod(
mob.scale, 1./self.zoom_factor,
method_kwargs = {"about_point" : dot.get_center()},
run_time = 1,
)
)
self.wait()
def show_tiny_step(self):
dot = self.dot
label = self.label
point = dot.get_center()
step_vect = 1.2*(UP+LEFT)/float(self.zoom_factor)
new_point = point + step_vect
interim_point = new_point[0]*RIGHT + point[1]*UP
dx_line = Line(point, interim_point, color = GREEN)
dy_line = Line(interim_point, new_point, color = RED)
for line, tex, vect in (dx_line, "dx", DOWN), (dy_line, "dy", LEFT):
label = TexMobject(tex)
label.next_to(line, vect, buff = SMALL_BUFF)
label.set_color(line.get_color())
label.scale(1./self.zoom_factor, about_point = line.get_center())
label.add_background_rectangle()
line.label = label
arrow = Arrow(
point, new_point, buff = 0,
tip_length = 0.15/self.zoom_factor,
color = WHITE
)
self.play(ShowCreation(arrow))
for line in dx_line, dy_line:
self.play(ShowCreation(line), Animation(arrow))
self.play(Write(line.label, run_time = 1))
self.wait()
self.step_group = VGroup(
arrow, dx_line, dx_line.label, dy_line, dy_line.label
)
def ask_about_derivatives(self):
formula = self.formula
lhs, rhs = self.lhs, self.rhs
word = TextMobject("Change?")
word.add_background_rectangle()
word.next_to(
Line(lhs.get_center(), rhs.get_center()),
DOWN, buff = 1.5*LARGE_BUFF
)
arrows = VGroup(*[
Arrow(word, part)
for part in (lhs, rhs)
])
self.play(FocusOn(formula))
self.play(
Write(word),
ShowCreation(arrows)
)
self.wait()
self.play(*list(map(FadeOut, [word, arrows])))
def differentiate_lhs(self):
formula = self.formula
lhs = self.lhs
brace = Brace(lhs, DOWN, buff = SMALL_BUFF)
sine_x = VGroup(*lhs[:6])
sine_rect = BackgroundRectangle(sine_x)
y_squared = VGroup(*lhs[6:])
mnemonic = TextMobject(
"``",
"Left", " d-Right", " + ",
"Right", " d-Left"
"''",
arg_separator = ""
)
mnemonic.set_color_by_tex("d-Right", RED)
mnemonic.set_color_by_tex("d-Left", GREEN)
mnemonic.add_background_rectangle()
mnemonic.set_width(FRAME_X_RADIUS-2*MED_LARGE_BUFF)
mnemonic.next_to(ORIGIN, UP)
mnemonic.to_edge(LEFT)
derivative = TexMobject(
"\\sin(x)", "(2y\\,dy)", "+",
"y^2", "(\\cos(x)\\,dx)",
)
derivative.set_color_by_tex("dx", GREEN)
derivative.set_color_by_tex("dy", RED)
derivative.set_width(FRAME_X_RADIUS - 2*MED_LARGE_BUFF)
derivative.next_to(
brace, DOWN,
buff = MED_LARGE_BUFF,
aligned_edge = LEFT
)
derivative_rects = [
BackgroundRectangle(VGroup(*subset))
for subset in (derivative[:2], derivative[2:])
]
derivative_rects[1].stretch(1.05, dim = 0)
self.play(GrowFromCenter(brace))
self.play(Write(mnemonic))
self.wait()
pairs = [
(sine_rect, derivative_rects[0]),
(sine_x, derivative[0]),
(y_squared, derivative[1]),
(sine_rect, derivative_rects[1]),
(y_squared, derivative[2]),
(y_squared, derivative[3]),
(sine_x, derivative[4]),
]
for pairs_subset in pairs[:3], pairs[3:]:
self.play(*[
ReplacementTransform(m1.copy(), m2, path_arc = np.pi/2)
for m1, m2 in pairs_subset
])
self.wait()
self.play(Indicate(pairs_subset[-1][1]))
self.wait()
self.wait()
self.play(FadeOut(mnemonic))
self.lhs_derivative = VGroup(*derivative_rects+[derivative])
self.lhs_brace = brace
def differentiate_rhs(self):
lhs_derivative = self.lhs_derivative
lhs_brace = self.lhs_brace
rhs = self.rhs
equals, dx = equals_dx = TexMobject("=", "dx")
equals_dx.scale(0.9)
equals_dx.set_color_by_tex("dx", GREEN)
equals_dx.add_background_rectangle()
equals_dx.next_to(lhs_derivative, RIGHT, buff = SMALL_BUFF)
circle = Circle(color = GREEN)
circle.replace(self.rhs)
circle.scale_in_place(1.7)
arrow = Arrow(rhs.get_right(), dx.get_top())
arrow.set_color(GREEN)
self.play(ReplacementTransform(lhs_brace, circle))
self.play(ShowCreation(arrow))
self.play(Write(equals_dx))
self.wait()
self.play(*list(map(FadeOut, [circle, arrow])))
self.equals_dx = equals_dx
def put_step_on_curve(self):
dot = self.dot
point = dot.get_center()
graph = self.graphs[4]
arrow, dx_line, dx_line.label, dy_line, dy_line.label = self.step_group
#Find graph point at right x_val
arrow_end = arrow.get_end()
graph_points = [
graph.point_from_proportion(alpha)
for alpha in np.linspace(0, 1, 1000)
]
distances = np.apply_along_axis(
lambda p : np.abs(p[0] - arrow_end[0]),
1, graph_points
)
index = np.argmin(distances)
new_end_point = graph_points[index]
lil_rect = self.little_rectangle
self.play(
arrow.put_start_and_end_on, point, new_end_point,
dy_line.put_start_and_end_on,
dy_line.get_start(), new_end_point,
MaintainPositionRelativeTo(dy_line.label, dy_line),
lil_rect.shift, lil_rect.get_height()*DOWN/3,
run_time = 2
)
self.wait(2)
def emphasize_equality(self):
self.play(FocusOn(self.lhs))
self.wait()
for mob in self.lhs, self.rhs:
self.play(Indicate(mob))
self.wait()
def manipulate_to_find_dy_dx(self):
full_derivative = VGroup(
self.lhs_derivative, self.equals_dx
)
brace = Brace(full_derivative, DOWN, buff = SMALL_BUFF)
words = brace.get_text(
"Commonly, solve for", "$dy/dx$",
buff = SMALL_BUFF
)
VGroup(*words[1][:2]).set_color(RED)
VGroup(*words[1][3:]).set_color(GREEN)
words.add_background_rectangle()
self.play(GrowFromCenter(brace))
self.play(Write(words))
self.wait()
randy = Randolph()
randy.to_corner(DOWN+LEFT)
randy.look_at(full_derivative)
self.play(FadeIn(randy))
self.play(randy.change_mode, "confused")
self.play(Blink(randy))
self.wait(2)
self.play(randy.change_mode, "pondering")
self.play(Blink(randy))
self.wait()
class AskAboutNaturalLog(TeacherStudentsScene):
def construct(self):
exp_deriv = TexMobject("\\frac{d(e^x)}{dx} = e^x")
for i in 2, 3, 9, 10:
exp_deriv[i].set_color(BLUE)
log_deriv = TexMobject("\\frac{d(\\ln(x))}{dx} = ???")
VGroup(*log_deriv[2:2+5]).set_color(GREEN)
for deriv in exp_deriv, log_deriv:
deriv.next_to(self.get_teacher().get_corner(UP+LEFT), UP)
self.teacher_says(
"""We can find
new derivatives""",
target_mode = "hooray"
)
self.change_student_modes(*["happy"]*3)
self.play(RemovePiCreatureBubble(
self.get_teacher(),
target_mode = "raise_right_hand"
))
self.play(Write(exp_deriv))
self.wait()
self.play(
Write(log_deriv),
exp_deriv.next_to, log_deriv, UP, LARGE_BUFF,
*[
ApplyMethod(pi.change_mode, "confused")
for pi in self.get_pi_creatures()
]
)
self.wait(3)
class DerivativeOfNaturalLog(ZoomedScene):
CONFIG = {
"zoom_factor" : 10,
"zoomed_canvas_corner" : DOWN+RIGHT,
"example_color" : MAROON_B,
}
def construct(self):
should_skip_animations = self.skip_animations
self.skip_animations = True
self.add_plane()
self.draw_graph()
self.describe_as_implicit_curve()
self.slope_gives_derivative()
self.rearrange_equation()
self.take_derivative()
self.show_tiny_nudge()
self.note_derivatives()
self.solve_for_dy_dx()
self.skip_animations = should_skip_animations
self.show_slope_above_x()
def add_plane(self):
plane = NumberPlane()
plane.fade()
plane.add_coordinates()
self.add(plane)
self.plane = plane
def draw_graph(self):
graph = FunctionGraph(
np.log,
x_min = 0.01,
x_max = FRAME_X_RADIUS,
num_steps = 100
)
formula = TexMobject("y = \\ln(x)")
formula.next_to(ORIGIN, LEFT, buff = MED_LARGE_BUFF)
formula.to_edge(UP)
formula.add_background_rectangle()
self.add(formula)
self.play(ShowCreation(graph))
self.wait()
self.formula = formula
self.graph = graph
def describe_as_implicit_curve(self):
formula = self.formula #y = ln(x)
graph = self.graph
dot = Dot(color = self.example_color)
label = TexMobject("(x, y)")
label.add_background_rectangle()
label.set_color(self.example_color)
def update_dot(dot, alpha):
prop = interpolate(0.1, 0.7, alpha)
point = graph.point_from_proportion(prop)
dot.move_to(point)
return dot
def update_label(label):
point = dot.get_center()
vect = point - FRAME_Y_RADIUS*(DOWN+RIGHT)
vect = vect/get_norm(vect)
label.move_to(
point + vect*0.5*label.get_width()
)
update_dot(dot, 0)
update_label(label)
self.play(*list(map(FadeIn, [dot, label])))
self.play(
UpdateFromAlphaFunc(dot, update_dot),
UpdateFromFunc(label, update_label),
run_time = 3,
)
self.wait()
xy_start = VGroup(label[1][1], label[1][3]).copy()
xy_end = VGroup(formula[1][5], formula[1][0]).copy()
xy_end.set_color(self.example_color)
self.play(Transform(
xy_start, xy_end,
run_time = 2,
))
self.wait()
self.play(
UpdateFromAlphaFunc(dot, update_dot),
UpdateFromFunc(label, update_label),
run_time = 3,
rate_func = lambda t : 1-0.6*smooth(t),
)
self.play(*list(map(FadeOut, [xy_start, label])))
self.dot = dot
def slope_gives_derivative(self):
dot = self.dot
point = dot.get_center()
line = Line(LEFT, RIGHT).scale(FRAME_X_RADIUS)
slope = 1./point[0]
line.rotate(np.arctan(slope))
line.move_to(point)
new_point = line.point_from_proportion(0.6)
interim_point = point[0]*RIGHT + new_point[1]*UP
dy_line = Line(point, interim_point, color = RED)
dx_line = Line(interim_point, new_point, color = GREEN)
equation = TexMobject(
"\\text{Slope} = ",
"\\frac{dy}{dx} = ",
"\\frac{d(\\ln(x))}{dx}",
)
VGroup(*equation[1][:2]).set_color(RED)
VGroup(*equation[2][:8]).set_color(RED)
VGroup(*equation[1][3:5]).set_color(GREEN)
VGroup(*equation[2][-2:]).set_color(GREEN)
for part in equation:
rect = BackgroundRectangle(part)
rect.stretch_in_place(1.2, 0)
part.add_to_back(rect)
equation.scale(0.8)
equation.next_to(ORIGIN, RIGHT)
equation.to_edge(UP, buff = MED_SMALL_BUFF)
self.play(
GrowFromCenter(line),
Animation(dot)
)
self.play(ShowCreation(VGroup(dy_line, dx_line)))
for part in equation:
self.play(Write(part, run_time = 2))
self.wait()
self.dx_line, self.dy_line = dx_line, dy_line
self.slope_equation = equation
self.tangent_line = line
def rearrange_equation(self):
formula = self.formula
y, eq = formula[1][:2]
ln = VGroup(*formula[1][2:4])
x = formula[1][5]
new_formula = TexMobject("e", "^y", "=", "x")
e, new_y, new_eq, new_x = new_formula
new_formula.next_to(
formula, DOWN,
buff = MED_LARGE_BUFF,
)
rect = BackgroundRectangle(new_formula)
y = new_y.copy().replace(y)
self.play(Indicate(formula, scale_factor = 1))
self.play(ReplacementTransform(ln.copy(), e))
self.play(ReplacementTransform(y, new_y))
self.play(ReplacementTransform(eq.copy(), new_eq))
self.play(
FadeIn(rect),
Animation(VGroup(e, new_y, new_eq)),
ReplacementTransform(x.copy(), new_x)
)
self.wait(2)
for mob in e, new_y, new_x:
self.play(Indicate(mob))
self.wait()
self.new_formula = new_formula
def take_derivative(self):
new_formula = self.new_formula
e, y, eq, x = new_formula
derivative = TexMobject("e", "^y", "\\,dy", "=", "dx")
new_e, new_y, dy, new_eq, dx = derivative
derivative.next_to(new_formula, DOWN, MED_LARGE_BUFF)
derivative.add_background_rectangle()
dx.set_color(GREEN)
dy.set_color(RED)
pairs = [
(VGroup(e, y), VGroup(new_e, new_y)),
(new_y, dy),
(eq, new_eq),
(x, dx)
]
for start, target in pairs:
self.play(
ReplacementTransform(start.copy(), target)
)
self.play(FadeIn(derivative[0]), Animation(derivative[1]))
self.remove(derivative, pairs[0][1])
self.add(derivative)
self.wait()
self.derivative = derivative
def show_tiny_nudge(self):
dot = self.dot
point = dot.get_center()
dx_line = self.dx_line
dy_line = self.dy_line
group = VGroup(dot, dx_line, dy_line)
self.play(group.scale, 1./self.zoom_factor, point)
for line, tex, vect in (dx_line, "dx", UP), (dy_line, "dy", LEFT):
label = TexMobject(tex)
label.add_background_rectangle()
label.next_to(line, vect, buff = SMALL_BUFF)
label.set_color(line.get_color())
label.scale(
1./self.zoom_factor,
about_point = line.get_center()
)
line.label = label
self.activate_zooming()
lil_rect = self.little_rectangle
lil_rect.move_to(group)
lil_rect.scale_in_place(self.zoom_factor)
self.play(lil_rect.scale_in_place, 1./self.zoom_factor)
self.play(Write(dx_line.label))
self.play(Write(dy_line.label))
self.wait()
def note_derivatives(self):
e, y, dy, eq, dx = self.derivative[1]
self.play(FocusOn(e))
self.play(Indicate(VGroup(e, y, dy)))
self.wait()
self.play(Indicate(dx))
self.wait()
def solve_for_dy_dx(self):
e, y, dy, eq, dx = self.derivative[1]
ey_group = VGroup(e, y)
original_rect = self.derivative[0]
rearranged = TexMobject(
"{dy \\over ", " dx}", "=", "{1 \\over ", "e", "^y}"
)
new_dy, new_dx, new_eq, one_over, new_e, new_y = rearranged
new_ey_group = VGroup(new_e, new_y)
new_dx.set_color(GREEN)
new_dy.set_color(RED)
rearranged.shift(eq.get_center() - new_eq.get_center())
rearranged.shift(MED_SMALL_BUFF*DOWN)
new_rect = BackgroundRectangle(rearranged)
self.play(*[
ReplacementTransform(
m1, m2,
run_time = 2,
path_arc = -np.pi/2,
)
for m1, m2 in [
(original_rect, new_rect),
(dx, new_dx),
(dy, new_dy),
(eq, new_eq),
(ey_group, new_ey_group),
(e.copy(), one_over)
]
])
self.wait()
#Change denominator
e, y, eq, x = self.new_formula
ey_group = VGroup(e, y).copy()
ey_group.set_color(YELLOW)
x_copy = x.copy()
self.play(new_ey_group.set_color, YELLOW)
self.play(Transform(new_ey_group, ey_group))
self.play(
new_ey_group.set_color, WHITE,
x_copy.set_color, YELLOW
)
self.play(x_copy.next_to, one_over, DOWN, MED_SMALL_BUFF)
self.wait(2)
equals_one_over_x = VGroup(
new_eq, one_over, x_copy
).copy()
rect = BackgroundRectangle(equals_one_over_x)
rect.stretch_in_place(1.1, dim = 0)
equals_one_over_x.add_to_back(rect)
self.play(
equals_one_over_x.next_to,
self.slope_equation, RIGHT, 0,
run_time = 2
)
self.wait()
def show_slope_above_x(self):
line = self.tangent_line
start_x = line.get_center()[0]
target_x = 0.2
graph = FunctionGraph(
lambda x : 1./x,
x_min = 0.1,
x_max = FRAME_X_RADIUS,
num_steps = 100,
color = PINK,
)
def update_line(line, alpha):
x = interpolate(start_x, target_x, alpha)
point = x*RIGHT + np.log(x)*UP
angle = np.arctan(1./x)
line.rotate(angle - line.get_angle())
line.move_to(point)
self.play(UpdateFromAlphaFunc(
line, update_line,
rate_func = there_and_back,
run_time = 6
))
self.wait()
self.play(ShowCreation(graph, run_time = 3))
self.wait()
self.play(UpdateFromAlphaFunc(
line, update_line,
rate_func = there_and_back,
run_time = 6
))
self.wait()
class FinalWords(TeacherStudentsScene):
def construct(self):
words = TextMobject(
"This is a peek into \\\\",
"Multivariable", "calculus"
)
mvc = VGroup(*words[1:])
words.set_color_by_tex("Multivariable", YELLOW)
formula = TexMobject("f(x, y) = \\sin(x)y^2")
formula.next_to(self.get_teacher().get_corner(UP+LEFT), UP)
self.teacher_says(words)
self.change_student_modes("erm", "hooray", "sassy")
self.play(
FadeOut(self.teacher.bubble),
FadeOut(VGroup(*words[:1])),
mvc.to_corner, UP+LEFT,
self.teacher.change_mode, "raise_right_hand",
self.teacher.look_at, formula,
Write(formula, run_time = 2),
)
self.change_student_modes("pondering", "confused", "thinking")
self.wait(3)
##Show series
series = VideoSeries()
series.to_edge(UP)
video = series[5]
lim = TexMobject("\\lim_{h \\to 0} \\frac{f(x+h)-f(x)}{h}")
self.play(
FadeOut(mvc),
FadeOut(formula),
self.teacher.change_mode, "plain",
FadeIn(
series, run_time = 2,
submobject_mode = "lagged_start",
),
)
self.play(
video.set_color, YELLOW,
video.shift, video.get_height()*DOWN/2
)
lim.next_to(video, DOWN)
self.play(
Write(lim),
*it.chain(*[
[pi.change_mode, "pondering", pi.look_at, lim]
for pi in self.get_pi_creatures()
])
)
self.wait(3)
class Chapter6PatreonThanks(PatreonThanks):
CONFIG = {
"specific_patrons" : [
"Ali Yahya",
"Meshal Alshammari",
"CrypticSwarm ",
"Nathan Pellegrin",
"Karan Bhargava",
"Justin Helps",
"Ankit Agarwal",
"Yu Jun",
"Dave Nicponski",
"Damion Kistler",
"Juan Benet",
"Othman Alikhan",
"Justin Helps",
"Markus Persson",
"Dan Buchoff",
"Derek Dai",
"Joseph John Cox",
"Luc Ritchie",
"Daan Smedinga",
"Jonathan Eppele",
"Nils Schneider",
"Albert Nguyen",
"Mustafa Mahdi",
"Mathew Bramson",
"Guido Gambardella",
"Jerry Ling",
"Mark Govea",
"Vecht",
"Shimin Kuang",
"Rish Kundalia",
"Achille Brighton",
"Kirk Werklund",
"Ripta Pasay",
"Felipe Diniz",
]
}
class Thumbnail(AlternateExample):
def construct(self):
title = VGroup(*list(map(TextMobject, [
"Implicit", "Differentiation"
])))
title.arrange_submobjects(DOWN)
title.scale(3)
title.next_to(ORIGIN, UP)
for word in title:
word.add_background_rectangle()
self.add_plane()
self.draw_graph()
self.graphs.set_stroke(width = 8)
self.remove(self.formula)
self.add(title)