diff --git a/active_projects/alt_calc.py b/active_projects/alt_calc.py index d6804c5c..3458b49a 100644 --- a/active_projects/alt_calc.py +++ b/active_projects/alt_calc.py @@ -47,18 +47,19 @@ class WriteOpeningWords(Scene): class StartingCalc101(PiCreatureScene): CONFIG = { + # "default_pi_creature_kwargs": { + # "color": BLUE, + # "flip_at_start": False, + # }, } def construct(self): randy = self.pi_creature - deriv_equation = TexMobject( - "\\frac{df}{dx}(x) = \\lim(\\Delta x \\to \\infty)" + - "{f(x + \\Delta x) - f(x) \\over \\Delta x}", - tex_to_color_map={"\\Delta x": BLUE} + deriv_string = "\\frac{df}{dx}(x) = \\lim(\\delta x \\to \\infty)" + \ + "{f(x + \\delta x) - f(x) \\over \\delta x}" + equations = VGroup( + TexMobject(*break_up_string_by_terms(deriv_string, "\\delta x")) ) - self.add(deriv_equation) - equations = VGroup(deriv_equation) - title = TextMobject("Calculus 101") title.to_edge(UP) h_line = Line(LEFT, RIGHT) diff --git a/active_projects/eop/chapter1/all_sequences.py b/active_projects/eop/chapter1/all_sequences.py new file mode 100644 index 00000000..3a9d7e70 --- /dev/null +++ b/active_projects/eop/chapter1/all_sequences.py @@ -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 + + + + + diff --git a/active_projects/eop/chapter1/area_model_erf.py b/active_projects/eop/chapter1/area_model_erf.py index cb978360..36fd0cce 100644 --- a/active_projects/eop/chapter1/area_model_erf.py +++ b/active_projects/eop/chapter1/area_model_erf.py @@ -84,7 +84,7 @@ class IllustrateAreaModelErf(GraphScene): 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) self.play( FadeIn(equals_sign), @@ -99,13 +99,13 @@ class IllustrateAreaModelErf(GraphScene): self.add(ContinualChangingDecimal( decimal_number_mobject = cdf_value, number_update_func = integral_update_func, - num_decimal_points = 3 + num_decimal_places = 3 )) self.add(ContinualChangingDecimal( decimal_number_mobject = cdf_percentage, number_update_func = integral_update_func_percent, - num_decimal_points = 1 + num_decimal_places = 1 )) diff --git a/active_projects/eop/chapter1/brick_row_scene.py b/active_projects/eop/chapter1/brick_row_scene.py index 6c8b06f6..b11a66ca 100644 --- a/active_projects/eop/chapter1/brick_row_scene.py +++ b/active_projects/eop/chapter1/brick_row_scene.py @@ -5,7 +5,7 @@ from active_projects.eop.reusable_imports import * 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 # either horizontally on top of the brick row # or diagonally into the bricks @@ -15,12 +15,12 @@ class BrickRowScene(PiCreatureScene): tally_targets_left = [ rect.get_center() + 0.25 * rect.get_width() * LEFT - for rect in self.row.rects + for rect in row.rects ] tally_targets_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): @@ -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 # Execution can be timed afterwards # Returns two lists: first all those going left, then those to the right @@ -73,12 +73,12 @@ class BrickRowScene(PiCreatureScene): tally_targets_left = [ rect.get_center() + 0.25 * rect.get_width() * LEFT - for rect in self.row.rects + for rect in row.rects ] tally_targets_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): @@ -122,13 +122,14 @@ class BrickRowScene(PiCreatureScene): 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)) - 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 - anims1, anims2 = self.tally_split_animations(direction = direction) + anims1, anims2 = self.tally_split_animations(row, direction = direction) self.play(*anims1) self.wait(0.3) 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.generate_points() - half_merged_row.move_to(self.row) + half_merged_row.move_to(row) self.play(FadeIn(half_merged_row)) - self.remove(self.row) - self.row = half_merged_row + self.remove(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): tally_targets = [ 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): - 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: target[1] = y_pos else: @@ -186,25 +187,25 @@ class BrickRowScene(PiCreatureScene): 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.generate_points() - merged_row.move_to(self.row) + merged_row.move_to(row) self.play(FadeIn(merged_row)) - self.remove(self.row) - self.row = merged_row + self.remove(row) + return merged_row - def move_tallies_on_top(self): + def move_tallies_on_top(self, row): 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: - tally.anchor += 1.2 * 0.5 * self.row.height * UP + tally.anchor += 1.2 * 0.5 * row.height * UP def create_pi_creature(self): randy = CoinFlippingPiCreature(color = MAROON_E) @@ -256,12 +257,11 @@ class BrickRowScene(PiCreatureScene): # # # # # # # # - self.play(FlipCoin(randy)) self.play(SplitRectsInBrickWall(self.row)) - self.merge_rects_by_subdiv() - self.merge_rects_by_coloring() + self.row = self.merge_rects_by_subdiv(self.row) + self.row = self.merge_rects_by_coloring(self.row) # # put tallies on top @@ -312,7 +312,6 @@ class BrickRowScene(PiCreatureScene): new_tails[i].shift(COIN_SEQUENCE_SPACING * DOWN) self.play(FadeIn(new_tails)) - decimal_tallies = VGroup() # introduce notion of tallies for (i, rect) in enumerate(self.row.get_rects_for_level(2)): @@ -347,6 +346,7 @@ class BrickRowScene(PiCreatureScene): ) self.wait() + self.tallies = VGroup() for (i, rect) in enumerate(self.row.get_rects_for_level(2)): tally = TallyStack(2-i, i, show_decimals = False) @@ -357,6 +357,7 @@ class BrickRowScene(PiCreatureScene): self.play(FadeIn(self.tallies)) self.wait() + anims = [] for (decimal_tally, tally_stack) in zip(decimal_tallies, self.tallies): anims.append(ApplyFunction( @@ -366,6 +367,7 @@ class BrickRowScene(PiCreatureScene): self.play(*anims) self.wait() + # replace the original decimal tallies with # the ones that belong to the TallyStacks 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) self.add_foreground_mobject(self.tallies) - self.merge_rects_by_subdiv() + self.row = self.merge_rects_by_subdiv(self.row) self.wait() - self.merge_rects_by_coloring() + self.row = self.merge_rects_by_coloring(self.row) self.wait() @@ -494,7 +496,7 @@ class BrickRowScene(PiCreatureScene): ) self.wait() - self.split_tallies_in_two_steps() + self.split_tallies_in_two_steps(self.row) self.wait() self.add_foreground_mobject(self.tallies) @@ -554,7 +556,7 @@ class BrickRowScene(PiCreatureScene): # self.wait() - # self.merge_rects_by_subdiv() + # self.row = self.merge_rects_by_subdiv(self.row) # self.wait() # self.play( @@ -575,9 +577,9 @@ class BrickRowScene(PiCreatureScene): # self.wait() - # self.merge_tallies(target_pos = DOWN) + # self.merge_tallies(self.row, target_pos = DOWN) # self.add_foreground_mobject(self.tallies) - # self.merge_rects_by_coloring() + # self.row = self.merge_rects_by_coloring(self.row) # self.wait() @@ -645,7 +647,7 @@ class BrickRowScene(PiCreatureScene): self.wait() - self.merge_rects_by_subdiv() + self.row = self.merge_rects_by_subdiv(self.row) self.wait() self.play( @@ -666,9 +668,9 @@ class BrickRowScene(PiCreatureScene): self.wait() - self.merge_tallies(target_pos = DOWN) + self.merge_tallies(self.row, target_pos = DOWN) self.add_foreground_mobject(self.tallies) - self.merge_rects_by_coloring() + self.row = self.merge_rects_by_coloring(self.row) self.wait() @@ -677,11 +679,18 @@ class BrickRowScene(PiCreatureScene): with_labels = True, inset = True) self.play(FadeOut(self.tallies)) - self.play(LaggedStart( - FadeIn, outcomes)) self.wait() 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)) brace1 = Brace(self.row.rects[2], UP) @@ -705,48 +714,54 @@ class BrickRowScene(PiCreatureScene): ) 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 # # # # # # # # # - # 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() self.add(previous_row) v = 1.25 * self.row.height * UP self.play( previous_row.shift, v, - #self.decimals.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.tallies.shift, v, ) + self.add_foreground_mobject(self.tallies) self.play( SplitRectsInBrickWall(self.row) ) self.wait() - self.merge_rects_by_subdiv() + self.row = self.merge_rects_by_subdiv(self.row) self.wait() @@ -754,7 +769,10 @@ class BrickRowScene(PiCreatureScene): k = 1 # tally to split # 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() index = 0 for i in range(n + 1): @@ -779,7 +797,10 @@ class BrickRowScene(PiCreatureScene): #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() index = 0 old_tally_sizes = [choose(n,i) for i in range(n + 1)] @@ -813,6 +834,13 @@ class BrickRowScene(PiCreatureScene): 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 anims = [] for i in range(n + 1): @@ -820,6 +848,11 @@ class BrickRowScene(PiCreatureScene): anims.append(FadeOut(grouped_outcomes_copy[i])) if i != k: 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) @@ -828,64 +861,69 @@ class BrickRowScene(PiCreatureScene): self.play( Transform(grouped_outcomes_copy[k - 1], original_grouped_outcomes[k - 1]) ) + self.play( Transform(grouped_outcomes[k], original_grouped_outcomes[k]) ) - new_rects = self.row.get_rects_for_level(n + 1) - #decimals_copy = self.decimals.copy() - #decimals_copy2 = self.decimals.copy() - self.play( 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]]), - #decimals_copy[k - 1].move_to, new_rects[k], - #decimals_copy2[k].move_to, new_rects[k], + Transform(grouped_outcomes_copy[k - 1][0],grouped_target_outcomes[k][0][:old_tally_sizes[k - 1]]), + ) + + 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, - # grouped_target_outcomes, - # target_outcomes, - # outcomes, - # previous_row, - # original_grouped_outcomes) + + # # # # # # # # # # + # EVEN MORE FLIPS # + # # # # # # # # # # + + self.play(FadeOut(new_tallies)) self.clear() - self.add(randy, self.row) - #self.row.shift(0.5 * UP) + self.add(randy, self.row) - #return - self.merge_rects_by_coloring() - - self.revert_to_original_skipping_status() - - for i in range(1): + for i in range(3): self.play(FlipCoin(randy)) self.wait() + previous_row = self.row.copy() + + self.play(previous_row.shift, 1.25 * self.row.height * UP) + self.play( SplitRectsInBrickWall(self.row) ) self.wait() - - - #self.split_tallies_at_once(direction = LEFT) + self.row = self.merge_rects_by_subdiv(self.row) self.wait() - self.merge_rects_by_subdiv() - self.wait() - #self.merge_tallies(direction = LEFT) - self.merge_rects_by_coloring() - #self.merge_decimals() + self.row = self.merge_rects_by_coloring(self.row) self.wait() + self.play(FadeOut(previous_row)) + + + + + + + + + + diff --git a/active_projects/eop/chapter1/entire_brick_wall.py b/active_projects/eop/chapter1/entire_brick_wall.py index 31d07ec1..90c52e29 100644 --- a/active_projects/eop/chapter1/entire_brick_wall.py +++ b/active_projects/eop/chapter1/entire_brick_wall.py @@ -1,29 +1,31 @@ from big_ol_pile_of_manim_imports import * from active_projects.eop.reusable_imports import * +from active_projects.eop.chapter1.brick_row_scene import BrickRowScene - -class EntireBrickWall(Scene): +class EntireBrickWall(BrickRowScene): def construct(self): + self.remove(self.get_primary_pi_creature()) + row_height = 0.3 nb_rows = 20 start_point = 3 * UP + 1 * LEFT rows = VMobject() rows.add(BrickRow(0, height = row_height)) - rows[0].move_to(start_point) + rows.move_to(start_point) self.add(rows) - + zero_counter = Integer(0).next_to(start_point + 0.5 * rows[0].width * RIGHT) nb_flips_text = TextMobject("\# of flips") nb_flips_text.next_to(zero_counter, RIGHT, buff = LARGE_BUFF) self.add(zero_counter, nb_flips_text) + flip_counters = VGroup(zero_counter) - for i in range(1,nb_rows + 1): - rows.add(BrickRow(i, height = row_height)) - rows[-1].move_to(start_point + (i - 1) * row_height * DOWN) + for i in range(1, nb_rows + 1): + rows.add(rows[-1].copy()) self.bring_to_back(rows[-1]) anims = [ rows[-1].shift, row_height * DOWN, @@ -33,10 +35,17 @@ class EntireBrickWall(Scene): if i % 5 == 0: counter = Integer(i) counter.next_to(rows[-1].get_right() + row_height * DOWN, RIGHT) + flip_counters.add(counter) anims.append(FadeIn(counter)) 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 tails_counters = VGroup() for (i, rect) in enumerate(rows[-1].rects): @@ -62,10 +71,73 @@ class EntireBrickWall(Scene): 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( 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]), ) + + + + + + + + + + + + + + + + + + + + diff --git a/active_projects/eop/chapter1/morph_brick_row_into_histogram.py b/active_projects/eop/chapter1/morph_brick_row_into_histogram.py index 7294e9e8..be3f744e 100644 --- a/active_projects/eop/chapter1/morph_brick_row_into_histogram.py +++ b/active_projects/eop/chapter1/morph_brick_row_into_histogram.py @@ -9,6 +9,7 @@ class GenericMorphBrickRowIntoHistogram(Scene): "bar_width" : 2.0, "bar_anchor_height" : -3.0, "show_tallies" : False, + "show_nb_flips" : True } def construct(self): @@ -25,13 +26,23 @@ class GenericMorphBrickRowIntoHistogram(Scene): for (i,brick) in enumerate(self.row.rects): tally = TallyStack(self.level - i, i) - tally.next_to(brick, UP) + tally.move_to(brick) self.add(tally) tallies.add(tally) 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) + 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 = [] for brick in self.row.rects: anims.append(brick.rotate) @@ -41,7 +52,7 @@ class GenericMorphBrickRowIntoHistogram(Scene): anims.append(FadeOut(tallies)) self.play(*anims) - + anims = [] for (i,brick) in enumerate(self.row.rects): anims.append(brick.next_to) @@ -50,11 +61,10 @@ class GenericMorphBrickRowIntoHistogram(Scene): self.play(*anims) self.bars.create_outline() - - anims = [] - for bar in self.bars.submobjects: - anims.append(bar.set_stroke) - anims.append({"width" : 0}) + anims = [ + ApplyMethod(rect.set_stroke, {"width" : 0}) + for rect in self.bars + ] anims.append(FadeIn(self.bars.outline)) self.play(*anims) @@ -67,7 +77,8 @@ class MorphBrickRowIntoHistogram3(GenericMorphBrickRowIntoHistogram): "prob_denominator" : 8, "bar_width" : 2.0, "bar_anchor_height" : -3.0, - "show_tallies" : True + "show_tallies" : True, + "show_nb_flips" : False } def construct(self): @@ -89,56 +100,72 @@ class MorphBrickRowIntoHistogram3(GenericMorphBrickRowIntoHistogram): nb_tails_label = TextMobject("\# of tails") nb_tails_label.next_to(x_labels[-1], RIGHT, MED_LARGE_BUFF) - - self.play( - FadeIn(x_axis), - FadeIn(x_labels), - FadeIn(nb_tails_label) - ) # draw y-guides y_guides = VMobject() - for i in range(1,self.prob_denominator + 1): + 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) - y_guide.add(y_guide_label) + if i != 0: + y_guide.add(y_guide_label) y_guides.add(y_guide) - self.bring_to_back(y_guides) - self.play(FadeIn(y_guides), Animation(self.bars)) - - - total_area_text = TextMobject("total area = 1", color = YELLOW) - total_area_rect = SurroundingRectangle(total_area_text, - buff = MED_SMALL_BUFF, - fill_opacity = 0.5, - fill_color = BLACK, - stroke_color = YELLOW + self.play( + FadeIn(y_guides), + Animation(self.bars.outline), + Animation(self.bars) ) self.play( - Write(total_area_text), + FadeIn(x_axis), + FadeIn(x_labels), + 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) + + total_area_group = VGroup(total_area_text, area_decimal) + total_area_group.move_to(2.7 * UP) + + self.play( + FadeIn(total_area_text), + ) + + cumulative_areas = [0.125, 0.5, 0.875, 1] + 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_rect = SurroundingRectangle( + total_area_group, + buff = MED_SMALL_BUFF, + stroke_color = area_color + ) + + self.play( + FadeOut(covering_rects), 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): @@ -165,9 +192,9 @@ class MorphBrickRowIntoHistogram20(GenericMorphBrickRowIntoHistogram): label.next_to(self.bar_anchors[i], DOWN) x_labels.add(label) - nb_tails_label = TextMobject("\# of heads") - nb_tails_label.next_to(x_labels[-1], RIGHT, MED_LARGE_BUFF) - + nb_tails_label = TextMobject("\# of tails") + nb_tails_label.move_to(5 * RIGHT + 2.5 * DOWN) + self.play( FadeIn(x_axis), FadeIn(x_labels), @@ -186,7 +213,7 @@ class MorphBrickRowIntoHistogram20(GenericMorphBrickRowIntoHistogram): y_guide_height = self.bar_anchor_height + i * float(self.row.width) y_guide_heights.append(y_guide_height) 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.next_to(y_guide, LEFT) y_guide.add(y_guide_label) @@ -199,7 +226,7 @@ class MorphBrickRowIntoHistogram20(GenericMorphBrickRowIntoHistogram): histogram_height = self.bars.get_height() # 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 diff --git a/active_projects/eop/chapter1/prob_dist_visuals.py b/active_projects/eop/chapter1/prob_dist_visuals.py index 6bd2dbae..1292d7b4 100644 --- a/active_projects/eop/chapter1/prob_dist_visuals.py +++ b/active_projects/eop/chapter1/prob_dist_visuals.py @@ -14,15 +14,25 @@ class ProbabilityDistributions(PiCreatureScene): def construct(self): 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 unit_rect = Rectangle( - height = 4, width = 4 - ) + height = 3, width = 3 + ).shift(DOWN) p_rain = 0.23 p_sun = 1 - p_rain @@ -38,7 +48,7 @@ class ProbabilityDistributions(PiCreatureScene): sun_rect.set_fill(color = YELLOW, opacity = opacity) 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) sun = SVGMobject(file_name = "sun").scale(0.35) @@ -189,7 +199,8 @@ class ProbabilityDistributions(PiCreatureScene): coin_flip_rect.add(braces, labels) 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( MoveToTarget(coin_flip_rect) @@ -255,25 +266,3 @@ class ProbabilityDistributions(PiCreatureScene): rate_func=there_and_back_with_pause, run_time=run_time ) - - - - - - - - - - - - - - - - - - - - - - diff --git a/active_projects/eop/chapter1/quiz_result.py b/active_projects/eop/chapter1/quiz_result.py index f03700c1..3488efea 100644 --- a/active_projects/eop/chapter1/quiz_result.py +++ b/active_projects/eop/chapter1/quiz_result.py @@ -1,12 +1,14 @@ - - from big_ol_pile_of_manim_imports import * from active_projects.eop.reusable_imports 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): @@ -23,14 +25,15 @@ class QuizResult(Scene): return quiz - highlight_color = YELLOW + highlight_color = WHITE nb_students_x = 5 nb_students_y = 3 spacing_students_x = 2.0 spacing_students_y = 2.2 - all_students = VGroup() + all_students = PiCreatureClass( + width = nb_students_x, height = nb_students_y)# VGroup() student_points = [] grades = [] grades_count = [] @@ -39,9 +42,10 @@ class QuizResult(Scene): for j in range(nb_students_y): x = i * spacing_students_x y = j * spacing_students_y - pi = PiCreature().scale(0.3) - pi.move_to([x,y,0]) - all_students.add(pi) + #pi = PiCreature().scale(0.3) + #pi.move_to([x,y,0]) + #all_students.add(pi) + all_students[i*nb_students_y + j].move_to([x,y,0]) q1 = np.random.choice([True, False]) q2 = np.random.choice([True, False]) q3 = np.random.choice([True, False]) @@ -55,7 +59,8 @@ class QuizResult(Scene): all_students.move_to(ORIGIN) - self.add(all_students) + self.pi_creatures = all_students + self.play(FadeIn(all_students)) all_quizzes = VGroup() @@ -133,17 +138,20 @@ class QuizResult(Scene): ) 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.move_to(3 * LEFT + 2 * UP) + nb_students_label.move_to(5 * LEFT + 2 * UP) 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) 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.move_to(nb_students_label) @@ -151,10 +159,11 @@ class QuizResult(Scene): anims = [] for (label, percentage) in zip(grade_hist.y_labels_group, percentages): new_label = DecimalNumber(percentage, - num_decimal_points = 1, + num_decimal_places = 1, unit = "\%", color = highlight_color ) + new_label.scale(0.7) new_label.move_to(label) anims.append(Transform(label, new_label)) anims.append(ReplacementTransform(nb_students_label, percentage_label)) @@ -174,8 +183,8 @@ class QuizResult(Scene): prob_label.move_to(percentage_label) self.play( all_students[8].set_color, MAROON_E, - all_students[:8].fade, 0.6, - all_students[9:].fade, 0.6, + #all_students[:8].fade, 0.6, + #all_students[9:].fade, 0.6, ReplacementTransform(percentage_label, prob_label) ) @@ -184,12 +193,32 @@ class QuizResult(Scene): FadeOut(arrows) ) - for i in range(1): - self.play( - FlashThroughHistogram( + flash_hist = FlashThroughHistogram( grade_hist, direction = "vertical", 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) + + + + + + + + + diff --git a/active_projects/eop/reusables/brick_row.py b/active_projects/eop/reusables/brick_row.py index e07bcd88..92ca15f7 100644 --- a/active_projects/eop/reusables/brick_row.py +++ b/active_projects/eop/reusables/brick_row.py @@ -11,7 +11,7 @@ class BrickRow(VMobject): "height" : 1.0, "width" : 8.0, "outcome_shrinkage_factor_x" : 0.95, - "outcome_shrinkage_factor_y" : 0.95 + "outcome_shrinkage_factor_y" : 0.94 } def __init__(self, n, **kwargs): @@ -104,12 +104,12 @@ class BrickRow(VMobject): outcome_width = float(self.width) / (2 ** r) 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 - rect = Rectangle( # RoundedRectangle( + rect = RoundedRectangle( width = outcome_width, height = outcome_height, - #corner_radius = corner_radius, + corner_radius = corner_radius, fill_color = WHITE, fill_opacity = 0.2, 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) - diff --git a/active_projects/eop/reusables/histograms.py b/active_projects/eop/reusables/histograms.py index dc1e1b2c..91c12e86 100644 --- a/active_projects/eop/reusables/histograms.py +++ b/active_projects/eop/reusables/histograms.py @@ -201,7 +201,10 @@ class FlashThroughHistogram(Animation): "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) @@ -277,6 +280,15 @@ class FlashThroughHistogram(Animation): 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. CONFIG = { - "outline_stroke_width" : 5, + "outline_stroke_width" : 3, "stroke_color" : WHITE } def create_outline(self, animated = False, **kwargs): diff --git a/active_projects/eop/reusables/upright_coins.py b/active_projects/eop/reusables/upright_coins.py index 849180b2..1f5456b7 100644 --- a/active_projects/eop/reusables/upright_coins.py +++ b/active_projects/eop/reusables/upright_coins.py @@ -37,6 +37,7 @@ class UprightTails(UprightCoin): class CoinSequence(VGroup): CONFIG = { "sequence": [], + "radius" : COIN_RADIUS, "spacing": COIN_SEQUENCE_SPACING, "direction": RIGHT } @@ -47,11 +48,11 @@ class CoinSequence(VGroup): offset = 0 for symbol in self.sequence: if symbol == "H": - new_coin = UprightHeads() + new_coin = UprightHeads(radius = self.radius) elif symbol == "T": - new_coin = UprightTails() + new_coin = UprightTails(radius = self.radius) else: - new_coin = UprightCoin(symbol = symbol) + new_coin = UprightCoin(symbol = symbol, radius = self.radius) new_coin.shift(offset * self.direction) self.add(new_coin) offset += self.spacing diff --git a/animation/numbers.py b/animation/numbers.py index f7b8d250..428203f3 100644 --- a/animation/numbers.py +++ b/animation/numbers.py @@ -10,7 +10,7 @@ from utils.config_ops import digest_config class ChangingDecimal(Animation): CONFIG = { - "num_decimal_points": None, + "num_decimal_places": None, "show_ellipsis": None, "position_update_func": None, "tracked_mobject": None, @@ -21,7 +21,7 @@ class ChangingDecimal(Animation): self.decimal_number_config = dict( 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) if value is not None: self.decimal_number_config[attr] = value diff --git a/extract_scene.py b/extract_scene.py index ae52be31..f7c91f94 100644 --- a/extract_scene.py +++ b/extract_scene.py @@ -151,11 +151,12 @@ def handle_scene(scene, **config): if config["show_file_in_finder"]: commands.append("-R") - # + if config["show_last_frame"]: commands.append(scene.get_image_file_path()) else: commands.append(scene.get_movie_file_path()) + #commands.append("-g") FNULL = open(os.devnull, 'w') sp.call(commands, stdout=FNULL, stderr=sp.STDOUT) FNULL.close() @@ -223,8 +224,11 @@ def get_module_posix(file_name): module_name = file_name.replace(".py", "") last_module = imp.load_module(".", *imp.find_module(".")) for part in module_name.split(os.sep): - load_args = imp.find_module(part, last_module.__path__) - last_module = imp.load_module(part, *load_args) + try: + load_args = imp.find_module(part, last_module.__path__) + last_module = imp.load_module(part, *load_args) + except ImportError: + continue return last_module diff --git a/for_3b1b_videos/pi_class.py b/for_3b1b_videos/pi_class.py new file mode 100644 index 00000000..2c0479d7 --- /dev/null +++ b/for_3b1b_videos/pi_class.py @@ -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) + + diff --git a/for_3b1b_videos/pi_creature_animations.py b/for_3b1b_videos/pi_creature_animations.py index 352ae5ce..96721b7f 100644 --- a/for_3b1b_videos/pi_creature_animations.py +++ b/for_3b1b_videos/pi_creature_animations.py @@ -6,6 +6,7 @@ from mobject.mobject import Group from mobject.svg.drawings import SpeechBubble +from animation.animation import Animation from animation.creation import ShowCreation from animation.creation import Write 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 there_and_back +from for_3b1b_videos.pi_class import PiCreatureClass + class Blink(ApplyMethod): CONFIG = { @@ -101,3 +104,46 @@ class RemovePiCreatureBubble(AnimationGroup): self.pi_creature.bubble = None if surrounding_scene is not None: 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) + + + + + + + + + + + + + + + diff --git a/mobject/matrix.py b/mobject/matrix.py index 727f8f4d..cb8e1af2 100644 --- a/mobject/matrix.py +++ b/mobject/matrix.py @@ -139,7 +139,7 @@ class Matrix(VMobject): class DecimalMatrix(Matrix): CONFIG = { "element_to_mobject": DecimalNumber, - "element_to_mobject_config": {"num_decimal_points": 1} + "element_to_mobject_config": {"num_decimal_places": 1} } diff --git a/mobject/mobject.py b/mobject/mobject.py index 4c5721f9..56c87c51 100644 --- a/mobject/mobject.py +++ b/mobject/mobject.py @@ -623,13 +623,17 @@ class Mobject(Container): values = [] values += [ mob.reduce_across_dimension(points_func, reduce_func, dim) - for mob in self.submobjects + for mob in self.nonempty_submobjects() ] try: return reduce_func(values) except: 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): result = None for mob in self.family_members_with_points(): @@ -745,6 +749,7 @@ class Mobject(Container): def submobject_family(self): sub_families = map(Mobject.submobject_family, self.submobjects) all_mobjects = [self] + list(it.chain(*sub_families)) + #all_mobjects = list(it.chain(*sub_families)) + [self] return remove_list_redundancies(all_mobjects) def family_members_with_points(self): diff --git a/mobject/numbers.py b/mobject/numbers.py index 5a6ff682..e4986813 100644 --- a/mobject/numbers.py +++ b/mobject/numbers.py @@ -8,7 +8,7 @@ from mobject.types.vectorized_mobject import VMobject class DecimalNumber(VMobject): CONFIG = { - "num_decimal_points": 2, + "num_decimal_places": 2, "digit_to_digit_buff": 0.05, "show_ellipsis": False, "unit": None, # Aligned to bottom unless it starts with "^" @@ -18,7 +18,7 @@ class DecimalNumber(VMobject): def __init__(self, number, **kwargs): VMobject.__init__(self, **kwargs) self.number = number - ndp = self.num_decimal_points + ndp = self.num_decimal_places # Build number string if isinstance(number, complex): @@ -71,5 +71,5 @@ class DecimalNumber(VMobject): class Integer(DecimalNumber): CONFIG = { - "num_decimal_points": 0, + "num_decimal_places": 0, } diff --git a/mobject/svg/tex_mobject.py b/mobject/svg/tex_mobject.py index 642d1a61..c7bcc78b 100644 --- a/mobject/svg/tex_mobject.py +++ b/mobject/svg/tex_mobject.py @@ -5,6 +5,7 @@ from svg_mobject import VMobjectFromSVGPathstring from utils.config_ops import digest_config from utils.strings import split_string_list_to_isolate_substring 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 VectorizedPoint @@ -290,3 +291,27 @@ class TexMobjectFromPresetString(TexMobject): TexMobject.__init__(self, self.tex, **kwargs) 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 diff --git a/old_projects/WindingNumber.py b/old_projects/WindingNumber.py index c2d20fef..c12c5cbd 100644 --- a/old_projects/WindingNumber.py +++ b/old_projects/WindingNumber.py @@ -565,7 +565,7 @@ def walker_animation_with_display( number_update_func = None, show_arrows = True, scale_arrows = False, - num_decimal_points = 1, + num_decimal_places = 1, include_background_rectangle = True, **kwargs ): @@ -581,7 +581,7 @@ def walker_animation_with_display( if number_update_func != None: display = DecimalNumber(0, - num_decimal_points = num_decimal_points, + num_decimal_places = num_decimal_places, fill_color = WHITE if include_background_rectangle else BLACK, include_background_rectangle = include_background_rectangle) if include_background_rectangle: @@ -732,7 +732,7 @@ class PiWalker(ColorMappedByFuncScene): "show_num_plane" : False, "draw_lines" : True, "num_checkpoints" : 10, - "num_decimal_points" : 1, + "num_decimal_places" : 1, "include_background_rectangle" : False, } @@ -788,7 +788,7 @@ class PiWalker(ColorMappedByFuncScene): number_update_func = number_update_func, run_time = self.step_run_time, 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, ) @@ -2751,7 +2751,7 @@ class OneFifthTwoFifthWinder(SpecifiedWinder): "step_size" : 0.01, "show_num_plane" : False, "step_run_time" : 6, - "num_decimal_points" : 2, + "num_decimal_places" : 2, } class OneFifthOneFifthWinderWithReset(OneFifthTwoFifthWinder): diff --git a/old_projects/WindingNumber_G.py b/old_projects/WindingNumber_G.py index 501fc289..4b65bb31 100644 --- a/old_projects/WindingNumber_G.py +++ b/old_projects/WindingNumber_G.py @@ -386,7 +386,7 @@ class Introduce1DFunctionCase(Scene): ) decimal = DecimalNumber( 0, - num_decimal_points = 3, + num_decimal_places = 3, show_ellipsis = True, ) decimal.scale(0.7) @@ -484,7 +484,7 @@ class Introduce1DFunctionCase(Scene): if show_decimal: decimal = DecimalNumber( axes.x_axis.point_to_number(arrow.get_start()), - num_decimal_points = 3, + num_decimal_places = 3, # show_ellipsis = True, ) 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, get_total_winding, position_update_func = lambda l : l.next_to(dot, UP+LEFT, SMALL_BUFF) diff --git a/old_projects/basel/basel.py b/old_projects/basel/basel.py index 259c537c..69809107 100644 --- a/old_projects/basel/basel.py +++ b/old_projects/basel/basel.py @@ -119,7 +119,7 @@ class LightIndicator(VMobject): self.foreground.set_stroke(color=INDICATOR_STROKE_COLOR,width=INDICATOR_STROKE_WIDTH) 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.move_to(self.get_center()) if self.show_reading: @@ -287,7 +287,7 @@ class IntroScene(PiCreatureScene): equals_sign = self.euler_sum.get_part_by_tex("=") 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) @@ -313,7 +313,7 @@ class IntroScene(PiCreatureScene): self.partial_sum_decimal, partial_results_values[i+1], run_time = self.duration, - num_decimal_points = 6, + num_decimal_places = 6, show_ellipsis = True, position_update_func = lambda m: m.next_to(equals_sign, RIGHT) ) @@ -863,7 +863,7 @@ class SingleLighthouseScene(PiCreatureScene): # angle msmt (decimal number) self.angle_indicator = DecimalNumber(arc_angle / DEGREES, - num_decimal_points = 0, + num_decimal_places = 0, unit = "^\\circ", fill_opacity = 1.0, fill_color = WHITE) @@ -4262,7 +4262,7 @@ class LabeledArc(Arc): 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 theta = self.start_angle + self.angle/2 label_pos = r * np.array([np.cos(theta), np.sin(theta), 0]) diff --git a/old_projects/basel/basel2.py b/old_projects/basel/basel2.py index 1638a26f..bdd41ccc 100644 --- a/old_projects/basel/basel2.py +++ b/old_projects/basel/basel2.py @@ -94,7 +94,7 @@ class LightIndicator(Mobject): self.foreground.set_fill(color = self.fill_color) 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.scale_to_fit_height(self.reading_height) self.reading.move_to(self.get_center()) @@ -317,7 +317,7 @@ class IntroScene(PiCreatureScene): partial_sum_decimal = self.partial_sum_decimal = DecimalNumber( series_terms[1], - num_decimal_points = 2 + num_decimal_places = 2 ) partial_sum_decimal.next_to(equals_sign, RIGHT) @@ -418,7 +418,7 @@ class IntroScene(PiCreatureScene): partial_sum_decimal, series_terms[i+1], run_time = 1, - num_decimal_points = 6, + num_decimal_places = 6, position_update_func = lambda m: m.next_to(equals_sign, RIGHT) ) ] @@ -430,7 +430,7 @@ class IntroScene(PiCreatureScene): ChangeDecimalToValue( partial_sum_decimal, series_terms[i+1], - num_decimal_points = 6, + num_decimal_places = 6, ), ] if i == 5: @@ -451,7 +451,7 @@ class IntroScene(PiCreatureScene): ChangeDecimalToValue( partial_sum_decimal, series_terms[-1], - num_decimal_points = 6, + num_decimal_places = 6, ), morty.change, "confused", ) @@ -1295,7 +1295,7 @@ class IntroduceScreen(Scene): self.angle_indicator = DecimalNumber( arc_angle / DEGREES, - num_decimal_points = 0, + num_decimal_places = 0, unit = "^\\circ" ) 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)) # Decimal - decimal = DecimalNumber(0, num_decimal_points = 6) + decimal = DecimalNumber(0, num_decimal_places = 6) decimal.to_edge(UP) terms = [2./(n**2) for n in range(1, 100, 2)] partial_sums = np.cumsum(terms) @@ -4250,7 +4250,7 @@ class LabeledArc(Arc): 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 theta = self.start_angle + self.angle/2 label_pos = r * np.array([np.cos(theta), np.sin(theta), 0]) diff --git a/old_projects/fourier.py b/old_projects/fourier.py index 830f8c78..33d624e5 100644 --- a/old_projects/fourier.py +++ b/old_projects/fourier.py @@ -728,7 +728,7 @@ class UnmixMixedPaint(Scene): class MachineThatTreatsOneFrequencyDifferently(Scene): def construct(self): 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) self.graph = graph @@ -1273,7 +1273,7 @@ class WrapCosineGraphAroundCircle(FourierMachineScene): def get_winding_frequency_label(self): freq = self.initial_winding_frequency winding_freq_label = VGroup( - DecimalNumber(freq, num_decimal_points = 2), + DecimalNumber(freq, num_decimal_places = 2), TextMobject("cycles/second") ) winding_freq_label.arrange_submobjects(RIGHT) diff --git a/old_projects/fractal_dimension.py b/old_projects/fractal_dimension.py index 27a05397..683f3154 100644 --- a/old_projects/fractal_dimension.py +++ b/old_projects/fractal_dimension.py @@ -1805,7 +1805,7 @@ class BoxCountingScene(Scene): return label 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.add_to_back(BackgroundRectangle(num)) diff --git a/old_projects/nn/part1.py b/old_projects/nn/part1.py index b2d872fc..cdd3618d 100644 --- a/old_projects/nn/part1.py +++ b/old_projects/nn/part1.py @@ -559,7 +559,7 @@ class WriteAProgram(Scene): rgb = square.fill_rgb num = DecimalNumber( square.fill_rgb[0], - num_decimal_points = 1 + num_decimal_places = 1 ) num.set_stroke(width = 1) color = rgba_to_color(1 - (rgb + 0.2)/1.2) @@ -1113,7 +1113,7 @@ class IntroduceEachLayer(PreviewMNistNetwork): example_num = None for neuron in neurons: 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.move_to(neuron) if o > 0.8: diff --git a/old_projects/nn/part2.py b/old_projects/nn/part2.py index 114ddff9..f32e805b 100644 --- a/old_projects/nn/part2.py +++ b/old_projects/nn/part2.py @@ -962,14 +962,14 @@ class IntroduceCostFunction(PreviewLearning): terms = VGroup() term_updates = [] 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.next_to(arrow, LEFT) term.num_update_func = generate_term_update_func(d1, d2) terms.add(term) term_updates.append(ChangingDecimalWithColor( term, term.num_update_func, - num_decimal_points = 4 + num_decimal_places = 4 )) brace.target.next_to(terms, LEFT) @@ -2780,7 +2780,7 @@ class TestPerformance(PreviewLearning): "wrong_wait_time" : 0.5, "stroke_width_exp" : 2, "decimal_kwargs" : { - "num_decimal_points" : 3, + "num_decimal_places" : 3, } } def construct(self): diff --git a/old_projects/nn/part3.py b/old_projects/nn/part3.py index 5b14b69b..ade62581 100644 --- a/old_projects/nn/part3.py +++ b/old_projects/nn/part3.py @@ -671,7 +671,7 @@ class WalkThroughTwoExample(ShowAveragingCost): decimals = VGroup() for neuron in neurons: 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.move_to(neuron) if activation > 0.8: @@ -748,7 +748,7 @@ class WalkThroughTwoExample(ShowAveragingCost): anims.append(ChangingDecimal( decimal, get_decimal_update(decimal.number, target), - num_decimal_points = 1 + num_decimal_places = 1 )) anims.append(UpdateFromFunc( self.decimals[i], @@ -1076,7 +1076,7 @@ class WalkThroughTwoExample(ShowAveragingCost): ChangingDecimal( two_decimal, lambda a : interpolate(two_activation, 1, a), - num_decimal_points = 1, + num_decimal_places = 1, ), UpdateFromFunc( two_decimal, @@ -1110,7 +1110,7 @@ class WalkThroughTwoExample(ShowAveragingCost): ChangingDecimal( two_decimal, lambda a : interpolate(1, two_activation, a), - num_decimal_points = 1, + num_decimal_places = 1, ), UpdateFromFunc( two_decimal, @@ -3613,7 +3613,7 @@ class SimplestNetworkExample(PreviewLearning): def get_neuron_activation_decimal(self, neuron): 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()) if decimal.number > 0.8: decimal.set_fill(BLACK) diff --git a/old_projects/pi_day.py b/old_projects/pi_day.py index ce4c2e36..bea9b697 100644 --- a/old_projects/pi_day.py +++ b/old_projects/pi_day.py @@ -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) ), ) - decimal = DecimalNumber(0, num_decimal_points = 4, show_ellipsis = True) + decimal = DecimalNumber(0, num_decimal_places = 4, show_ellipsis = True) decimal.scale(0.75) def reposition_decimal(decimal): vect = radius.get_vector() @@ -318,7 +318,7 @@ class PiTauDebate(PiCreatureScene): circum_line.next_to(circle, DOWN, buff = MED_LARGE_BUFF) # circum_line.to_edge(LEFT) 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.next_to(brace, DOWN, SMALL_BUFF) diff --git a/old_projects/wallis.py b/old_projects/wallis.py index b2ffb1ed..707d7d94 100644 --- a/old_projects/wallis.py +++ b/old_projects/wallis.py @@ -112,7 +112,7 @@ class Introduction(Scene): ) get_arrow_update().update(1) 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_anim = ChangingDecimal( decimal, @@ -512,7 +512,7 @@ class ShowProduct(Scene): ]) 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) self.add(brace, decimal, dots[0], parts[0]) @@ -677,7 +677,7 @@ class ShowProduct(Scene): ]) 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) self.play(*map(FadeIn, [brace, decimal, dots[0]])) @@ -894,7 +894,7 @@ class DistanceProductScene(MovingCameraScene): self.d_labels.add(d_label) 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 if lines is None: if not hasattr(self, "distance_lines"): @@ -904,7 +904,7 @@ class DistanceProductScene(MovingCameraScene): for line in lines: label = DecimalNumber( line.get_length() / radius, - num_decimal_points=num_decimal_points, + num_decimal_places=num_decimal_places, show_ellipsis=show_ellipsis, include_background_rectangle=self.include_distance_labels_background_rectangle, ) @@ -943,7 +943,7 @@ class DistanceProductScene(MovingCameraScene): product_decimal = DecimalNumber( self.get_distance_product(fraction), - num_decimal_points=3, + num_decimal_places=3, show_ellipsis=True, 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()) complex_decimal = self.complex_decimal = DecimalNumber( values[3], - num_decimal_points=3, + num_decimal_places=3, include_background_rectangle=True ) complex_decimal.next_to(outer_arrow.get_start(), LEFT, SMALL_BUFF) @@ -2190,7 +2190,7 @@ class PlugObserverIntoPolynomial(DistanceProductScene): numeric_chord_label = DecimalNumber( np.sqrt(3), - num_decimal_points=4, + num_decimal_places=4, include_background_rectangle=True, show_ellipsis=True, ) @@ -2907,7 +2907,7 @@ class ProveLemma2(PlugObserverIntoPolynomial): product = DecimalNumber( self.num_lighthouses, - num_decimal_points=3, + num_decimal_places=3, show_ellipsis=True ) product.move_to(self.q_marks, LEFT) @@ -3235,7 +3235,7 @@ class KeeperAndSailor(DistanceProductScene, PiCreatureScene): new_keeper_dp_decimal = DecimalNumber( 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.set_color(YELLOW) diff --git a/utils/rate_functions.py b/utils/rate_functions.py index 5587cb51..f9ebb142 100644 --- a/utils/rate_functions.py +++ b/utils/rate_functions.py @@ -4,6 +4,9 @@ from utils.bezier import bezier from utils.simple_functions import sigmoid +def linear(t): + return t + def smooth(t, inflection=10.0): error = sigmoid(-inflection / 2) return (sigmoid(inflection * (t - 0.5)) - error) / (1 - 2 * error) diff --git a/utils/tex_file_writing.py b/utils/tex_file_writing.py deleted file mode 100644 index 892b6fbe..00000000 --- a/utils/tex_file_writing.py +++ /dev/null @@ -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