Merge pull request #230 from 3b1b/eop

Eop
This commit is contained in:
Grant Sanderson 2018-05-09 14:03:28 -07:00 committed by GitHub
commit 169f5db9bb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 616 additions and 370 deletions

View file

@ -47,18 +47,19 @@ class WriteOpeningWords(Scene):
class StartingCalc101(PiCreatureScene): class StartingCalc101(PiCreatureScene):
CONFIG = { CONFIG = {
# "default_pi_creature_kwargs": {
# "color": BLUE,
# "flip_at_start": False,
# },
} }
def construct(self): def construct(self):
randy = self.pi_creature randy = self.pi_creature
deriv_equation = TexMobject( deriv_string = "\\frac{df}{dx}(x) = \\lim(\\delta x \\to \\infty)" + \
"\\frac{df}{dx}(x) = \\lim(\\Delta x \\to \\infty)" + "{f(x + \\delta x) - f(x) \\over \\delta x}"
"{f(x + \\Delta x) - f(x) \\over \\Delta x}", equations = VGroup(
tex_to_color_map={"\\Delta x": BLUE} TexMobject(*break_up_string_by_terms(deriv_string, "\\delta x"))
) )
self.add(deriv_equation)
equations = VGroup(deriv_equation)
title = TextMobject("Calculus 101") title = TextMobject("Calculus 101")
title.to_edge(UP) title.to_edge(UP)
h_line = Line(LEFT, RIGHT) h_line = Line(LEFT, RIGHT)

View file

@ -0,0 +1,62 @@
from big_ol_pile_of_manim_imports import *
from active_projects.eop.reusable_imports import *
class ShuffleThroughAllSequences(Scene):
CONFIG = {
"nb_coins" : 14,
"run_time" : 5,
"fps" : int(1.0/PRODUCTION_QUALITY_FRAME_DURATION),
"coin_size" : 0.5,
"coin_spacing" : 0.65
}
def construct(self):
nb_frames = self.run_time * self.fps
nb_relevant_coins = int(np.log2(nb_frames)) + 1
print "relevant coins:", nb_relevant_coins
nb_idle_coins = self.nb_coins - nb_relevant_coins
idle_heads = CoinSequence(nb_idle_coins * ["H"],
radius = self.coin_size * 0.5,
spacing = self.coin_spacing)
idle_tails = CoinSequence(nb_idle_coins * ["T"],
radius = self.coin_size * 0.5,
spacing = self.coin_spacing)
idle_tails.fade(0.5)
idle_part = VGroup(idle_heads, idle_tails)
left_idle_part = CoinSequence(6 * ["H"],
radius = self.coin_size * 0.5,
spacing = self.coin_spacing)
self.add(idle_part, left_idle_part)
last_coin_seq = VGroup()
for i in range(2**nb_relevant_coins):
binary_seq = binary(i)
# pad to the left with 0s
nb_leading_zeroes = nb_relevant_coins - len(binary_seq)
for j in range(nb_leading_zeroes):
binary_seq.insert(0, 0)
seq2 = ["H" if x == 0 else "T" for x in binary_seq]
coin_seq = CoinSequence(seq2,
radius = self.coin_size * 0.5,
spacing = self.coin_spacing)
coin_seq.next_to(idle_part, LEFT, buff = self.coin_spacing - self.coin_size)
left_idle_part.next_to(coin_seq, LEFT, buff = self.coin_spacing - self.coin_size)
all_coins = VGroup(left_idle_part, coin_seq, idle_part)
all_coins.center()
self.remove(last_coin_seq)
self.add(coin_seq)
#self.wait(1.0/self.fps)
self.update_frame()
self.add_frames(self.get_frame())
last_coin_seq = coin_seq
print float(i)/2**nb_relevant_coins

View file

@ -84,7 +84,7 @@ class IllustrateAreaModelErf(GraphScene):
equals_sign = TexMobject("=").next_to(cdf_formula, buff = MED_LARGE_BUFF) equals_sign = TexMobject("=").next_to(cdf_formula, buff = MED_LARGE_BUFF)
cdf_value = DecimalNumber(0, color = graph.color, num_decimal_points = 3) cdf_value = DecimalNumber(0, color = graph.color, num_decimal_places = 3)
cdf_value.next_to(equals_sign) cdf_value.next_to(equals_sign)
self.play( self.play(
FadeIn(equals_sign), FadeIn(equals_sign),
@ -99,13 +99,13 @@ class IllustrateAreaModelErf(GraphScene):
self.add(ContinualChangingDecimal( self.add(ContinualChangingDecimal(
decimal_number_mobject = cdf_value, decimal_number_mobject = cdf_value,
number_update_func = integral_update_func, number_update_func = integral_update_func,
num_decimal_points = 3 num_decimal_places = 3
)) ))
self.add(ContinualChangingDecimal( self.add(ContinualChangingDecimal(
decimal_number_mobject = cdf_percentage, decimal_number_mobject = cdf_percentage,
number_update_func = integral_update_func_percent, number_update_func = integral_update_func_percent,
num_decimal_points = 1 num_decimal_places = 1
)) ))

View file

@ -5,7 +5,7 @@ from active_projects.eop.reusable_imports import *
class BrickRowScene(PiCreatureScene): class BrickRowScene(PiCreatureScene):
def split_tallies(self, direction = DOWN): def split_tallies(self, row, direction = DOWN):
# Split all tally symbols at once and move the copies # Split all tally symbols at once and move the copies
# either horizontally on top of the brick row # either horizontally on top of the brick row
# or diagonally into the bricks # or diagonally into the bricks
@ -15,12 +15,12 @@ class BrickRowScene(PiCreatureScene):
tally_targets_left = [ tally_targets_left = [
rect.get_center() + 0.25 * rect.get_width() * LEFT rect.get_center() + 0.25 * rect.get_width() * LEFT
for rect in self.row.rects for rect in row.rects
] ]
tally_targets_right = [ tally_targets_right = [
rect.get_center() + 0.25 * rect.get_width() * RIGHT rect.get_center() + 0.25 * rect.get_width() * RIGHT
for rect in self.row.rects for rect in row.rects
] ]
if np.all(direction == LEFT) or np.all(direction == RIGHT): if np.all(direction == LEFT) or np.all(direction == RIGHT):
@ -63,7 +63,7 @@ class BrickRowScene(PiCreatureScene):
def tally_split_animations(self, direction = DOWN): def tally_split_animations(self, row, direction = DOWN):
# Just creates the animations and returns them # Just creates the animations and returns them
# Execution can be timed afterwards # Execution can be timed afterwards
# Returns two lists: first all those going left, then those to the right # Returns two lists: first all those going left, then those to the right
@ -73,12 +73,12 @@ class BrickRowScene(PiCreatureScene):
tally_targets_left = [ tally_targets_left = [
rect.get_center() + 0.25 * rect.get_width() * LEFT rect.get_center() + 0.25 * rect.get_width() * LEFT
for rect in self.row.rects for rect in row.rects
] ]
tally_targets_right = [ tally_targets_right = [
rect.get_center() + 0.25 * rect.get_width() * RIGHT rect.get_center() + 0.25 * rect.get_width() * RIGHT
for rect in self.row.rects for rect in row.rects
] ]
if np.all(direction == LEFT) or np.all(direction == RIGHT): if np.all(direction == LEFT) or np.all(direction == RIGHT):
@ -122,13 +122,14 @@ class BrickRowScene(PiCreatureScene):
return anims1, anims2 return anims1, anims2
def split_tallies_at_once(self, direction = DOWN):
anims1, anims2 = self.tally_split_animations(direction = direction) def split_tallies_at_once(self, row, direction = DOWN):
anims1, anims2 = self.tally_split_animations(row, direction = direction)
self.play(*(anims1 + anims2)) self.play(*(anims1 + anims2))
def split_tallies_in_two_steps(self, direction = DOWN): def split_tallies_in_two_steps(self, row, direction = DOWN):
# First all those to the left, then those to the right # First all those to the left, then those to the right
anims1, anims2 = self.tally_split_animations(direction = direction) anims1, anims2 = self.tally_split_animations(row, direction = direction)
self.play(*anims1) self.play(*anims1)
self.wait(0.3) self.wait(0.3)
self.play(*anims2) self.play(*anims2)
@ -136,31 +137,31 @@ class BrickRowScene(PiCreatureScene):
def merge_rects_by_subdiv(self): def merge_rects_by_subdiv(self, row):
half_merged_row = self.row.copy() half_merged_row = row.copy()
half_merged_row.subdiv_level += 1 half_merged_row.subdiv_level += 1
half_merged_row.generate_points() half_merged_row.generate_points()
half_merged_row.move_to(self.row) half_merged_row.move_to(row)
self.play(FadeIn(half_merged_row)) self.play(FadeIn(half_merged_row))
self.remove(self.row) self.remove(row)
self.row = half_merged_row return half_merged_row
def merge_tallies(self, target_pos = UP): def merge_tallies(self, row, target_pos = UP):
r = self.row.subdiv_level r = row.subdiv_level
if np.all(target_pos == DOWN): if np.all(target_pos == DOWN):
tally_targets = [ tally_targets = [
rect.get_center() rect.get_center()
for rect in self.row.get_rects_for_level(r) for rect in row.get_rects_for_level(r)
] ]
elif np.all(target_pos == UP): elif np.all(target_pos == UP):
y_pos = self.row.get_center()[1] + 1.2 * 0.5 * self.row.get_height() y_pos = row.get_center()[1] + 1.2 * 0.5 * row.get_height()
for target in tally_targets: for target in tally_targets:
target[1] = y_pos target[1] = y_pos
else: else:
@ -186,25 +187,25 @@ class BrickRowScene(PiCreatureScene):
self.tallies.add(self.tallies_copy[-1]) self.tallies.add(self.tallies_copy[-1])
def merge_rects_by_coloring(self): def merge_rects_by_coloring(self, row):
merged_row = self.row.copy() merged_row = row.copy()
merged_row.coloring_level += 1 merged_row.coloring_level += 1
merged_row.generate_points() merged_row.generate_points()
merged_row.move_to(self.row) merged_row.move_to(row)
self.play(FadeIn(merged_row)) self.play(FadeIn(merged_row))
self.remove(self.row) self.remove(row)
self.row = merged_row return merged_row
def move_tallies_on_top(self): def move_tallies_on_top(self, row):
self.play( self.play(
self.tallies.shift, 1.2 * 0.5 * self.row.height * UP self.tallies.shift, 1.2 * 0.5 * row.height * UP
) )
for tally in self.tallies: for tally in self.tallies:
tally.anchor += 1.2 * 0.5 * self.row.height * UP tally.anchor += 1.2 * 0.5 * row.height * UP
def create_pi_creature(self): def create_pi_creature(self):
randy = CoinFlippingPiCreature(color = MAROON_E) randy = CoinFlippingPiCreature(color = MAROON_E)
@ -256,12 +257,11 @@ class BrickRowScene(PiCreatureScene):
# # # # # # # # # # # # # # # #
self.play(FlipCoin(randy)) self.play(FlipCoin(randy))
self.play(SplitRectsInBrickWall(self.row)) self.play(SplitRectsInBrickWall(self.row))
self.merge_rects_by_subdiv() self.row = self.merge_rects_by_subdiv(self.row)
self.merge_rects_by_coloring() self.row = self.merge_rects_by_coloring(self.row)
# #
# put tallies on top # put tallies on top
@ -312,7 +312,6 @@ class BrickRowScene(PiCreatureScene):
new_tails[i].shift(COIN_SEQUENCE_SPACING * DOWN) new_tails[i].shift(COIN_SEQUENCE_SPACING * DOWN)
self.play(FadeIn(new_tails)) self.play(FadeIn(new_tails))
decimal_tallies = VGroup() decimal_tallies = VGroup()
# introduce notion of tallies # introduce notion of tallies
for (i, rect) in enumerate(self.row.get_rects_for_level(2)): for (i, rect) in enumerate(self.row.get_rects_for_level(2)):
@ -347,6 +346,7 @@ class BrickRowScene(PiCreatureScene):
) )
self.wait() self.wait()
self.tallies = VGroup() self.tallies = VGroup()
for (i, rect) in enumerate(self.row.get_rects_for_level(2)): for (i, rect) in enumerate(self.row.get_rects_for_level(2)):
tally = TallyStack(2-i, i, show_decimals = False) tally = TallyStack(2-i, i, show_decimals = False)
@ -357,6 +357,7 @@ class BrickRowScene(PiCreatureScene):
self.play(FadeIn(self.tallies)) self.play(FadeIn(self.tallies))
self.wait() self.wait()
anims = [] anims = []
for (decimal_tally, tally_stack) in zip(decimal_tallies, self.tallies): for (decimal_tally, tally_stack) in zip(decimal_tallies, self.tallies):
anims.append(ApplyFunction( anims.append(ApplyFunction(
@ -366,6 +367,7 @@ class BrickRowScene(PiCreatureScene):
self.play(*anims) self.play(*anims)
self.wait() self.wait()
# replace the original decimal tallies with # replace the original decimal tallies with
# the ones that belong to the TallyStacks # the ones that belong to the TallyStacks
for (decimal_tally, tally_stack) in zip(decimal_tallies, self.tallies): for (decimal_tally, tally_stack) in zip(decimal_tallies, self.tallies):
@ -374,9 +376,9 @@ class BrickRowScene(PiCreatureScene):
tally_stack.add(tally_stack.decimal_tally) tally_stack.add(tally_stack.decimal_tally)
self.add_foreground_mobject(self.tallies) self.add_foreground_mobject(self.tallies)
self.merge_rects_by_subdiv() self.row = self.merge_rects_by_subdiv(self.row)
self.wait() self.wait()
self.merge_rects_by_coloring() self.row = self.merge_rects_by_coloring(self.row)
self.wait() self.wait()
@ -494,7 +496,7 @@ class BrickRowScene(PiCreatureScene):
) )
self.wait() self.wait()
self.split_tallies_in_two_steps() self.split_tallies_in_two_steps(self.row)
self.wait() self.wait()
self.add_foreground_mobject(self.tallies) self.add_foreground_mobject(self.tallies)
@ -554,7 +556,7 @@ class BrickRowScene(PiCreatureScene):
# self.wait() # self.wait()
# self.merge_rects_by_subdiv() # self.row = self.merge_rects_by_subdiv(self.row)
# self.wait() # self.wait()
# self.play( # self.play(
@ -575,9 +577,9 @@ class BrickRowScene(PiCreatureScene):
# self.wait() # self.wait()
# self.merge_tallies(target_pos = DOWN) # self.merge_tallies(self.row, target_pos = DOWN)
# self.add_foreground_mobject(self.tallies) # self.add_foreground_mobject(self.tallies)
# self.merge_rects_by_coloring() # self.row = self.merge_rects_by_coloring(self.row)
# self.wait() # self.wait()
@ -645,7 +647,7 @@ class BrickRowScene(PiCreatureScene):
self.wait() self.wait()
self.merge_rects_by_subdiv() self.row = self.merge_rects_by_subdiv(self.row)
self.wait() self.wait()
self.play( self.play(
@ -666,9 +668,9 @@ class BrickRowScene(PiCreatureScene):
self.wait() self.wait()
self.merge_tallies(target_pos = DOWN) self.merge_tallies(self.row, target_pos = DOWN)
self.add_foreground_mobject(self.tallies) self.add_foreground_mobject(self.tallies)
self.merge_rects_by_coloring() self.row = self.merge_rects_by_coloring(self.row)
self.wait() self.wait()
@ -677,11 +679,18 @@ class BrickRowScene(PiCreatureScene):
with_labels = True, with_labels = True,
inset = True) inset = True)
self.play(FadeOut(self.tallies)) self.play(FadeOut(self.tallies))
self.play(LaggedStart(
FadeIn, outcomes))
self.wait() self.wait()
self.play(LaggedStart( self.play(LaggedStart(
FadeOut, outcomes)) FadeIn, outcomes,
#rate_func = there_and_back_with_pause,
run_time = 5))
self.wait()
self.play(LaggedStart(
FadeOut, outcomes,
#rate_func = there_and_back_with_pause,
run_time = 5))
self.wait()
self.play(FadeIn(self.tallies)) self.play(FadeIn(self.tallies))
brace1 = Brace(self.row.rects[2], UP) brace1 = Brace(self.row.rects[2], UP)
@ -705,21 +714,37 @@ class BrickRowScene(PiCreatureScene):
) )
self.wait() self.wait()
# put visuals for other probability distribtuions here
# back to three coin flips, show all 8 outcomes
run_time = 5
self.play(
LaggedStart(FadeIn, outcomes,
#rate_func = there_and_back_with_pause,
run_time = run_time),
FadeOut(self.tallies,
run_time = run_time)
)
self.wait()
self.play(
LaggedStart(FadeOut, outcomes,
#rate_func = there_and_back_with_pause,
run_time = 5),
FadeIn(self.tallies,
run_time = run_time)
)
# # # # # # # # # # # # # # # #
# FOURTH FLIP # # FOURTH FLIP #
# # # # # # # # # # # # # # # #
# removing the tallies (boy are they sticky)
self.play(FadeOut(self.tallies))
self.remove(self.tallies, self.tallies_copy)
for tally in self.tallies:
self.remove_foreground_mobject(tally)
self.remove(tally)
for tally in self.tallies_copy:
self.remove_foreground_mobject(tally)
self.remove(tally)
previous_row = self.row.copy() previous_row = self.row.copy()
self.add(previous_row) self.add(previous_row)
@ -727,26 +752,16 @@ class BrickRowScene(PiCreatureScene):
v = 1.25 * self.row.height * UP v = 1.25 * self.row.height * UP
self.play( self.play(
previous_row.shift, v, previous_row.shift, v,
#self.decimals.shift, v, self.tallies.shift, v,
#self.decimal_copies.shift, v
)
self.add(self.row)
self.bring_to_back(self.row)
self.row.shift(v)
w = 1.5 * self.row.height * DOWN
self.play(
self.row.shift, w,
Animation(previous_row)
) )
self.add_foreground_mobject(self.tallies)
self.play( self.play(
SplitRectsInBrickWall(self.row) SplitRectsInBrickWall(self.row)
) )
self.wait() self.wait()
self.merge_rects_by_subdiv() self.row = self.merge_rects_by_subdiv(self.row)
self.wait() self.wait()
@ -754,7 +769,10 @@ class BrickRowScene(PiCreatureScene):
k = 1 # tally to split k = 1 # tally to split
# show individual outcomes # show individual outcomes
outcomes = previous_row.get_outcome_rects_for_level(n, with_labels = False) outcomes = previous_row.get_outcome_rects_for_level(n,
with_labels = False,
inset = True
)
grouped_outcomes = VGroup() grouped_outcomes = VGroup()
index = 0 index = 0
for i in range(n + 1): for i in range(n + 1):
@ -779,7 +797,10 @@ class BrickRowScene(PiCreatureScene):
#self.revert_to_original_skipping_status() #self.revert_to_original_skipping_status()
target_outcomes = self.row.get_outcome_rects_for_level(n + 1, with_labels = False) target_outcomes = self.row.get_outcome_rects_for_level(n + 1,
with_labels = False,
inset = True
)
grouped_target_outcomes = VGroup() grouped_target_outcomes = VGroup()
index = 0 index = 0
old_tally_sizes = [choose(n,i) for i in range(n + 1)] old_tally_sizes = [choose(n,i) for i in range(n + 1)]
@ -813,6 +834,13 @@ class BrickRowScene(PiCreatureScene):
self.wait() self.wait()
# fade in new tallies
new_rects = self.row.get_rects_for_level(4)
new_tallies = VGroup(*[
TallyStack(n + 1 - i, i).move_to(rect) for (i, rect) in enumerate(new_rects)
])
self.play(FadeIn(new_tallies))
self.add_foreground_mobject(new_tallies[1])
# remove outcomes and sizes except for one tally # remove outcomes and sizes except for one tally
anims = [] anims = []
for i in range(n + 1): for i in range(n + 1):
@ -820,6 +848,11 @@ class BrickRowScene(PiCreatureScene):
anims.append(FadeOut(grouped_outcomes_copy[i])) anims.append(FadeOut(grouped_outcomes_copy[i]))
if i != k: if i != k:
anims.append(FadeOut(grouped_outcomes[i])) anims.append(FadeOut(grouped_outcomes[i]))
anims.append(FadeOut(new_tallies[i]))
#anims.append(FadeOut(self.tallies[0]))
#anims.append(FadeOut(self.tallies[2:]))
anims.append(FadeOut(new_tallies[-1]))
self.play(*anims) self.play(*anims)
@ -828,64 +861,69 @@ class BrickRowScene(PiCreatureScene):
self.play( self.play(
Transform(grouped_outcomes_copy[k - 1], original_grouped_outcomes[k - 1]) Transform(grouped_outcomes_copy[k - 1], original_grouped_outcomes[k - 1])
) )
self.play( self.play(
Transform(grouped_outcomes[k], original_grouped_outcomes[k]) Transform(grouped_outcomes[k], original_grouped_outcomes[k])
) )
new_rects = self.row.get_rects_for_level(n + 1) new_rects = self.row.get_rects_for_level(n + 1)
#decimals_copy = self.decimals.copy()
#decimals_copy2 = self.decimals.copy()
self.play( self.play(
Transform(grouped_outcomes[k][0],grouped_target_outcomes[k][0][old_tally_sizes[k - 1]:]), Transform(grouped_outcomes[k][0],grouped_target_outcomes[k][0][old_tally_sizes[k - 1]:]),
Transform(grouped_outcomes_copy[k - 1][0],grouped_target_outcomes[k][0][:old_tally_sizes[k]]), Transform(grouped_outcomes_copy[k - 1][0],grouped_target_outcomes[k][0][:old_tally_sizes[k - 1]]),
#decimals_copy[k - 1].move_to, new_rects[k], )
#decimals_copy2[k].move_to, new_rects[k],
self.play(
FadeOut(previous_row),
FadeOut(self.tallies),
)
self.row = self.merge_rects_by_coloring(self.row)
self.play(
FadeIn(new_tallies[0]),
FadeIn(new_tallies[2:]),
) )
# # # # # # # #
# FIFTH FLIP #
# # # # # # # #
# self.remove(
# grouped_outcomes, # # # # # # # # # #
# grouped_outcomes_copy, # EVEN MORE FLIPS #
# grouped_target_outcomes, # # # # # # # # # #
# target_outcomes,
# outcomes, self.play(FadeOut(new_tallies))
# previous_row,
# original_grouped_outcomes)
self.clear() self.clear()
self.add(randy, self.row) self.add(randy, self.row)
#self.row.shift(0.5 * UP)
#return
self.merge_rects_by_coloring() for i in range(3):
self.revert_to_original_skipping_status()
for i in range(1):
self.play(FlipCoin(randy)) self.play(FlipCoin(randy))
self.wait() self.wait()
previous_row = self.row.copy()
self.play(previous_row.shift, 1.25 * self.row.height * UP)
self.play( self.play(
SplitRectsInBrickWall(self.row) SplitRectsInBrickWall(self.row)
) )
self.wait() self.wait()
self.row = self.merge_rects_by_subdiv(self.row)
#self.split_tallies_at_once(direction = LEFT)
self.wait() self.wait()
self.merge_rects_by_subdiv() self.row = self.merge_rects_by_coloring(self.row)
self.wait()
#self.merge_tallies(direction = LEFT)
self.merge_rects_by_coloring()
#self.merge_decimals()
self.wait() self.wait()
self.play(FadeOut(previous_row))

View file

@ -1,29 +1,31 @@
from big_ol_pile_of_manim_imports import * from big_ol_pile_of_manim_imports import *
from active_projects.eop.reusable_imports import * from active_projects.eop.reusable_imports import *
from active_projects.eop.chapter1.brick_row_scene import BrickRowScene
class EntireBrickWall(BrickRowScene):
class EntireBrickWall(Scene):
def construct(self): def construct(self):
self.remove(self.get_primary_pi_creature())
row_height = 0.3 row_height = 0.3
nb_rows = 20 nb_rows = 20
start_point = 3 * UP + 1 * LEFT start_point = 3 * UP + 1 * LEFT
rows = VMobject() rows = VMobject()
rows.add(BrickRow(0, height = row_height)) rows.add(BrickRow(0, height = row_height))
rows[0].move_to(start_point) rows.move_to(start_point)
self.add(rows) self.add(rows)
zero_counter = Integer(0).next_to(start_point + 0.5 * rows[0].width * RIGHT) zero_counter = Integer(0).next_to(start_point + 0.5 * rows[0].width * RIGHT)
nb_flips_text = TextMobject("\# of flips") nb_flips_text = TextMobject("\# of flips")
nb_flips_text.next_to(zero_counter, RIGHT, buff = LARGE_BUFF) nb_flips_text.next_to(zero_counter, RIGHT, buff = LARGE_BUFF)
self.add(zero_counter, nb_flips_text) self.add(zero_counter, nb_flips_text)
flip_counters = VGroup(zero_counter)
for i in range(1,nb_rows + 1): for i in range(1, nb_rows + 1):
rows.add(BrickRow(i, height = row_height)) rows.add(rows[-1].copy())
rows[-1].move_to(start_point + (i - 1) * row_height * DOWN)
self.bring_to_back(rows[-1]) self.bring_to_back(rows[-1])
anims = [ anims = [
rows[-1].shift, row_height * DOWN, rows[-1].shift, row_height * DOWN,
@ -33,10 +35,17 @@ class EntireBrickWall(Scene):
if i % 5 == 0: if i % 5 == 0:
counter = Integer(i) counter = Integer(i)
counter.next_to(rows[-1].get_right() + row_height * DOWN, RIGHT) counter.next_to(rows[-1].get_right() + row_height * DOWN, RIGHT)
flip_counters.add(counter)
anims.append(FadeIn(counter)) anims.append(FadeIn(counter))
self.play(*anims) self.play(*anims)
self.play(SplitRectsInBrickWall(rows[-1]))
rows.submobjects[-1] = self.merge_rects_by_subdiv(rows[-1])
rows.submobjects[-1] = self.merge_rects_by_coloring(rows[-1])
# draw indices under the last row for the number of tails # draw indices under the last row for the number of tails
tails_counters = VGroup() tails_counters = VGroup()
for (i, rect) in enumerate(rows[-1].rects): for (i, rect) in enumerate(rows[-1].rects):
@ -62,10 +71,73 @@ class EntireBrickWall(Scene):
FadeIn(nb_tails_text) FadeIn(nb_tails_text)
) )
special_brick_copy = rows[-1].rects[13].copy() # remove any hidden brick rows
self.clear()
self.add(nb_flips_text)
mobs_to_shift = VGroup(
rows, flip_counters, tails_counters, nb_tails_text,
)
self.play(mobs_to_shift.shift, 3 * UP)
last_row_rect = SurroundingRectangle(rows[-1], buff = 0)
last_row_rect.set_stroke(color = YELLOW, width = 6)
self.play( self.play(
rows.fade, 0.9, rows.fade, 0.9,
FadeIn(special_brick_copy) ShowCreation(last_row_rect)
)
def highlighted_brick(row = 20, nb_tails = 10):
brick_copy = rows[row].rects[nb_tails].copy()
brick_copy.set_fill(color = YELLOW, opacity = 0.8)
prob_percentage = float(choose(row, nb_tails)) / 2**row * 100
brick_label = DecimalNumber(prob_percentage,
unit = "\%", num_decimal_places = 1, color = BLACK)
brick_label.move_to(brick_copy)
brick_label.scale_to_fit_height(0.8 * brick_copy.get_height())
return VGroup(brick_copy, brick_label)
highlighted_bricks = [
highlighted_brick(row = 20, nb_tails = i)
for i in range(20)
]
self.play(
FadeIn(highlighted_bricks[10])
)
self.play(
FadeOut(highlighted_bricks[10]),
FadeIn(highlighted_bricks[9]),
FadeIn(highlighted_bricks[11]),
)
self.play(
FadeOut(highlighted_bricks[9]),
FadeOut(highlighted_bricks[11]),
FadeIn(highlighted_bricks[8]),
FadeIn(highlighted_bricks[12]),
) )

View file

@ -9,6 +9,7 @@ class GenericMorphBrickRowIntoHistogram(Scene):
"bar_width" : 2.0, "bar_width" : 2.0,
"bar_anchor_height" : -3.0, "bar_anchor_height" : -3.0,
"show_tallies" : False, "show_tallies" : False,
"show_nb_flips" : True
} }
def construct(self): def construct(self):
@ -25,13 +26,23 @@ class GenericMorphBrickRowIntoHistogram(Scene):
for (i,brick) in enumerate(self.row.rects): for (i,brick) in enumerate(self.row.rects):
tally = TallyStack(self.level - i, i) tally = TallyStack(self.level - i, i)
tally.next_to(brick, UP) tally.move_to(brick)
self.add(tally) self.add(tally)
tallies.add(tally) tallies.add(tally)
brick.set_stroke(width = 3) brick.set_stroke(width = 3)
if self.show_nb_flips:
nb_flips_text = TextMobject("\# of flips: " + str(self.level))
nb_flips_text.to_corner(UR)
self.add(nb_flips_text)
self.remove(self.row.subdivs, self.row.border) self.remove(self.row.subdivs, self.row.border)
for rect in self.row.rects:
rect.set_stroke(color = WHITE, width = 3)
self.play(self.row.rects.space_out_submobjects, {"factor" : 1.3})
anims = [] anims = []
for brick in self.row.rects: for brick in self.row.rects:
anims.append(brick.rotate) anims.append(brick.rotate)
@ -50,11 +61,10 @@ class GenericMorphBrickRowIntoHistogram(Scene):
self.play(*anims) self.play(*anims)
self.bars.create_outline() self.bars.create_outline()
anims = [
anims = [] ApplyMethod(rect.set_stroke, {"width" : 0})
for bar in self.bars.submobjects: for rect in self.bars
anims.append(bar.set_stroke) ]
anims.append({"width" : 0})
anims.append(FadeIn(self.bars.outline)) anims.append(FadeIn(self.bars.outline))
self.play(*anims) self.play(*anims)
@ -67,7 +77,8 @@ class MorphBrickRowIntoHistogram3(GenericMorphBrickRowIntoHistogram):
"prob_denominator" : 8, "prob_denominator" : 8,
"bar_width" : 2.0, "bar_width" : 2.0,
"bar_anchor_height" : -3.0, "bar_anchor_height" : -3.0,
"show_tallies" : True "show_tallies" : True,
"show_nb_flips" : False
} }
def construct(self): def construct(self):
@ -90,55 +101,71 @@ class MorphBrickRowIntoHistogram3(GenericMorphBrickRowIntoHistogram):
nb_tails_label = TextMobject("\# of tails") nb_tails_label = TextMobject("\# of tails")
nb_tails_label.next_to(x_labels[-1], RIGHT, MED_LARGE_BUFF) nb_tails_label.next_to(x_labels[-1], RIGHT, MED_LARGE_BUFF)
# draw y-guides
y_guides = VMobject()
for i in range(0,self.prob_denominator + 1):
y_guide = Line(5 * LEFT, 5 * RIGHT, stroke_color = GRAY)
y_guide.move_to(self.bar_anchor_height * UP + i * float(self.row.width) / self.prob_denominator * UP)
y_guide_label = TexMobject("{" + str(i) + "\over " + str(self.prob_denominator) + "}", color = GRAY)
y_guide_label.scale(0.7)
y_guide_label.next_to(y_guide, LEFT)
if i != 0:
y_guide.add(y_guide_label)
y_guides.add(y_guide)
self.play(
FadeIn(y_guides),
Animation(self.bars.outline),
Animation(self.bars)
)
self.play( self.play(
FadeIn(x_axis), FadeIn(x_axis),
FadeIn(x_labels), FadeIn(x_labels),
FadeIn(nb_tails_label) FadeIn(nb_tails_label)
) )
self.add_foreground_mobject(nb_tails_label)
area_color = YELLOW
total_area_text = TextMobject("total area =", color = area_color)
area_decimal = DecimalNumber(0, color = area_color, num_decimal_places = 3)
area_decimal.next_to(total_area_text, RIGHT)
# draw y-guides total_area_group = VGroup(total_area_text, area_decimal)
total_area_group.move_to(2.7 * UP)
y_guides = VMobject() self.play(
for i in range(1,self.prob_denominator + 1): FadeIn(total_area_text),
y_guide = Line(5 * LEFT, 5 * RIGHT, stroke_color = GRAY) )
y_guide.move_to(self.bar_anchor_height * UP + i * float(self.row.width) / self.prob_denominator * UP)
y_guide_label = TexMobject("{" + str(i) + "\over " + str(self.prob_denominator) + "}", color = GRAY)
y_guide_label.scale(0.7)
y_guide_label.next_to(y_guide, LEFT)
y_guide.add(y_guide_label)
y_guides.add(y_guide)
self.bring_to_back(y_guides) cumulative_areas = [0.125, 0.5, 0.875, 1]
self.play(FadeIn(y_guides), Animation(self.bars)) covering_rects = self.bars.copy()
for (i,rect) in enumerate(covering_rects):
rect.set_fill(color = area_color, opacity = 0.5)
self.play(
FadeIn(rect, rate_func = linear),
ChangeDecimalToValue(area_decimal, cumulative_areas[i],
rate_func = linear)
)
self.wait(0.2)
self.wait()
total_area_text = TextMobject("total area = 1", color = YELLOW) total_area_rect = SurroundingRectangle(
total_area_rect = SurroundingRectangle(total_area_text, total_area_group,
buff = MED_SMALL_BUFF, buff = MED_SMALL_BUFF,
fill_opacity = 0.5, stroke_color = area_color
fill_color = BLACK,
stroke_color = YELLOW
) )
self.play( self.play(
Write(total_area_text), FadeOut(covering_rects),
ShowCreation(total_area_rect) ShowCreation(total_area_rect)
) )
prob_dist_text = TextMobject("probability distribution", color = YELLOW)
prob_dist_text.to_corner(UP, buff = LARGE_BUFF)
prob_dist_rect = SurroundingRectangle(prob_dist_text,
buff = MED_SMALL_BUFF,
stroke_color = YELLOW
)
self.play(
Write(prob_dist_text),
ShowCreation(prob_dist_rect)
)
class MorphBrickRowIntoHistogram20(GenericMorphBrickRowIntoHistogram): class MorphBrickRowIntoHistogram20(GenericMorphBrickRowIntoHistogram):
@ -165,8 +192,8 @@ class MorphBrickRowIntoHistogram20(GenericMorphBrickRowIntoHistogram):
label.next_to(self.bar_anchors[i], DOWN) label.next_to(self.bar_anchors[i], DOWN)
x_labels.add(label) x_labels.add(label)
nb_tails_label = TextMobject("\# of heads") nb_tails_label = TextMobject("\# of tails")
nb_tails_label.next_to(x_labels[-1], RIGHT, MED_LARGE_BUFF) nb_tails_label.move_to(5 * RIGHT + 2.5 * DOWN)
self.play( self.play(
FadeIn(x_axis), FadeIn(x_axis),
@ -186,7 +213,7 @@ class MorphBrickRowIntoHistogram20(GenericMorphBrickRowIntoHistogram):
y_guide_height = self.bar_anchor_height + i * float(self.row.width) y_guide_height = self.bar_anchor_height + i * float(self.row.width)
y_guide_heights.append(y_guide_height) y_guide_heights.append(y_guide_height)
y_guide.move_to(y_guide_height * UP) y_guide.move_to(y_guide_height * UP)
y_guide_label = DecimalNumber(i, num_decimal_points = 2, color = GRAY) y_guide_label = DecimalNumber(i, num_decimal_places = 2, color = GRAY)
y_guide_label.scale(0.7) y_guide_label.scale(0.7)
y_guide_label.next_to(y_guide, LEFT) y_guide_label.next_to(y_guide, LEFT)
y_guide.add(y_guide_label) y_guide.add(y_guide_label)
@ -199,7 +226,7 @@ class MorphBrickRowIntoHistogram20(GenericMorphBrickRowIntoHistogram):
histogram_height = self.bars.get_height() histogram_height = self.bars.get_height()
# scale to fit screen # scale to fit screen
self.scale_x = 10.0/(len(self.bars) * self.bar_width) self.scale_x = 10.0/((len(self.bars) - 1) * self.bar_width)
self.scale_y = 6.0/histogram_height self.scale_y = 6.0/histogram_height

View file

@ -14,15 +14,25 @@ class ProbabilityDistributions(PiCreatureScene):
def construct(self): def construct(self):
lag_ratio = 0.2 lag_ratio = 0.2
run_time = 5 run_time = 3
text = TextMobject("Probability distributions", color = YELLOW)
text.to_edge(UP)
text_rect = SurroundingRectangle(text, buff = MED_SMALL_BUFF)
self.play(
FadeIn(text),
ShowCreation(text_rect)
)
# WEATHER FORECAST # WEATHER FORECAST
unit_rect = Rectangle( unit_rect = Rectangle(
height = 4, width = 4 height = 3, width = 3
) ).shift(DOWN)
p_rain = 0.23 p_rain = 0.23
p_sun = 1 - p_rain p_sun = 1 - p_rain
@ -38,7 +48,7 @@ class ProbabilityDistributions(PiCreatureScene):
sun_rect.set_fill(color = YELLOW, opacity = opacity) sun_rect.set_fill(color = YELLOW, opacity = opacity)
sun_rect.set_stroke(width = 0) sun_rect.set_stroke(width = 0)
self.add(unit_rect, rain_rect, sun_rect) self.play(FadeIn(VGroup(unit_rect, rain_rect, sun_rect)))
rain = SVGMobject(file_name = "rain").scale(0.35) rain = SVGMobject(file_name = "rain").scale(0.35)
sun = SVGMobject(file_name = "sun").scale(0.35) sun = SVGMobject(file_name = "sun").scale(0.35)
@ -189,7 +199,8 @@ class ProbabilityDistributions(PiCreatureScene):
coin_flip_rect.add(braces, labels) coin_flip_rect.add(braces, labels)
coin_flip_rect.target = coin_flip_rect.copy().scale(0.6) coin_flip_rect.target = coin_flip_rect.copy().scale(0.6)
coin_flip_rect.target.to_corner(UR, buff = LARGE_BUFF) coin_flip_rect.target.to_corner(UR, buff = MED_LARGE_BUFF)
coin_flip_rect.target.shift(DOWN)
self.play( self.play(
MoveToTarget(coin_flip_rect) MoveToTarget(coin_flip_rect)
@ -255,25 +266,3 @@ class ProbabilityDistributions(PiCreatureScene):
rate_func=there_and_back_with_pause, rate_func=there_and_back_with_pause,
run_time=run_time run_time=run_time
) )

View file

@ -1,12 +1,14 @@
from big_ol_pile_of_manim_imports import * from big_ol_pile_of_manim_imports import *
from active_projects.eop.reusable_imports import * from active_projects.eop.reusable_imports import *
from active_projects.eop.independence import * from active_projects.eop.independence import *
from for_3b1b_videos.pi_class import PiCreatureClass
class QuizResult(Scene): class QuizResult(PiCreatureScene):
CONFIG = {
"pi_creatures_start_on_screen" : False,
"random_seed" : 6
}
def construct(self): def construct(self):
@ -23,14 +25,15 @@ class QuizResult(Scene):
return quiz return quiz
highlight_color = YELLOW highlight_color = WHITE
nb_students_x = 5 nb_students_x = 5
nb_students_y = 3 nb_students_y = 3
spacing_students_x = 2.0 spacing_students_x = 2.0
spacing_students_y = 2.2 spacing_students_y = 2.2
all_students = VGroup() all_students = PiCreatureClass(
width = nb_students_x, height = nb_students_y)# VGroup()
student_points = [] student_points = []
grades = [] grades = []
grades_count = [] grades_count = []
@ -39,9 +42,10 @@ class QuizResult(Scene):
for j in range(nb_students_y): for j in range(nb_students_y):
x = i * spacing_students_x x = i * spacing_students_x
y = j * spacing_students_y y = j * spacing_students_y
pi = PiCreature().scale(0.3) #pi = PiCreature().scale(0.3)
pi.move_to([x,y,0]) #pi.move_to([x,y,0])
all_students.add(pi) #all_students.add(pi)
all_students[i*nb_students_y + j].move_to([x,y,0])
q1 = np.random.choice([True, False]) q1 = np.random.choice([True, False])
q2 = np.random.choice([True, False]) q2 = np.random.choice([True, False])
q3 = np.random.choice([True, False]) q3 = np.random.choice([True, False])
@ -55,7 +59,8 @@ class QuizResult(Scene):
all_students.move_to(ORIGIN) all_students.move_to(ORIGIN)
self.add(all_students) self.pi_creatures = all_students
self.play(FadeIn(all_students))
all_quizzes = VGroup() all_quizzes = VGroup()
@ -133,17 +138,20 @@ class QuizResult(Scene):
) )
grade_hist.move_to(all_students) grade_hist.move_to(all_students)
self.play(FadeIn(grade_hist)) self.play(
FadeIn(grade_hist),
FadeOut(all_students)
)
nb_students_label = TextMobject("\# of students", color = highlight_color) nb_students_label = TextMobject("\# of students", color = highlight_color)
nb_students_label.move_to(3 * LEFT + 2 * UP) nb_students_label.move_to(5 * LEFT + 2 * UP)
arrows = VGroup(*[ arrows = VGroup(*[
Arrow(nb_students_label, grade_hist.bars[i].get_center(), Arrow(nb_students_label.get_right(), grade_hist.bars[i].get_center(),
color = highlight_color) color = highlight_color)
for i in range(4) for i in range(4)
]) ])
self.play(Write(nb_students_label), LaggedStart(ShowCreation,arrows)) self.play(Write(nb_students_label), LaggedStart(GrowArrow,arrows))
percentage_label = TextMobject("\% of students", color = highlight_color) percentage_label = TextMobject("\% of students", color = highlight_color)
percentage_label.move_to(nb_students_label) percentage_label.move_to(nb_students_label)
@ -151,10 +159,11 @@ class QuizResult(Scene):
anims = [] anims = []
for (label, percentage) in zip(grade_hist.y_labels_group, percentages): for (label, percentage) in zip(grade_hist.y_labels_group, percentages):
new_label = DecimalNumber(percentage, new_label = DecimalNumber(percentage,
num_decimal_points = 1, num_decimal_places = 1,
unit = "\%", unit = "\%",
color = highlight_color color = highlight_color
) )
new_label.scale(0.7)
new_label.move_to(label) new_label.move_to(label)
anims.append(Transform(label, new_label)) anims.append(Transform(label, new_label))
anims.append(ReplacementTransform(nb_students_label, percentage_label)) anims.append(ReplacementTransform(nb_students_label, percentage_label))
@ -174,8 +183,8 @@ class QuizResult(Scene):
prob_label.move_to(percentage_label) prob_label.move_to(percentage_label)
self.play( self.play(
all_students[8].set_color, MAROON_E, all_students[8].set_color, MAROON_E,
all_students[:8].fade, 0.6, #all_students[:8].fade, 0.6,
all_students[9:].fade, 0.6, #all_students[9:].fade, 0.6,
ReplacementTransform(percentage_label, prob_label) ReplacementTransform(percentage_label, prob_label)
) )
@ -184,12 +193,32 @@ class QuizResult(Scene):
FadeOut(arrows) FadeOut(arrows)
) )
for i in range(1): flash_hist = FlashThroughHistogram(
self.play(
FlashThroughHistogram(
grade_hist, grade_hist,
direction = "vertical", direction = "vertical",
mode = "random", mode = "random",
run_time = 5 cell_opacity = 0.5,
run_time = 5,
rate_func = linear
) )
flash_class = FlashThroughClass(
all_students,
mode = "random",
highlight_color = MAROON_E,
run_time = 5,
rate_func = linear
) )
for i in range(3):
self.play(flash_hist, flash_class)
self.remove(flash_hist.prototype_cell)

View file

@ -11,7 +11,7 @@ class BrickRow(VMobject):
"height" : 1.0, "height" : 1.0,
"width" : 8.0, "width" : 8.0,
"outcome_shrinkage_factor_x" : 0.95, "outcome_shrinkage_factor_x" : 0.95,
"outcome_shrinkage_factor_y" : 0.95 "outcome_shrinkage_factor_y" : 0.94
} }
def __init__(self, n, **kwargs): def __init__(self, n, **kwargs):
@ -104,12 +104,12 @@ class BrickRow(VMobject):
outcome_width = float(self.width) / (2 ** r) outcome_width = float(self.width) / (2 ** r)
outcome_height = self.height outcome_height = self.height
corner_radius = 0 # min(0.1, 0.3 * min(outcome_width, outcome_height)) corner_radius = min(0.1, 0.3 * min(outcome_width, outcome_height))
# this scales down the corner radius for very narrow rects # this scales down the corner radius for very narrow rects
rect = Rectangle( # RoundedRectangle( rect = RoundedRectangle(
width = outcome_width, width = outcome_width,
height = outcome_height, height = outcome_height,
#corner_radius = corner_radius, corner_radius = corner_radius,
fill_color = WHITE, fill_color = WHITE,
fill_opacity = 0.2, fill_opacity = 0.2,
stroke_width = 0 stroke_width = 0
@ -205,13 +205,3 @@ class SplitRectsInBrickWall(AnimationGroup):
# def update_mobject(self, alpha):
# for subdiv in self.subdivs:
# x = subdiv.get_start()[0]
# start = self.mobject.get_center()
# start += x * RIGHT + 0.5 * self.mobject.get_height() * UP
# end = start + alpha * self.mobject.get_height() * DOWN
# subdiv.put_start_and_end_on(start,end)

View file

@ -201,7 +201,10 @@ class FlashThroughHistogram(Animation):
"hist_opacity" : 0.2 "hist_opacity" : 0.2
} }
def __init__(self, mobject, direction = "horizontal", mode = "random", **kwargs): def __init__(self, mobject,
direction = "horizontal",
mode = "random",
**kwargs):
digest_config(self, kwargs) digest_config(self, kwargs)
@ -277,6 +280,15 @@ class FlashThroughHistogram(Animation):
self.mobject.remove(self.prototype_cell) self.mobject.remove(self.prototype_cell)
def clean_up(self, surrounding_scene = None):
Animation.clean_up(self, surrounding_scene)
self.update(1)
if surrounding_scene is not None:
if self.is_remover():
surrounding_scene.remove(self.prototype_cell)
else:
surrounding_scene.add(self.prototype_cell)
return self
@ -290,7 +302,7 @@ class OutlineableBars(VGroup):
# We use this to morph a row of bricks into a histogram. # We use this to morph a row of bricks into a histogram.
CONFIG = { CONFIG = {
"outline_stroke_width" : 5, "outline_stroke_width" : 3,
"stroke_color" : WHITE "stroke_color" : WHITE
} }
def create_outline(self, animated = False, **kwargs): def create_outline(self, animated = False, **kwargs):

View file

@ -37,6 +37,7 @@ class UprightTails(UprightCoin):
class CoinSequence(VGroup): class CoinSequence(VGroup):
CONFIG = { CONFIG = {
"sequence": [], "sequence": [],
"radius" : COIN_RADIUS,
"spacing": COIN_SEQUENCE_SPACING, "spacing": COIN_SEQUENCE_SPACING,
"direction": RIGHT "direction": RIGHT
} }
@ -47,11 +48,11 @@ class CoinSequence(VGroup):
offset = 0 offset = 0
for symbol in self.sequence: for symbol in self.sequence:
if symbol == "H": if symbol == "H":
new_coin = UprightHeads() new_coin = UprightHeads(radius = self.radius)
elif symbol == "T": elif symbol == "T":
new_coin = UprightTails() new_coin = UprightTails(radius = self.radius)
else: else:
new_coin = UprightCoin(symbol = symbol) new_coin = UprightCoin(symbol = symbol, radius = self.radius)
new_coin.shift(offset * self.direction) new_coin.shift(offset * self.direction)
self.add(new_coin) self.add(new_coin)
offset += self.spacing offset += self.spacing

View file

@ -10,7 +10,7 @@ from utils.config_ops import digest_config
class ChangingDecimal(Animation): class ChangingDecimal(Animation):
CONFIG = { CONFIG = {
"num_decimal_points": None, "num_decimal_places": None,
"show_ellipsis": None, "show_ellipsis": None,
"position_update_func": None, "position_update_func": None,
"tracked_mobject": None, "tracked_mobject": None,
@ -21,7 +21,7 @@ class ChangingDecimal(Animation):
self.decimal_number_config = dict( self.decimal_number_config = dict(
decimal_number_mobject.initial_config decimal_number_mobject.initial_config
) )
for attr in "num_decimal_points", "show_ellipsis": for attr in "num_decimal_places", "show_ellipsis":
value = getattr(self, attr) value = getattr(self, attr)
if value is not None: if value is not None:
self.decimal_number_config[attr] = value self.decimal_number_config[attr] = value

View file

@ -151,11 +151,12 @@ def handle_scene(scene, **config):
if config["show_file_in_finder"]: if config["show_file_in_finder"]:
commands.append("-R") commands.append("-R")
#
if config["show_last_frame"]: if config["show_last_frame"]:
commands.append(scene.get_image_file_path()) commands.append(scene.get_image_file_path())
else: else:
commands.append(scene.get_movie_file_path()) commands.append(scene.get_movie_file_path())
#commands.append("-g")
FNULL = open(os.devnull, 'w') FNULL = open(os.devnull, 'w')
sp.call(commands, stdout=FNULL, stderr=sp.STDOUT) sp.call(commands, stdout=FNULL, stderr=sp.STDOUT)
FNULL.close() FNULL.close()
@ -223,8 +224,11 @@ def get_module_posix(file_name):
module_name = file_name.replace(".py", "") module_name = file_name.replace(".py", "")
last_module = imp.load_module(".", *imp.find_module(".")) last_module = imp.load_module(".", *imp.find_module("."))
for part in module_name.split(os.sep): for part in module_name.split(os.sep):
try:
load_args = imp.find_module(part, last_module.__path__) load_args = imp.find_module(part, last_module.__path__)
last_module = imp.load_module(part, *load_args) last_module = imp.load_module(part, *load_args)
except ImportError:
continue
return last_module return last_module

View file

@ -0,0 +1,23 @@
import numpy as np
import warnings
from constants import *
from mobject.types.vectorized_mobject import VGroup
from for_3b1b_videos.pi_creature import PiCreature
class PiCreatureClass(VGroup):
CONFIG = {
"width" : 3,
"height" : 2
}
def __init__(self, **kwargs):
VGroup.__init__(self, **kwargs)
for i in range(self.width):
for j in range(self.height):
pi = PiCreature().scale(0.3)
pi.move_to(i*DOWN + j* RIGHT)
self.add(pi)

View file

@ -6,6 +6,7 @@ from mobject.mobject import Group
from mobject.svg.drawings import SpeechBubble from mobject.svg.drawings import SpeechBubble
from animation.animation import Animation
from animation.creation import ShowCreation from animation.creation import ShowCreation
from animation.creation import Write from animation.creation import Write
from animation.composition import AnimationGroup from animation.composition import AnimationGroup
@ -16,6 +17,8 @@ from utils.config_ops import digest_config
from utils.rate_functions import squish_rate_func from utils.rate_functions import squish_rate_func
from utils.rate_functions import there_and_back from utils.rate_functions import there_and_back
from for_3b1b_videos.pi_class import PiCreatureClass
class Blink(ApplyMethod): class Blink(ApplyMethod):
CONFIG = { CONFIG = {
@ -101,3 +104,46 @@ class RemovePiCreatureBubble(AnimationGroup):
self.pi_creature.bubble = None self.pi_creature.bubble = None
if surrounding_scene is not None: if surrounding_scene is not None:
surrounding_scene.add(self.pi_creature) surrounding_scene.add(self.pi_creature)
class FlashThroughClass(Animation):
CONFIG = {
"highlight_color" : GREEN,
}
def __init__(self, mobject, mode = "linear", **kwargs):
if not isinstance(mobject, PiCreatureClass):
raise Exception("FlashThroughClass mobject must be a PiCreatureClass")
digest_config(self, kwargs)
self.indices = range(mobject.height * mobject.width)
if mode == "random":
np.random.shuffle(self.indices)
Animation.__init__(self, mobject, **kwargs)
def update_mobject(self, alpha):
index = int(np.floor(alpha * self.mobject.height * self.mobject.width))
for pi in self.mobject:
pi.set_color(BLUE_E)
if index < self.mobject.height * self.mobject.width:
self.mobject[self.indices[index]].set_color(self.highlight_color)

View file

@ -139,7 +139,7 @@ class Matrix(VMobject):
class DecimalMatrix(Matrix): class DecimalMatrix(Matrix):
CONFIG = { CONFIG = {
"element_to_mobject": DecimalNumber, "element_to_mobject": DecimalNumber,
"element_to_mobject_config": {"num_decimal_points": 1} "element_to_mobject_config": {"num_decimal_places": 1}
} }

View file

@ -623,13 +623,17 @@ class Mobject(Container):
values = [] values = []
values += [ values += [
mob.reduce_across_dimension(points_func, reduce_func, dim) mob.reduce_across_dimension(points_func, reduce_func, dim)
for mob in self.submobjects for mob in self.nonempty_submobjects()
] ]
try: try:
return reduce_func(values) return reduce_func(values)
except: except:
return 0 return 0
def nonempty_submobjects(self):
return [submob for submob in self.submobjects
if len(submob.submobjects) != 0 or len(submob.points) != 0]
def get_merged_array(self, array_attr): def get_merged_array(self, array_attr):
result = None result = None
for mob in self.family_members_with_points(): for mob in self.family_members_with_points():
@ -745,6 +749,7 @@ class Mobject(Container):
def submobject_family(self): def submobject_family(self):
sub_families = map(Mobject.submobject_family, self.submobjects) sub_families = map(Mobject.submobject_family, self.submobjects)
all_mobjects = [self] + list(it.chain(*sub_families)) all_mobjects = [self] + list(it.chain(*sub_families))
#all_mobjects = list(it.chain(*sub_families)) + [self]
return remove_list_redundancies(all_mobjects) return remove_list_redundancies(all_mobjects)
def family_members_with_points(self): def family_members_with_points(self):

View file

@ -8,7 +8,7 @@ from mobject.types.vectorized_mobject import VMobject
class DecimalNumber(VMobject): class DecimalNumber(VMobject):
CONFIG = { CONFIG = {
"num_decimal_points": 2, "num_decimal_places": 2,
"digit_to_digit_buff": 0.05, "digit_to_digit_buff": 0.05,
"show_ellipsis": False, "show_ellipsis": False,
"unit": None, # Aligned to bottom unless it starts with "^" "unit": None, # Aligned to bottom unless it starts with "^"
@ -18,7 +18,7 @@ class DecimalNumber(VMobject):
def __init__(self, number, **kwargs): def __init__(self, number, **kwargs):
VMobject.__init__(self, **kwargs) VMobject.__init__(self, **kwargs)
self.number = number self.number = number
ndp = self.num_decimal_points ndp = self.num_decimal_places
# Build number string # Build number string
if isinstance(number, complex): if isinstance(number, complex):
@ -71,5 +71,5 @@ class DecimalNumber(VMobject):
class Integer(DecimalNumber): class Integer(DecimalNumber):
CONFIG = { CONFIG = {
"num_decimal_points": 0, "num_decimal_places": 0,
} }

View file

@ -5,6 +5,7 @@ from svg_mobject import VMobjectFromSVGPathstring
from utils.config_ops import digest_config from utils.config_ops import digest_config
from utils.strings import split_string_list_to_isolate_substring from utils.strings import split_string_list_to_isolate_substring
from utils.tex_file_writing import tex_to_svg_file from utils.tex_file_writing import tex_to_svg_file
from mobject.geometry import Line
from mobject.types.vectorized_mobject import VGroup from mobject.types.vectorized_mobject import VGroup
from mobject.types.vectorized_mobject import VectorizedPoint from mobject.types.vectorized_mobject import VectorizedPoint
@ -290,3 +291,27 @@ class TexMobjectFromPresetString(TexMobject):
TexMobject.__init__(self, self.tex, **kwargs) TexMobject.__init__(self, self.tex, **kwargs)
self.set_color(self.color) self.set_color(self.color)
class Title(TextMobject):
CONFIG = {
"scale_factor": 1,
"include_underline": True,
"underline_width": FRAME_WIDTH - 2,
# This will override underline_width
"match_underline_width_to_text": False,
"underline_buff": MED_SMALL_BUFF,
}
def __init__(self, text, **kwargs):
TextMobject.__init__(self, text, **kwargs)
self.scale(self.scale_factor)
self.to_edge(UP)
if self.include_underline:
underline = Line(LEFT, RIGHT)
underline.next_to(self, DOWN, buff=self.underline_buff)
if self.match_underline_width_to_text:
underline.match_width(self)
else:
underline.scale_to_fit_width(self.underline_width)
self.add(underline)
self.underline = underline

View file

@ -565,7 +565,7 @@ def walker_animation_with_display(
number_update_func = None, number_update_func = None,
show_arrows = True, show_arrows = True,
scale_arrows = False, scale_arrows = False,
num_decimal_points = 1, num_decimal_places = 1,
include_background_rectangle = True, include_background_rectangle = True,
**kwargs **kwargs
): ):
@ -581,7 +581,7 @@ def walker_animation_with_display(
if number_update_func != None: if number_update_func != None:
display = DecimalNumber(0, display = DecimalNumber(0,
num_decimal_points = num_decimal_points, num_decimal_places = num_decimal_places,
fill_color = WHITE if include_background_rectangle else BLACK, fill_color = WHITE if include_background_rectangle else BLACK,
include_background_rectangle = include_background_rectangle) include_background_rectangle = include_background_rectangle)
if include_background_rectangle: if include_background_rectangle:
@ -732,7 +732,7 @@ class PiWalker(ColorMappedByFuncScene):
"show_num_plane" : False, "show_num_plane" : False,
"draw_lines" : True, "draw_lines" : True,
"num_checkpoints" : 10, "num_checkpoints" : 10,
"num_decimal_points" : 1, "num_decimal_places" : 1,
"include_background_rectangle" : False, "include_background_rectangle" : False,
} }
@ -788,7 +788,7 @@ class PiWalker(ColorMappedByFuncScene):
number_update_func = number_update_func, number_update_func = number_update_func,
run_time = self.step_run_time, run_time = self.step_run_time,
walker_stroke_color = WALKER_LIGHT_COLOR if self.color_foreground_not_background else BLACK, walker_stroke_color = WALKER_LIGHT_COLOR if self.color_foreground_not_background else BLACK,
num_decimal_points = self.num_decimal_points, num_decimal_places = self.num_decimal_places,
include_background_rectangle = self.include_background_rectangle, include_background_rectangle = self.include_background_rectangle,
) )
@ -2751,7 +2751,7 @@ class OneFifthTwoFifthWinder(SpecifiedWinder):
"step_size" : 0.01, "step_size" : 0.01,
"show_num_plane" : False, "show_num_plane" : False,
"step_run_time" : 6, "step_run_time" : 6,
"num_decimal_points" : 2, "num_decimal_places" : 2,
} }
class OneFifthOneFifthWinderWithReset(OneFifthTwoFifthWinder): class OneFifthOneFifthWinderWithReset(OneFifthTwoFifthWinder):

View file

@ -386,7 +386,7 @@ class Introduce1DFunctionCase(Scene):
) )
decimal = DecimalNumber( decimal = DecimalNumber(
0, 0,
num_decimal_points = 3, num_decimal_places = 3,
show_ellipsis = True, show_ellipsis = True,
) )
decimal.scale(0.7) decimal.scale(0.7)
@ -484,7 +484,7 @@ class Introduce1DFunctionCase(Scene):
if show_decimal: if show_decimal:
decimal = DecimalNumber( decimal = DecimalNumber(
axes.x_axis.point_to_number(arrow.get_start()), axes.x_axis.point_to_number(arrow.get_start()),
num_decimal_points = 3, num_decimal_places = 3,
# show_ellipsis = True, # show_ellipsis = True,
) )
height = self.rect.get_height() height = self.rect.get_height()
@ -2310,7 +2310,7 @@ class TransitionFromPathsToBoundaries(ColorMappedObjectsScene):
) )
) )
label = DecimalNumber(0, num_decimal_points = 1) label = DecimalNumber(0, num_decimal_places = 1)
label_upadte = ContinualChangingDecimal( label_upadte = ContinualChangingDecimal(
label, get_total_winding, label, get_total_winding,
position_update_func = lambda l : l.next_to(dot, UP+LEFT, SMALL_BUFF) position_update_func = lambda l : l.next_to(dot, UP+LEFT, SMALL_BUFF)

View file

@ -119,7 +119,7 @@ class LightIndicator(VMobject):
self.foreground.set_stroke(color=INDICATOR_STROKE_COLOR,width=INDICATOR_STROKE_WIDTH) self.foreground.set_stroke(color=INDICATOR_STROKE_COLOR,width=INDICATOR_STROKE_WIDTH)
self.add(self.background, self.foreground) self.add(self.background, self.foreground)
self.reading = DecimalNumber(self.intensity,num_decimal_points = self.precision) self.reading = DecimalNumber(self.intensity,num_decimal_places = self.precision)
self.reading.set_fill(color=INDICATOR_TEXT_COLOR) self.reading.set_fill(color=INDICATOR_TEXT_COLOR)
self.reading.move_to(self.get_center()) self.reading.move_to(self.get_center())
if self.show_reading: if self.show_reading:
@ -287,7 +287,7 @@ class IntroScene(PiCreatureScene):
equals_sign = self.euler_sum.get_part_by_tex("=") equals_sign = self.euler_sum.get_part_by_tex("=")
self.partial_sum_decimal = DecimalNumber(partial_results_values[1], self.partial_sum_decimal = DecimalNumber(partial_results_values[1],
num_decimal_points = 2) num_decimal_places = 2)
self.partial_sum_decimal.next_to(equals_sign, RIGHT) self.partial_sum_decimal.next_to(equals_sign, RIGHT)
@ -313,7 +313,7 @@ class IntroScene(PiCreatureScene):
self.partial_sum_decimal, self.partial_sum_decimal,
partial_results_values[i+1], partial_results_values[i+1],
run_time = self.duration, run_time = self.duration,
num_decimal_points = 6, num_decimal_places = 6,
show_ellipsis = True, show_ellipsis = True,
position_update_func = lambda m: m.next_to(equals_sign, RIGHT) position_update_func = lambda m: m.next_to(equals_sign, RIGHT)
) )
@ -863,7 +863,7 @@ class SingleLighthouseScene(PiCreatureScene):
# angle msmt (decimal number) # angle msmt (decimal number)
self.angle_indicator = DecimalNumber(arc_angle / DEGREES, self.angle_indicator = DecimalNumber(arc_angle / DEGREES,
num_decimal_points = 0, num_decimal_places = 0,
unit = "^\\circ", unit = "^\\circ",
fill_opacity = 1.0, fill_opacity = 1.0,
fill_color = WHITE) fill_color = WHITE)
@ -4262,7 +4262,7 @@ class LabeledArc(Arc):
Arc.__init__(self,angle,**kwargs) Arc.__init__(self,angle,**kwargs)
label = DecimalNumber(self.length, num_decimal_points = 0) label = DecimalNumber(self.length, num_decimal_places = 0)
r = BUFFER * self.radius r = BUFFER * self.radius
theta = self.start_angle + self.angle/2 theta = self.start_angle + self.angle/2
label_pos = r * np.array([np.cos(theta), np.sin(theta), 0]) label_pos = r * np.array([np.cos(theta), np.sin(theta), 0])

View file

@ -94,7 +94,7 @@ class LightIndicator(Mobject):
self.foreground.set_fill(color = self.fill_color) self.foreground.set_fill(color = self.fill_color)
self.add(self.background, self.foreground) self.add(self.background, self.foreground)
self.reading = DecimalNumber(self.intensity,num_decimal_points = self.precision) self.reading = DecimalNumber(self.intensity,num_decimal_places = self.precision)
self.reading.set_fill(color=INDICATOR_TEXT_COLOR) self.reading.set_fill(color=INDICATOR_TEXT_COLOR)
self.reading.scale_to_fit_height(self.reading_height) self.reading.scale_to_fit_height(self.reading_height)
self.reading.move_to(self.get_center()) self.reading.move_to(self.get_center())
@ -317,7 +317,7 @@ class IntroScene(PiCreatureScene):
partial_sum_decimal = self.partial_sum_decimal = DecimalNumber( partial_sum_decimal = self.partial_sum_decimal = DecimalNumber(
series_terms[1], series_terms[1],
num_decimal_points = 2 num_decimal_places = 2
) )
partial_sum_decimal.next_to(equals_sign, RIGHT) partial_sum_decimal.next_to(equals_sign, RIGHT)
@ -418,7 +418,7 @@ class IntroScene(PiCreatureScene):
partial_sum_decimal, partial_sum_decimal,
series_terms[i+1], series_terms[i+1],
run_time = 1, run_time = 1,
num_decimal_points = 6, num_decimal_places = 6,
position_update_func = lambda m: m.next_to(equals_sign, RIGHT) position_update_func = lambda m: m.next_to(equals_sign, RIGHT)
) )
] ]
@ -430,7 +430,7 @@ class IntroScene(PiCreatureScene):
ChangeDecimalToValue( ChangeDecimalToValue(
partial_sum_decimal, partial_sum_decimal,
series_terms[i+1], series_terms[i+1],
num_decimal_points = 6, num_decimal_places = 6,
), ),
] ]
if i == 5: if i == 5:
@ -451,7 +451,7 @@ class IntroScene(PiCreatureScene):
ChangeDecimalToValue( ChangeDecimalToValue(
partial_sum_decimal, partial_sum_decimal,
series_terms[-1], series_terms[-1],
num_decimal_points = 6, num_decimal_places = 6,
), ),
morty.change, "confused", morty.change, "confused",
) )
@ -1295,7 +1295,7 @@ class IntroduceScreen(Scene):
self.angle_indicator = DecimalNumber( self.angle_indicator = DecimalNumber(
arc_angle / DEGREES, arc_angle / DEGREES,
num_decimal_points = 0, num_decimal_places = 0,
unit = "^\\circ" unit = "^\\circ"
) )
self.angle_indicator.next_to(self.angle_arc, RIGHT) self.angle_indicator.next_to(self.angle_arc, RIGHT)
@ -3818,7 +3818,7 @@ class ThinkBackToHowAmazingThisIs(ThreeDScene):
dot_pairs = it.starmap(VGroup, zip(positive_dots, negative_dots)) dot_pairs = it.starmap(VGroup, zip(positive_dots, negative_dots))
# Decimal # Decimal
decimal = DecimalNumber(0, num_decimal_points = 6) decimal = DecimalNumber(0, num_decimal_places = 6)
decimal.to_edge(UP) decimal.to_edge(UP)
terms = [2./(n**2) for n in range(1, 100, 2)] terms = [2./(n**2) for n in range(1, 100, 2)]
partial_sums = np.cumsum(terms) partial_sums = np.cumsum(terms)
@ -4250,7 +4250,7 @@ class LabeledArc(Arc):
Arc.__init__(self,angle,**kwargs) Arc.__init__(self,angle,**kwargs)
label = DecimalNumber(self.length, num_decimal_points = 0) label = DecimalNumber(self.length, num_decimal_places = 0)
r = BUFFER * self.radius r = BUFFER * self.radius
theta = self.start_angle + self.angle/2 theta = self.start_angle + self.angle/2
label_pos = r * np.array([np.cos(theta), np.sin(theta), 0]) label_pos = r * np.array([np.cos(theta), np.sin(theta), 0])

View file

@ -728,7 +728,7 @@ class UnmixMixedPaint(Scene):
class MachineThatTreatsOneFrequencyDifferently(Scene): class MachineThatTreatsOneFrequencyDifferently(Scene):
def construct(self): def construct(self):
graph = self.get_cosine_graph(0.5) graph = self.get_cosine_graph(0.5)
frequency_mob = DecimalNumber(220, num_decimal_points = 0) frequency_mob = DecimalNumber(220, num_decimal_places = 0)
frequency_mob.next_to(graph, UP, buff = MED_LARGE_BUFF) frequency_mob.next_to(graph, UP, buff = MED_LARGE_BUFF)
self.graph = graph self.graph = graph
@ -1273,7 +1273,7 @@ class WrapCosineGraphAroundCircle(FourierMachineScene):
def get_winding_frequency_label(self): def get_winding_frequency_label(self):
freq = self.initial_winding_frequency freq = self.initial_winding_frequency
winding_freq_label = VGroup( winding_freq_label = VGroup(
DecimalNumber(freq, num_decimal_points = 2), DecimalNumber(freq, num_decimal_places = 2),
TextMobject("cycles/second") TextMobject("cycles/second")
) )
winding_freq_label.arrange_submobjects(RIGHT) winding_freq_label.arrange_submobjects(RIGHT)

View file

@ -1805,7 +1805,7 @@ class BoxCountingScene(Scene):
return label return label
def count_boxes(self, boxes): def count_boxes(self, boxes):
num = DecimalNumber(len(boxes), num_decimal_points = 0) num = DecimalNumber(len(boxes), num_decimal_places = 0)
num.next_to(boxes, RIGHT) num.next_to(boxes, RIGHT)
num.add_to_back(BackgroundRectangle(num)) num.add_to_back(BackgroundRectangle(num))

View file

@ -559,7 +559,7 @@ class WriteAProgram(Scene):
rgb = square.fill_rgb rgb = square.fill_rgb
num = DecimalNumber( num = DecimalNumber(
square.fill_rgb[0], square.fill_rgb[0],
num_decimal_points = 1 num_decimal_places = 1
) )
num.set_stroke(width = 1) num.set_stroke(width = 1)
color = rgba_to_color(1 - (rgb + 0.2)/1.2) color = rgba_to_color(1 - (rgb + 0.2)/1.2)
@ -1113,7 +1113,7 @@ class IntroduceEachLayer(PreviewMNistNetwork):
example_num = None example_num = None
for neuron in neurons: for neuron in neurons:
o = neuron.get_fill_opacity() o = neuron.get_fill_opacity()
num = DecimalNumber(o, num_decimal_points = 1) num = DecimalNumber(o, num_decimal_places = 1)
num.scale_to_fit_width(0.7*neuron.get_width()) num.scale_to_fit_width(0.7*neuron.get_width())
num.move_to(neuron) num.move_to(neuron)
if o > 0.8: if o > 0.8:

View file

@ -962,14 +962,14 @@ class IntroduceCostFunction(PreviewLearning):
terms = VGroup() terms = VGroup()
term_updates = [] term_updates = []
for arrow, d1, d2 in zip(arrows, *self.decimal_groups): for arrow, d1, d2 in zip(arrows, *self.decimal_groups):
term = DecimalNumber(0, num_decimal_points = 4) term = DecimalNumber(0, num_decimal_places = 4)
term.scale_to_fit_height(d1.get_height()) term.scale_to_fit_height(d1.get_height())
term.next_to(arrow, LEFT) term.next_to(arrow, LEFT)
term.num_update_func = generate_term_update_func(d1, d2) term.num_update_func = generate_term_update_func(d1, d2)
terms.add(term) terms.add(term)
term_updates.append(ChangingDecimalWithColor( term_updates.append(ChangingDecimalWithColor(
term, term.num_update_func, term, term.num_update_func,
num_decimal_points = 4 num_decimal_places = 4
)) ))
brace.target.next_to(terms, LEFT) brace.target.next_to(terms, LEFT)
@ -2780,7 +2780,7 @@ class TestPerformance(PreviewLearning):
"wrong_wait_time" : 0.5, "wrong_wait_time" : 0.5,
"stroke_width_exp" : 2, "stroke_width_exp" : 2,
"decimal_kwargs" : { "decimal_kwargs" : {
"num_decimal_points" : 3, "num_decimal_places" : 3,
} }
} }
def construct(self): def construct(self):

View file

@ -671,7 +671,7 @@ class WalkThroughTwoExample(ShowAveragingCost):
decimals = VGroup() decimals = VGroup()
for neuron in neurons: for neuron in neurons:
activation = neuron.get_fill_opacity() activation = neuron.get_fill_opacity()
decimal = DecimalNumber(activation, num_decimal_points = 1) decimal = DecimalNumber(activation, num_decimal_places = 1)
decimal.scale_to_fit_width(0.7*neuron.get_width()) decimal.scale_to_fit_width(0.7*neuron.get_width())
decimal.move_to(neuron) decimal.move_to(neuron)
if activation > 0.8: if activation > 0.8:
@ -748,7 +748,7 @@ class WalkThroughTwoExample(ShowAveragingCost):
anims.append(ChangingDecimal( anims.append(ChangingDecimal(
decimal, decimal,
get_decimal_update(decimal.number, target), get_decimal_update(decimal.number, target),
num_decimal_points = 1 num_decimal_places = 1
)) ))
anims.append(UpdateFromFunc( anims.append(UpdateFromFunc(
self.decimals[i], self.decimals[i],
@ -1076,7 +1076,7 @@ class WalkThroughTwoExample(ShowAveragingCost):
ChangingDecimal( ChangingDecimal(
two_decimal, two_decimal,
lambda a : interpolate(two_activation, 1, a), lambda a : interpolate(two_activation, 1, a),
num_decimal_points = 1, num_decimal_places = 1,
), ),
UpdateFromFunc( UpdateFromFunc(
two_decimal, two_decimal,
@ -1110,7 +1110,7 @@ class WalkThroughTwoExample(ShowAveragingCost):
ChangingDecimal( ChangingDecimal(
two_decimal, two_decimal,
lambda a : interpolate(1, two_activation, a), lambda a : interpolate(1, two_activation, a),
num_decimal_points = 1, num_decimal_places = 1,
), ),
UpdateFromFunc( UpdateFromFunc(
two_decimal, two_decimal,
@ -3613,7 +3613,7 @@ class SimplestNetworkExample(PreviewLearning):
def get_neuron_activation_decimal(self, neuron): def get_neuron_activation_decimal(self, neuron):
opacity = neuron.get_fill_opacity() opacity = neuron.get_fill_opacity()
decimal = DecimalNumber(opacity, num_decimal_points = 2) decimal = DecimalNumber(opacity, num_decimal_places = 2)
decimal.scale_to_fit_width(0.85*neuron.get_width()) decimal.scale_to_fit_width(0.85*neuron.get_width())
if decimal.number > 0.8: if decimal.number > 0.8:
decimal.set_fill(BLACK) decimal.set_fill(BLACK)

View file

@ -226,7 +226,7 @@ def get_circle_drawing_terms(radius = 1, positioning_func = lambda m : m.center(
0.25*rotate_vector(radius.get_vector(), TAU/4) 0.25*rotate_vector(radius.get_vector(), TAU/4)
), ),
) )
decimal = DecimalNumber(0, num_decimal_points = 4, show_ellipsis = True) decimal = DecimalNumber(0, num_decimal_places = 4, show_ellipsis = True)
decimal.scale(0.75) decimal.scale(0.75)
def reposition_decimal(decimal): def reposition_decimal(decimal):
vect = radius.get_vector() vect = radius.get_vector()
@ -318,7 +318,7 @@ class PiTauDebate(PiCreatureScene):
circum_line.next_to(circle, DOWN, buff = MED_LARGE_BUFF) circum_line.next_to(circle, DOWN, buff = MED_LARGE_BUFF)
# circum_line.to_edge(LEFT) # circum_line.to_edge(LEFT)
brace = Brace(circum_line, DOWN, buff = SMALL_BUFF) brace = Brace(circum_line, DOWN, buff = SMALL_BUFF)
decimal = DecimalNumber(np.pi, num_decimal_points = 4, show_ellipsis = True) decimal = DecimalNumber(np.pi, num_decimal_places = 4, show_ellipsis = True)
decimal.scale(0.75) decimal.scale(0.75)
decimal.next_to(brace, DOWN, SMALL_BUFF) decimal.next_to(brace, DOWN, SMALL_BUFF)

View file

@ -112,7 +112,7 @@ class Introduction(Scene):
) )
get_arrow_update().update(1) get_arrow_update().update(1)
decimal = DecimalNumber( decimal = DecimalNumber(
curr_product, num_decimal_points=5, show_ellipsis=True) curr_product, num_decimal_places=5, show_ellipsis=True)
decimal.next_to(arrow, UP, SMALL_BUFF, submobject_to_align=decimal[:5]) decimal.next_to(arrow, UP, SMALL_BUFF, submobject_to_align=decimal[:5])
decimal_anim = ChangingDecimal( decimal_anim = ChangingDecimal(
decimal, decimal,
@ -512,7 +512,7 @@ class ShowProduct(Scene):
]) ])
brace = braces[0].copy() brace = braces[0].copy()
decimal = DecimalNumber(partial_products[0], num_decimal_points=4) decimal = DecimalNumber(partial_products[0], num_decimal_places=4)
decimal.next_to(brace, DOWN) decimal.next_to(brace, DOWN)
self.add(brace, decimal, dots[0], parts[0]) self.add(brace, decimal, dots[0], parts[0])
@ -677,7 +677,7 @@ class ShowProduct(Scene):
]) ])
brace = braces[0].copy() brace = braces[0].copy()
decimal = DecimalNumber(partial_products_iter.next(), num_decimal_points=4) decimal = DecimalNumber(partial_products_iter.next(), num_decimal_places=4)
decimal.next_to(brace, DOWN) decimal.next_to(brace, DOWN)
self.play(*map(FadeIn, [brace, decimal, dots[0]])) self.play(*map(FadeIn, [brace, decimal, dots[0]]))
@ -894,7 +894,7 @@ class DistanceProductScene(MovingCameraScene):
self.d_labels.add(d_label) self.d_labels.add(d_label)
return self.d_labels return self.d_labels
def get_numeric_distance_labels(self, lines=None, num_decimal_points=3, show_ellipsis=True): def get_numeric_distance_labels(self, lines=None, num_decimal_places=3, show_ellipsis=True):
radius = self.circle.get_width() / 2 radius = self.circle.get_width() / 2
if lines is None: if lines is None:
if not hasattr(self, "distance_lines"): if not hasattr(self, "distance_lines"):
@ -904,7 +904,7 @@ class DistanceProductScene(MovingCameraScene):
for line in lines: for line in lines:
label = DecimalNumber( label = DecimalNumber(
line.get_length() / radius, line.get_length() / radius,
num_decimal_points=num_decimal_points, num_decimal_places=num_decimal_places,
show_ellipsis=show_ellipsis, show_ellipsis=show_ellipsis,
include_background_rectangle=self.include_distance_labels_background_rectangle, include_background_rectangle=self.include_distance_labels_background_rectangle,
) )
@ -943,7 +943,7 @@ class DistanceProductScene(MovingCameraScene):
product_decimal = DecimalNumber( product_decimal = DecimalNumber(
self.get_distance_product(fraction), self.get_distance_product(fraction),
num_decimal_points=3, num_decimal_places=3,
show_ellipsis=True, show_ellipsis=True,
include_background_rectangle=self.include_distance_labels_background_rectangle, include_background_rectangle=self.include_distance_labels_background_rectangle,
) )
@ -1632,7 +1632,7 @@ class FromGeometryToAlgebra(DistanceProductScene):
values = map(plane.point_to_number, self.get_lh_points()) values = map(plane.point_to_number, self.get_lh_points())
complex_decimal = self.complex_decimal = DecimalNumber( complex_decimal = self.complex_decimal = DecimalNumber(
values[3], values[3],
num_decimal_points=3, num_decimal_places=3,
include_background_rectangle=True include_background_rectangle=True
) )
complex_decimal.next_to(outer_arrow.get_start(), LEFT, SMALL_BUFF) complex_decimal.next_to(outer_arrow.get_start(), LEFT, SMALL_BUFF)
@ -2190,7 +2190,7 @@ class PlugObserverIntoPolynomial(DistanceProductScene):
numeric_chord_label = DecimalNumber( numeric_chord_label = DecimalNumber(
np.sqrt(3), np.sqrt(3),
num_decimal_points=4, num_decimal_places=4,
include_background_rectangle=True, include_background_rectangle=True,
show_ellipsis=True, show_ellipsis=True,
) )
@ -2907,7 +2907,7 @@ class ProveLemma2(PlugObserverIntoPolynomial):
product = DecimalNumber( product = DecimalNumber(
self.num_lighthouses, self.num_lighthouses,
num_decimal_points=3, num_decimal_places=3,
show_ellipsis=True show_ellipsis=True
) )
product.move_to(self.q_marks, LEFT) product.move_to(self.q_marks, LEFT)
@ -3235,7 +3235,7 @@ class KeeperAndSailor(DistanceProductScene, PiCreatureScene):
new_keeper_dp_decimal = DecimalNumber( new_keeper_dp_decimal = DecimalNumber(
self.num_lighthouses, self.num_lighthouses,
num_decimal_points=3, num_decimal_places=3,
) )
new_keeper_dp_decimal.replace(keeper_dp_decimal, dim_to_match=1) new_keeper_dp_decimal.replace(keeper_dp_decimal, dim_to_match=1)
new_keeper_dp_decimal.set_color(YELLOW) new_keeper_dp_decimal.set_color(YELLOW)

View file

@ -4,6 +4,9 @@ from utils.bezier import bezier
from utils.simple_functions import sigmoid from utils.simple_functions import sigmoid
def linear(t):
return t
def smooth(t, inflection=10.0): def smooth(t, inflection=10.0):
error = sigmoid(-inflection / 2) error = sigmoid(-inflection / 2)
return (sigmoid(inflection * (t - 0.5)) - error) / (1 - 2 * error) return (sigmoid(inflection * (t - 0.5)) - error) / (1 - 2 * error)

View file

@ -1,81 +0,0 @@
import os
from constants import TEX_DIR
from constants import TEX_TEXT_TO_REPLACE
def tex_hash(expression, template_tex_file):
return str(hash(expression + template_tex_file))
def tex_to_svg_file(expression, template_tex_file):
tex_file = generate_tex_file(expression, template_tex_file)
dvi_file = tex_to_dvi(tex_file)
return dvi_to_svg(dvi_file)
def generate_tex_file(expression, template_tex_file):
result = os.path.join(
TEX_DIR,
tex_hash(expression, template_tex_file)
) + ".tex"
if not os.path.exists(result):
print("Writing \"%s\" to %s" % (
"".join(expression), result
))
with open(template_tex_file, "r") as infile:
body = infile.read()
body = body.replace(TEX_TEXT_TO_REPLACE, expression)
with open(result, "w") as outfile:
outfile.write(body)
return result
def get_null():
if os.name == "nt":
return "NUL"
return "/dev/null"
def tex_to_dvi(tex_file):
result = tex_file.replace(".tex", ".dvi")
if not os.path.exists(result):
commands = [
"latex",
"-interaction=batchmode",
"-halt-on-error",
"-output-directory=" + TEX_DIR,
tex_file,
">",
get_null()
]
exit_code = os.system(" ".join(commands))
if exit_code != 0:
log_file = tex_file.replace(".tex", ".log")
raise Exception(
"Latex error converting to dvi. "
"See log output above or the log file: %s" % log_file)
return result
def dvi_to_svg(dvi_file, regen_if_exists=False):
"""
Converts a dvi, which potentially has multiple slides, into a
directory full of enumerated pngs corresponding with these slides.
Returns a list of PIL Image objects for these images sorted as they
where in the dvi
"""
result = dvi_file.replace(".dvi", ".svg")
if not os.path.exists(result):
commands = [
"dvisvgm",
dvi_file,
"-n",
"-v",
"0",
"-o",
result,
">",
get_null()
]
os.system(" ".join(commands))
return result