Up to patron-posted draft of eoc/chapter1.py

This commit is contained in:
Grant Sanderson
2016-11-14 15:06:44 -08:00
parent 4d60a245f6
commit c7f7f3c596
2 changed files with 444 additions and 64 deletions

View File

@ -202,13 +202,42 @@ class CircleScene(PiCreatureScene):
###################### ######################
class PatronsOnly(Scene):
def construct(self):
morty = Mortimer()
morty.shift(2*DOWN)
title = TextMobject("""
This is a draft
for patrons only
""")
title.highlight(RED)
title.scale(2)
title.to_edge(UP)
self.add(morty)
self.play(
Write(title),
morty.change_mode, "wave_1"
)
self.play(Blink(morty))
self.play(
morty.change_mode, "pondering",
morty.look_at, title
)
self.play(Blink(morty))
self.dither()
class OpeningQuote(Scene): class OpeningQuote(Scene):
CONFIG = { CONFIG = {
"quote" : """ "quote" : [
The art of doing mathematics is finding """The art of doing mathematics is finding
that special case that contains all the that """, "special case",
germs of generality. """that contains all the
""", germs of generality."""
],
"highlighted_quote_terms" : {
"special case" : BLUE
},
"author" : "David Hilbert" "author" : "David Hilbert"
} }
def construct(self): def construct(self):
@ -218,17 +247,25 @@ class OpeningQuote(Scene):
self.play(FadeIn( self.play(FadeIn(
quote, quote,
submobject_mode = "lagged_start", submobject_mode = "lagged_start",
run_time = 2 run_time = 4
)) ))
self.dither(2) self.dither(2)
self.play(Write(author, run_time = 4)) self.play(Write(author, run_time = 3))
self.dither() self.dither()
def get_quote(self): def get_quote(self):
if isinstance(self.quote, str):
quote = TextMobject( quote = TextMobject(
"``%s''"%self.quote.strip(), "``%s''"%self.quote.strip(),
alignment = "", alignment = "",
) )
else:
words = list(self.quote)
words[0] = "``%s"%words[0]
words[-1] += "''"
quote = TextMobject(*words, alignment = "")
for term, color in self.highlighted_quote_terms.items():
quote.highlight_by_tex(term, color)
quote.to_edge(UP) quote.to_edge(UP)
return quote return quote
@ -1170,11 +1207,11 @@ class BuildToDADR(CircleScene):
self.play(self.pi_creature.change_mode, "guilty") self.play(self.pi_creature.change_mode, "guilty")
self.dither() self.dither()
new_bubble = self.pi_creature.get_bubble("speech", height = 6) new_bubble = self.pi_creature.get_bubble("speech")
new_bubble.set_fill(BLACK, opacity = 0.8) new_bubble.set_fill(BLACK, opacity = 0.8)
new_bubble.write("But it gets \\\\ less wrong!")
new_bubble.resize_to_content() new_bubble.resize_to_content()
new_bubble.pin_to(self.pi_creature) new_bubble.pin_to(self.pi_creature)
new_bubble.write("But it gets \\\\ less wrong!")
self.play( self.play(
FadeOut(bubble), FadeOut(bubble),
@ -1193,8 +1230,8 @@ class NameDerivative(IntroduceTinyChangeInArea):
self.change_nudge_label() self.change_nudge_label()
self.name_derivative_for_cricle() self.name_derivative_for_cricle()
self.interpret_geometrically() self.interpret_geometrically()
self.replace_words()
self.show_limiting_process() self.show_limiting_process()
self.reference_approximation()
self.emphasize_equality() self.emphasize_equality()
def change_nudge_label(self): def change_nudge_label(self):
@ -1255,6 +1292,7 @@ class NameDerivative(IntroduceTinyChangeInArea):
self.dither() self.dither()
self.dArea_fom = dArea_fom self.dArea_fom = dArea_fom
self.words = words self.words = words
self.two_pi_R = two_pi_R
def interpret_geometrically(self): def interpret_geometrically(self):
target_formula = TexMobject( target_formula = TexMobject(
@ -1298,21 +1336,9 @@ class NameDerivative(IntroduceTinyChangeInArea):
self.play(Transform(circum_circle.copy(), circum_form)) self.play(Transform(circum_circle.copy(), circum_form))
self.change_mode("happy") self.change_mode("happy")
def replace_words(self):
new_words = TextMobject(
"Ask what this\\\\",
"ratio approaches."
)
new_words.move_to(self.words)
self.play(
Transform(self.words, new_words),
self.pi_creature.change_mode, "pondering"
)
self.dither()
def show_limiting_process(self): def show_limiting_process(self):
big_dR = 0.3 big_dR = 0.3
small_dR = 0.05 small_dR = 0.01
big_ring = self.get_ring(self.radius, big_dR) big_ring = self.get_ring(self.radius, big_dR)
small_ring = self.get_ring(self.radius, small_dR) small_ring = self.get_ring(self.radius, small_dR)
big_nudge_line = self.nudge_line.copy().scale_to_fit_width(big_dR) big_nudge_line = self.nudge_line.copy().scale_to_fit_width(big_dR)
@ -1322,42 +1348,73 @@ class NameDerivative(IntroduceTinyChangeInArea):
new_nudge_arrow = Arrow(self.nudge_label, big_nudge_line) new_nudge_arrow = Arrow(self.nudge_label, big_nudge_line)
small_nudge_arrow = Arrow(self.nudge_label, small_nudge_line) small_nudge_arrow = Arrow(self.nudge_label, small_nudge_line)
ring_group = VGroup(self.outer_ring, self.nudge_line, self.nudge_arrow)
ring_group.save_state()
big_group = VGroup(big_ring, big_nudge_line, new_nudge_arrow)
small_group = VGroup(small_ring, small_nudge_line, small_nudge_arrow)
fracs = VGroup()
sample_dRs = [0.3, 0.1, 0.01]
for dR in sample_dRs:
dA = 2*np.pi*dR + np.pi*(dR**2)
frac = TexMobject("\\frac{%.3f}{%.2f}"%(dA, dR))
VGroup(*frac[:5]).highlight(self.outer_ring.get_color())
VGroup(*frac[6:]).highlight(self.dR_color)
fracs.add(frac)
fracs.add(TexMobject("\\cdots \\rightarrow"))
fracs.add(TexMobject("???"))
fracs[-1].gradient_highlight(self.dR_color, self.outer_ring.get_color())
fracs.arrange_submobjects(RIGHT, buff = 2*MED_BUFF)
fracs.to_corner(DOWN+LEFT)
arrows = VGroup()
for frac in fracs[:len(sample_dRs)] + [fracs[-1]]:
arrow = Arrow(self.words.get_bottom(), frac.get_top())
arrow.highlight(WHITE)
if frac is fracs[-1]:
check = TexMobject("\\checkmark")
check.highlight(GREEN)
check.next_to(arrow.get_center(), UP+RIGHT, SMALL_BUFF)
arrow.add(check)
else:
cross = TexMobject("\\times")
cross.highlight(RED)
cross.move_to(arrow.get_center())
cross.set_stroke(RED, width = 5)
arrow.add(cross)
arrows.add(arrow)
self.play( self.play(
Transform(self.outer_ring, big_ring), Transform(ring_group, big_group),
Transform(self.nudge_line, big_nudge_line), self.pi_creature.change_mode, "sassy"
Transform(self.nudge_arrow, new_nudge_arrow),
self.pi_creature.change_mode, "pondering"
) )
big_trap = self.outer_ring.copy() for n, frac in enumerate(fracs):
big_trap.dR = big_dR anims = [FadeIn(frac)]
small_trap = self.get_unwrapped(small_ring.copy()) num_fracs = len(sample_dRs)
for trap in big_trap, small_trap: if n < num_fracs:
trap.set_fill(opacity = 0.5) anims.append(ShowCreation(arrows[n]))
self.unwrap_ring(big_trap) anims.append(Transform(
small_trap.move_to(big_trap) ring_group, small_group,
big_rect, small_rect = [ rate_func = lambda t : t*(1./(num_fracs-n)),
Rectangle( run_time = 2
height = trap.get_height(), ))
width = 2*np.pi*self.radius, elif n > num_fracs:
stroke_width = 0, anims.append(ShowCreation(arrows[-1]))
fill_color = BLUE, self.play(*anims)
fill_opacity = 0.5 self.dither(2)
).move_to(trap)
for trap in big_trap, small_trap
]
self.play(FadeIn(big_rect))
self.play( self.play(
Transform(self.outer_ring, small_ring), FadeOut(arrows),
Transform(self.nudge_line, small_nudge_line), ring_group.restore,
Transform(self.nudge_arrow, small_nudge_arrow), self.pi_creature.change_mode, "happy",
Transform(big_trap, small_trap),
Transform(big_rect, small_rect),
run_time = 6,
rate_func = None
) )
self.change_mode("happy")
self.dither() self.dither()
self.last_mover = VGroup(big_trap, big_rect)
def reference_approximation(self):
ring_copy = self.outer_ring.copy()
self.unwrap_ring(ring_copy)
self.dither()
self.last_mover = ring_copy
def emphasize_equality(self): def emphasize_equality(self):
equals = self.dArea_fom[-2] equals = self.dArea_fom[-2]
@ -1366,9 +1423,15 @@ class NameDerivative(IntroduceTinyChangeInArea):
self.remove(self.last_mover) self.remove(self.last_mover)
self.play( self.play(
equals.scale_in_place, 1.5, equals.scale_in_place, 1.5,
equals.highlight, GREEN equals.highlight, GREEN,
rate_func = there_and_back,
run_time = 2
)
self.play(
self.two_pi_R.set_stroke, YELLOW, 3,
rate_func = there_and_back,
run_time = 2
) )
self.play(equals.scale_in_place, 1./1.5)
self.dither() self.dither()
new_words = TextMobject( new_words = TextMobject(
@ -1392,6 +1455,7 @@ class DerivativeAsTangentLine(ZoomedScene):
self.setup_axes() self.setup_axes()
self.show_zoomed_in_steps() self.show_zoomed_in_steps()
self.show_tangent_lines() self.show_tangent_lines()
self.state_commonality()
def setup_axes(self): def setup_axes(self):
x_axis = NumberLine( x_axis = NumberLine(
@ -1408,6 +1472,7 @@ class DerivativeAsTangentLine(ZoomedScene):
x_axis.add_numbers(1, 2, 3, 4) x_axis.add_numbers(1, 2, 3, 4)
x_label = TexMobject("R") x_label = TexMobject("R")
x_label.next_to(x_axis, RIGHT+UP, buff = SMALL_BUFF) x_label.next_to(x_axis, RIGHT+UP, buff = SMALL_BUFF)
self.x_axis_label = x_label
y_axis = NumberLine( y_axis = NumberLine(
x_min = -2, x_min = -2,
@ -1559,6 +1624,7 @@ class DerivativeAsTangentLine(ZoomedScene):
self.play(ShowCreation(line)) self.play(ShowCreation(line))
self.dither() self.dither()
self.note_R_value_of_point()
alphas = np.arange(0, 1, 0.01) alphas = np.arange(0, 1, 0.01)
graph_points = map(self.graph.point_from_proportion, alphas) graph_points = map(self.graph.point_from_proportion, alphas)
@ -1588,6 +1654,65 @@ class DerivativeAsTangentLine(ZoomedScene):
shift_everything_to_alpha(0.8, 4) shift_everything_to_alpha(0.8, 4)
self.dither() self.dither()
def note_R_value_of_point(self):
R = self.R_to_zoom_in_on
point = self.graph_point(R)
R_axis_point = point[0]*RIGHT + 2.5*DOWN
dashed_line = DashedLine(point, R_axis_point, color = RED)
dot = Dot(R_axis_point, color = RED)
arrow = Arrow(
self.x_axis_label.get_left(),
dot,
buff = SMALL_BUFF
)
self.play(ShowCreation(dashed_line))
self.play(ShowCreation(dot))
self.play(ShowCreation(arrow))
self.play(dot.scale_in_place, 2, rate_func = there_and_back)
self.dither()
self.play(*map(FadeOut, [dashed_line, dot, arrow]))
def state_commonality(self):
morty = Mortimer()
morty.scale(0.7)
morty.to_edge(DOWN).shift(2*RIGHT)
bubble = morty.get_bubble("speech", height = 2)
bubble.set_fill(BLACK, opacity = 0.8)
bubble.shift(0.5*DOWN)
bubble.write("This is the standard view")
self.play(FadeIn(morty))
self.play(
ShowCreation(bubble),
Write(bubble.content),
morty.change_mode, "surprised"
)
self.play(Blink(morty))
self.dither()
new_words = TextMobject("Which is...fine...")
new_words.move_to(bubble.content, RIGHT)
self.play(
bubble.stretch_to_fit_width, 5,
bubble.shift, RIGHT,
Transform(bubble.content, new_words),
morty.change_mode, "hesitant"
)
self.play(Blink(morty))
self.dither()
class SimpleConfusedPi(Scene):
def construct(self):
randy = Randolph()
confused = Randolph(mode = "confused")
for pi in randy, confused:
pi.flip()
pi.look(UP+LEFT)
pi.scale(2)
pi.rotate(np.pi/2)
self.play(Transform(randy, confused))
self.dither()
class TangentLinesAreNotEverything(TeacherStudentsScene): class TangentLinesAreNotEverything(TeacherStudentsScene):
def construct(self): def construct(self):
self.teacher_says(""" self.teacher_says("""
@ -1687,6 +1812,7 @@ class IntroduceConcentricRings(CircleScene):
area_sum.to_edge(RIGHT) area_sum.to_edge(RIGHT)
area_sum.to_edge(UP, buff = MED_BUFF) area_sum.to_edge(UP, buff = MED_BUFF)
dots_equals_area[-1].shift(0.1*UP) dots_equals_area[-1].shift(0.1*UP)
self.area_sum_rhs = dots_equals_area[-1]
# start_rings.set_fill(opacity = 0.3) # start_rings.set_fill(opacity = 0.3)
self.play( self.play(
@ -1797,6 +1923,31 @@ class IntroduceConcentricRings(CircleScene):
self.pi_creature.change_mode, "pondering" self.pi_creature.change_mode, "pondering"
) )
self.dither(2) self.dither(2)
last = VMobject()
last.save_state()
for ring in self.rings:
ring.save_state()
target = ring.copy()
target.set_fill(opacity = 1)
self.play(
last.restore,
Transform(ring, target),
Animation(self.foreground_group),
run_time = 0.5
)
last = ring
self.play(last.restore)
self.dither()
ghost = self.rings.copy()
for mob in self.area_sum_rhs, self.two_pi_r:
ghost.set_fill(opacity = 0.1)
self.play(Transform(ghost, mob))
self.dither()
self.remove(ghost)
self.dither()
self.play(FadeOut(formula_q)) self.play(FadeOut(formula_q))
self.play(Write(int_sym)) self.play(Write(int_sym))
self.dither() self.dither()
@ -1824,6 +1975,13 @@ class IntroduceConcentricRings(CircleScene):
self.play(Write(equals_pi_R_squared)) self.play(Write(equals_pi_R_squared))
self.dither() self.dither()
self.equals = equals_pi_R_squared[0] self.equals = equals_pi_R_squared[0]
self.integral_terms = VGroup(
self.integral_expression[1],
self.integral_expression[2],
self.int_lower_bound,
self.int_upper_bound,
VGroup(*equals_pi_R_squared[1:])
)
def grow_and_shrink_r_line(self, zero_target, R_target): def grow_and_shrink_r_line(self, zero_target, R_target):
self.radial_line.get_center = self.circle.get_center self.radial_line.get_center = self.circle.get_center
@ -1870,6 +2028,7 @@ class IntroduceConcentricRings(CircleScene):
self.r_label.restore, self.r_label.restore,
FadeOut(equals_0) FadeOut(equals_0)
) )
self.int_lower_bound, self.int_upper_bound = zero_target, R_target
def ask_about_approx(self): def ask_about_approx(self):
approx = TexMobject("\\approx").replace(self.equals) approx = TexMobject("\\approx").replace(self.equals)
@ -1912,7 +2071,12 @@ class IntroduceConcentricRings(CircleScene):
GrowFromCenter(int_brace), GrowFromCenter(int_brace),
Write(integral_word) Write(integral_word)
) )
self.dither(4) self.dither()
for term in self.integral_terms:
term.save_state()
self.play(term.highlight, YELLOW)
self.play(term.restore)
self.dither(3)
class AskAboutGeneralCircles(TeacherStudentsScene): class AskAboutGeneralCircles(TeacherStudentsScene):
def construct(self): def construct(self):
@ -1947,16 +2111,35 @@ class GraphIntegral(GraphScene):
"R" : 3.5, "R" : 3.5,
} }
def construct(self): def construct(self):
self.func = lambda r : 2*np.pi*r
integral = TexMobject("\\int_0^R 2\\pi r \\, dr") integral = TexMobject("\\int_0^R 2\\pi r \\, dr")
integral.to_edge(UP).shift(LEFT) integral.to_edge(UP).shift(LEFT)
self.little_r = integral[5]
self.play(Write(integral)) self.play(Write(integral))
self.dither() self.dither()
self.setup_axes() self.setup_axes()
self.show_horizontal_axis()
self.add_rectangles() self.add_rectangles()
self.thinner_rectangles() self.thinner_rectangles()
self.ask_about_area() self.ask_about_area()
def show_horizontal_axis(self):
arrows = [
Arrow(self.little_r, self.coords_to_point(*coords))
for coords in (0, 0), (self.x_max, 0)
]
moving_arrow = arrows[0].copy()
self.play(
ShowCreation(moving_arrow),
self.little_r.highlight, YELLOW
)
for arrow in reversed(arrows):
self.play(Transform(moving_arrow, arrow, run_time = 4))
self.play(
FadeOut(moving_arrow),
self.little_r.highlight, WHITE
)
def add_rectangles(self): def add_rectangles(self):
tick_height = 0.2 tick_height = 0.2
@ -2076,6 +2259,24 @@ class GraphIntegral(GraphScene):
0, self.R, dr, stroke_width = stroke_width 0, self.R, dr, stroke_width = stroke_width
) )
class MoreOnThisLater(TeacherStudentsScene):
def construct(self):
self.teacher_says("""
More details on
integrals later
""")
self.change_student_modes(
"raise_right_hand",
"raise_left_hand",
"raise_left_hand",
)
self.random_blink(2)
self.teacher_says("""
This is just
a preview
""")
self.random_blink(2)
class FundamentalTheorem(CircleScene): class FundamentalTheorem(CircleScene):
CONFIG = { CONFIG = {
"circle_corner" : ORIGIN, "circle_corner" : ORIGIN,
@ -2293,9 +2494,184 @@ class NameTheFundamentalTheorem(TeacherStudentsScene):
self.change_student_modes(*["happy"]*3) self.change_student_modes(*["happy"]*3)
self.dither(2) self.dither(2)
class CalculusInANutshell(CircleScene):
CONFIG = {
"circle_corner" : ORIGIN,
"radius" : 3,
}
def construct(self):
self.clear()
self.morph_word()
self.show_remainder_of_series()
def morph_word(self):
calculus = TextMobject("Calculus")
calculus.scale(1.5)
calculus.to_edge(UP)
dR = self.radius/float(len(calculus.split()))
rings = VGroup(*[
self.get_ring(rad, 0.95*dR)
for rad in np.arange(0, self.radius, dR)
])
for ring in rings:
ring.add(ring.copy().rotate(np.pi))
for mob in calculus, rings:
mob.gradient_highlight(BLUE, GREEN)
rings.set_stroke(width = 0)
self.play(Write(calculus))
self.dither()
self.play(Transform(
calculus, rings,
submobject_mode = "lagged_start",
run_time = 5
))
self.dither()
def show_remainder_of_series(self):
series = VideoSeries()
first = series[0]
first.set_fill(YELLOW)
first.save_state()
first.center()
first.scale_to_fit_height(SPACE_HEIGHT*2)
first.set_fill(opacity = 0)
everything = VGroup(*self.get_mobjects())
everything.generate_target()
everything.target.scale(series[1].get_height()/first.get_height())
everything.target.shift(first.saved_state.get_center())
everything.target.set_fill(opacity = 0.1)
second = series[1]
brace = Brace(second)
derivatives = brace.get_text("Derivatives")
self.play(
MoveToTarget(everything),
first.restore,
run_time = 2
)
self.play(FadeIn(
VGroup(*series[1:]),
submobject_mode = "lagged_start",
run_time = 2,
))
self.dither()
self.play(
GrowFromCenter(brace),
Write(derivatives)
)
self.dither()
class PatreonThanks(Scene):
CONFIG = {
"specific_patrons" : [
"Ali Yahya",
"Cryptic Swarm",
"Juan Batiz-Benet",
"Yu Jun",
"Othman Alikhan",
"Joseph John Cox",
"Luc Ritchie",
"Einar Johansen",
"Rish Kundalia",
"Achille Brighton",
"Kirk Werklund",
"Ripta Pasay",
"Felipe Diniz",
]
}
def construct(self):
morty = Mortimer()
morty.next_to(ORIGIN, DOWN)
n_patrons = len(self.specific_patrons)
special_thanks = TextMobject("Special thanks to:")
special_thanks.highlight(YELLOW)
special_thanks.shift(2*UP)
left_patrons = VGroup(*map(TextMobject,
self.specific_patrons[:n_patrons/2]
))
right_patrons = VGroup(*map(TextMobject,
self.specific_patrons[n_patrons/2:]
))
for patrons, vect in (left_patrons, LEFT), (right_patrons, RIGHT):
patrons.arrange_submobjects(DOWN, aligned_edge = LEFT)
patrons.next_to(special_thanks, DOWN)
patrons.to_edge(vect, buff = LARGE_BUFF)
self.play(morty.change_mode, "gracious")
self.play(Write(special_thanks, run_time = 1))
self.play(
Write(left_patrons),
morty.look_at, left_patrons
)
self.play(
Write(right_patrons),
morty.look_at, right_patrons
)
self.play(Blink(morty))
for patrons in left_patrons, right_patrons:
for index in 0, -1:
self.play(morty.look_at, patrons[index])
self.dither()
class Thumbnail(CircleScene):
CONFIG = {
"radius" : 2,
"circle_corner" : ORIGIN
}
def construct(self):
self.clear()
title = TextMobject("Essence of \\\\ calculus")
title.scale(2)
title.to_edge(UP)
area_circle = Circle(
fill_color = BLUE,
fill_opacity = 0.5,
stroke_width = 0,
)
circum_circle = Circle(
color = YELLOW
)
deriv_eq = TexMobject("\\frac{d \\quad}{dR} = ")
int_eq = TexMobject("\\int_0^R \\quad = ")
target_height = deriv_eq[0].get_height()*2
area_circle.scale_to_fit_height(target_height)
circum_circle.scale_to_fit_height(target_height)
area_circle.next_to(deriv_eq[0], buff = SMALL_BUFF)
circum_circle.next_to(deriv_eq)
deriv_eq.add(area_circle.copy(), circum_circle.copy())
area_circle.next_to(int_eq)
circum_circle.next_to(int_eq[-1], LEFT)
int_eq.add(area_circle, circum_circle)
for mob in deriv_eq, int_eq:
mob.scale(1.5)
arrow = TexMobject("\\Leftrightarrow").scale(2)
arrow.shift(DOWN)
deriv_eq.next_to(arrow, LEFT)
int_eq.next_to(arrow, RIGHT)
self.add(title, arrow, deriv_eq, int_eq)
# dR = 0.25
# rings = VGroup(*[
# self.get_ring(rad, 0.9*dR)
# for rad in np.arange(0, self.radius, dR)
# ])
# for ring in rings:
# ring.add(ring.copy().rotate(np.pi))
# rings.gradient_highlight(BLUE, GREEN_E)
# rings.next_to(title, DOWN)
# self.add(title, rings)

View File

@ -45,6 +45,8 @@ class GraphScene(Scene):
x_axis.add_numbers(*self.x_labeled_nums) x_axis.add_numbers(*self.x_labeled_nums)
x_label = TexMobject(self.x_axis_label) x_label = TexMobject(self.x_axis_label)
x_label.next_to(x_axis, RIGHT+UP, buff = SMALL_BUFF) x_label.next_to(x_axis, RIGHT+UP, buff = SMALL_BUFF)
x_axis.add(x_label)
self.x_axis_label_mob = x_label
y_num_range = float(self.y_max - self.y_min) y_num_range = float(self.y_max - self.y_min)
y_axis = NumberLine( y_axis = NumberLine(
@ -63,6 +65,8 @@ class GraphScene(Scene):
y_axis.numbers.shift(self.y_axis_numbers_nudge) y_axis.numbers.shift(self.y_axis_numbers_nudge)
y_label = TexMobject(self.y_axis_label) y_label = TexMobject(self.y_axis_label)
y_label.next_to(y_axis.get_top(), RIGHT, buff = 2*MED_BUFF) y_label.next_to(y_axis.get_top(), RIGHT, buff = 2*MED_BUFF)
y_axis.add(y_label)
self.y_axis_label_mob = y_label
if animate: if animate:
self.play(Write(VGroup(x_axis, y_axis))) self.play(Write(VGroup(x_axis, y_axis)))