from manim_imports_ext import * class PhotographVsHologram(InteractiveScene): def construct(self): # Test title = Text("Single piece of film") title.to_edge(UP, buff=MED_SMALL_BUFF) photo = VGroup( Text("Photograph"), Text("One point of view"), ) holo = VGroup( Text("Our Recording"), Text("Many points of view"), ) for part, x in zip([photo, holo], [-1, 1]): part[1].scale(0.7) part[1].set_color(GREY_A) part.arrange(DOWN) part.set_x(x * FRAME_WIDTH / 4) part.set_y(2) part.add_to_back(Arrow(title.get_edge_center(x * RIGHT), part.get_top(), path_arc=-x * 60 * DEGREES)) self.add(title) for part in [photo, holo]: self.play( GrowArrow(part[0]), FadeInFromPoint(part[1], part[0].get_start()), ) self.wait() self.play(Write(part[2])) self.wait() class GlintArrow(InteractiveScene): def construct(self): # Test circle = Circle(radius=0.25) circle.set_stroke(RED, 4) circle.insert_n_curves(20) arrow = Vector(DR, thickness=5, fill_color=RED) arrow.next_to(circle, UL, buff=0) self.play( GrowArrow(arrow), VShowPassingFlash(circle, time_width=1.5, time_span=(0.5, 1.5)), ) self.wait() class WriteHologram(InteractiveScene): def construct(self): # Test title = Text("Hologram", font_size=96) title.to_edge(UP) self.play(Write(title, stroke_color=GREEN_SCREEN, stroke_width=3, lag_ratio=0.1, run_time=3)) self.wait() class WriteTransmissionHologram(InteractiveScene): def construct(self): # Test title = Text("Transmission Hologram", font_size=96) title.to_edge(UP) self.play(Write(title, stroke_color=GREEN_SCREEN, stroke_width=3, lag_ratio=0.1, run_time=3)) self.wait() class WriteWhiteLightReflectionHologram(InteractiveScene): def construct(self): # Test title = Text("White Light Reflection Hologram", font_size=72) title.to_edge(UP) self.play(Write(title, stroke_color=WHITE, stroke_width=3, lag_ratio=0.1, run_time=3)) self.wait() class IndicationOnPhotograph(InteractiveScene): def construct(self): # Image image = ImageMobject("ContrastWithPhotography") image.set_height(FRAME_HEIGHT) # self.add(image) # Dots p0 = (-3.82, 2.11, 0.0) p1 = (-3.14, 2.17, 0.0) p2 = (2.61, 2.82, 0.0) p3 = (3.53, 2.24, 0.0) dot1 = GlowDot(p0, color=TEAL) dot2 = GlowDot(p2, color=TEAL) arrow = StrokeArrow(p0, p2, buff=SMALL_BUFF, path_arc=-30 * DEGREES) arrow.set_stroke(TEAL) self.play(FadeIn(dot1), FlashAround(dot1, stroke_width=5, time_width=2, color=TEAL)) self.play( TransformFromCopy(dot1, dot2, path_arc=-30 * DEGREES), ShowCreation(arrow, run_time=2), ) self.play( dot1.animate.move_to(p1), dot2.animate.move_to(p3), arrow.animate.match_points(StrokeArrow(p1, p3, buff=0.1, path_arc=-30 * DEGREES)), rate_func=there_and_back, run_time=3 ) self.play( FadeOut(dot1), FadeOut(dot2), FadeOut(arrow), ) class ContrastPhotographyAndHolography(InteractiveScene): def construct(self): # Test title = Text("Information lost in ordinary photography", font_size=60) title.to_edge(UP) underline = Underline(title, buff=-0.05) points = BulletedList( "All but one viewing angle", "Phase", buff=LARGE_BUFF ) points.scale(1.25) points.next_to(underline, DOWN, buff=1.5) points.shift(2 * LEFT) self.add(*(p[0] for p in points)) self.play( FadeIn(title), ShowCreation(underline) ) for point in points: self.wait() self.play(Write(point[1:])) self.play( FlashAround(points[1], color=TEAL, time_width=1.5, run_time=2), points[1].animate.set_color(TEAL) ) self.wait() class Outline(InteractiveScene): def construct(self): # Add top part frame = self.frame frame.set_y(2) background = FullScreenRectangle() background.fix_in_frame() self.add(background) top_outlines = ScreenRectangle().replicate(3) top_outlines.arrange(RIGHT, buff=1.5) top_outlines.set_width(13) top_outlines.set_stroke(WHITE, 2) top_outlines.set_fill(BLACK, 1) top_outlines.to_edge(UP, buff=LARGE_BUFF) top_images = Group( ImageMobject("HologramProcess.jpg"), ImageMobject("SimplestHologram.jpg"), ImageMobject("HologramEquation.png"), ) top_rects = Group( Group(outline, image.replace(outline)) for outline, image in zip(top_outlines, top_images) ) top_titles = VGroup( Text("The process"), Text("The simplest hologram"), Text("The general derivation"), ) top_titles.scale(0.75) for rect, title in zip(top_rects, top_titles): title.next_to(rect, UP, SMALL_BUFF) self.play( FadeIn(rect), FadeIn(title, 0.25 * UP) ) self.wait() # Highlight process self.play( FadeOut(top_rects[1:]), FadeOut(top_titles[1:]), frame.animate.set_height(4).move_to(top_rects[0]), run_time=2 ) self.wait() self.play( FadeIn(top_rects[1:]), FadeIn(top_titles[1:]), frame.animate.to_default_state().set_y(2), run_time=2 ) # Isolation animation def isolate(rects, titles, index, faded_opacity=0.15): return AnimationGroup( *( title.animate.set_opacity(1 if i == index else faded_opacity) for i, title in enumerate(titles) ), *( rect.animate.set_opacity(1 if i == index else faded_opacity) for i, rect in enumerate(rects) ), ) self.play(isolate(top_rects, top_titles, 0)) self.wait() self.play(isolate(top_rects, top_titles, 1)) self.wait() # Break down middle step mid_outlines = top_outlines.copy() mid_outlines.set_opacity(1) mid_outlines.next_to(top_rects, DOWN, buff=1.5) outer_lines = VGroup( CubicBezier( top_rects[1].get_corner(DL), top_rects[1].get_corner(DL) + DOWN, mid_outlines[0].get_corner(UL) + 2 * UP, mid_outlines[0].get_corner(UL), ), CubicBezier( top_rects[1].get_corner(DR), top_rects[1].get_corner(DR) + DOWN, mid_outlines[2].get_corner(UR) + 2 * UP, mid_outlines[2].get_corner(UR), ), ) mid_images = Group( ImageMobject("ZonePlateExposure"), ImageMobject("DotReconstruction"), ImageMobject("MultipleDotHologram"), ) mid_rects = Group( Group(outline, image.replace(outline)) for outline, image in zip(mid_outlines, mid_images) ) mid_titles = VGroup( Text("Exposure pattern"), Text("Reconstruction"), Text("Added complexity"), ) mid_titles.scale(0.75) for rect, title in zip(mid_rects, mid_titles): title.next_to(rect, UP, SMALL_BUFF) rect.save_state() rect.replace(top_rects[1]) rect.set_opacity(0) self.play( LaggedStartMap(Restore, mid_rects), ShowCreation(outer_lines, lag_ratio=0), frame.animate.set_y(0), FadeIn(mid_titles, time_span=(1.5, 2.0), lag_ratio=0.025), run_time=2 ) self.wait() for index in range(3): self.play(isolate(mid_rects, mid_titles, index)) self.wait() self.play(isolate(mid_rects, mid_titles, 0)) self.wait() # Minilesson low_outline = mid_outlines[1].copy() low_outline.next_to(mid_rects[1], DOWN, buff=1.5) low_image = ImageMobject("DiffractionGrating") low_image.replace(low_outline) low_rect = Group(low_outline, low_image) low_rect.shift(1.5 * LEFT) in_arrow = Arrow(mid_rects[0].get_bottom() + LEFT, low_rect.get_left(), path_arc=PI / 2, thickness=5, buff=0.15) up_arrow = Arrow(low_rect, mid_rects[1], thickness=5, buff=0.15) low_title = Text("Mini-lesson on\nDiffraction Gratings") low_title.next_to(low_rect, DOWN) self.play( frame.animate.set_y(-4), FadeIn(low_rect, DOWN), FadeIn(low_title, DOWN), GrowArrow(in_arrow), run_time=2 ) self.play(GrowArrow(up_arrow)) self.wait() # Zoom in on mini-lesson frame.save_state() self.play( frame.animate.set_height(4).move_to(Group(low_rect, low_title)), FadeOut(VGroup(in_arrow, up_arrow)), run_time=2, ) self.wait() self.play( Restore(frame), FadeIn(VGroup(in_arrow, up_arrow)), run_time=2 ) self.wait() # Back to the middle self.play( LaggedStartMap(FadeOut, Group(low_title, low_rect, arrow), lag_ratio=0.1, run_time=1), frame.animate.set_y(0).set_anim_args(run_time=2), ) self.wait() self.play(isolate(mid_rects, mid_titles, 2)) self.wait() # Back to the top self.play( LaggedStart( (mid_rect.animate.replace(top_rects[1]).set_opacity(0) for mid_rect in mid_rects), lag_ratio=0.05, group_type=Group ), FadeOut(mid_titles), Uncreate(outer_lines, lag_ratio=0), frame.animate.set_y(2), run_time=2 ) self.wait() self.play(isolate(top_rects, top_titles, 2)) self.wait() class GoalOfRediscovery(TeacherStudentsScene): def construct(self): # Test morty = self.teacher self.play( self.change_students("pondering", "confused", "maybe", look_at=self.screen), morty.change("guilty"), ) self.wait(2) self.play( morty.says("I want this to\nfeel rediscovered"), self.change_students("tease", "erm", "pondering", look_at=morty.eyes) ) self.wait(2) self.look_at(self.screen) self.play(self.change_students("thinking", "pondering", "thinking")) self.wait(4) class NameCraigAndSally(InteractiveScene): def construct(self): # Test image = ImageMobject("CraigSallyPaulGrant") image.set_height(FRAME_HEIGHT) craig_point = (1.2, 2.0, 0) sally_point = (3.9, 1.3, 0) craig_arrow = Vector(DR, thickness=5) craig_arrow.next_to(craig_point, UL) craig_name = Text("Craig Newswanger") craig_name.next_to(craig_arrow.get_start(), UP, buff=SMALL_BUFF) sally_arrow = Vector(DL, thickness=5) sally_arrow.next_to(sally_point, UR) sally_name = Text("Sally Weber") sally_name.next_to(sally_arrow.get_start(), UP, buff=SMALL_BUFF) VGroup(craig_arrow, craig_name, sally_arrow, sally_name).set_fill(WHITE).set_backstroke(BLACK, 5) self.play( GrowArrow(craig_arrow), FadeIn(craig_name), ) self.play( GrowArrow(sally_arrow), FadeIn(sally_name), ) class ShowALens(InteractiveScene): def construct(self): # Add lens arc = Arc(-30 * DEGREES, 60 * DEGREES) flipped = arc.copy().rotate(PI).next_to(arc, LEFT, buff=0) arc.append_vectorized_mobject(flipped) lens = arc lens.set_stroke(WHITE, 2) lens.set_fill(GREY_E, 1) lens.set_shading(0.1, 0.5, 0) lens.set_height(3) # Add lines n_lines = 20 points = np.linspace(lens.get_top(), lens.get_bottom(), n_lines) focal_point = lens.get_left() + 2 * LEFT in_lines = VGroup(Line(point + 8 * RIGHT, point) for point in points) out_lines = VGroup(Line(point, focal_point) for point in points) for in_line, out_line in zip(in_lines, out_lines): out_line.scale(1.25, about_point=out_line.get_start()) in_line.append_vectorized_mobject(out_line) in_lines.set_stroke(WHITE, 1) in_lines.insert_n_curves(100) self.add(in_lines, lens) self.play(ShowCreation(in_lines, lag_ratio=0.01, run_time=2, rate_func=linear)) self.wait() # Label viewing angle text = Text("Single viewing angle") text.next_to(lens.get_top(), UR) arrow = Vector(RIGHT).next_to(text, RIGHT) self.play(LaggedStart(Write(text, run_time=1), GrowArrow(arrow), lag_ratio=0.5)) self.wait() class AskAboutRecordingPhase(InteractiveScene): def construct(self): # Test morty = Mortimer() morty.to_corner(DR) randy = Randolph(height=2.5) randy.next_to(morty, LEFT, buff=1.5, aligned_edge=DOWN) for pi in [morty, randy]: pi.body.insert_n_curves(100) self.add(morty, randy) self.play( morty.says( Text(""" How could you detect this phase difference? """), look_at=randy.eyes, ), randy.change("pondering", morty.eyes) ) self.play(Blink(randy)) self.play( randy.animate.look_at(3 * UL), morty.change("tease", 3 * UL), ) self.play(randy.change("erm", 3 * UL)) self.play(Blink(morty)) self.play(Blink(randy)) self.wait(2) self.play(randy.change("confused", 3 * UL)) self.play(morty.change("pondering", 3 * UL)) self.play(Blink(randy)) self.wait(3) self.play(randy.change("thinking", 3 * LEFT)) self.play(Blink(randy)) self.play(Blink(morty)) self.wait(2) class HowIsThisHelpful(TeacherStudentsScene): def construct(self): # Test stds = self.students morty = self.teacher self.play(LaggedStart( stds[1].says("What does this have\nto do with recording 3d?", mode="maybe", look_at=self.screen), stds[0].change("confused", self.screen), stds[2].change("erm", self.screen), lag_ratio=0.25, run_time=2 )) self.play(morty.change('well')) self.wait(2) self.play(self.change_students("maybe", "confused", "pondering", look_at=self.screen)) self.wait(5) class NoWhiteLight(InteractiveScene): def construct(self): # Test white_label = VGroup( Text("White light", font_size=60), Text("(many frequencies)").set_color(GREY_B) ) white_label.arrange(DOWN) white_label.to_edge(UP).set_x(-3) laser_label = VGroup( Text("Laser", font_size=60).set_color(GREEN_SCREEN), Text("(single frequency)").set_color(GREY_B), ) laser_label.arrange(DOWN) laser_label.move_to(white_label, UP) cross = Cross(white_label, stroke_width=(0, 7, 7, 7, 0)) self.add(white_label) self.wait() self.play(ShowCreation(cross)) self.wait() self.play( FadeOut(VGroup(white_label, cross), DR), FadeIn(laser_label, DR), ) self.wait() class AnnotateSetup(InteractiveScene): def construct(self): # Add iamge image = ImageMobject("CraigSallyHologramSetup") image.set_height(FRAME_HEIGHT) # self.add(image) # Reference polarization pol_words = Text("Correct the polarization") pol_words.set_backstroke(BLACK, 5) point = (-0.5, 1.2, 0) pol_words.next_to(point, UR, buff=1.5).shift(LEFT) pol_arrow = Arrow(pol_words["Correct"].get_bottom(), point) self.play( Write(pol_words), GrowArrow(pol_arrow) ) self.wait() self.play( FadeOut(pol_words), FadeOut(pol_arrow), ) # Show object beam obj_beam_points = [ (-1.625, 2.167, 0), (-1.625, 1.264, 0), (0.375, 1.264, 0), (-0.625, -3.625, 0), (-0.111, -3.167, 0), ] obj_beam = VMobject().set_points_as_corners(obj_beam_points) obj_beam.set_stroke(GREEN_SCREEN, 4) obj_beam_name = Text("Object beam") obj_beam_name.set_color(GREEN_SCREEN) obj_beam_name.next_to(obj_beam.pfp(0.5), RIGHT) scene_point = (1.278, -1.972, 0) scene_circle = Circle(radius=0.75).shift(scene_point) obj_beam_spread = VGroup( Line(obj_beam_points[-1], scene_circle.pfp(a) + np.random.uniform(-0.025, 0.025, 3)) for a in np.arange(0, 1, 0.001) ) obj_beam_spread.set_stroke(GREEN_SCREEN, 1, 0.25) self.play( ShowCreation(obj_beam, rate_func=linear), FadeIn(obj_beam_name, lag_ratio=0.1), ) self.play(ShowCreation(obj_beam_spread, lag_ratio=0, rate_func=rush_from)) self.wait() # Show reference beam ref_beam_points = [ obj_beam_points[0], (-1.61, -1.39, 0), (-1.056, -1.809, 0), ] ref_beam = obj_beam.copy() ref_beam.set_points_as_corners(ref_beam_points) ref_beam_name = Text("Reference beam") ref_beam_name.match_style(obj_beam_name) ref_beam_name.next_to(ref_beam.pfp(0.5), LEFT) ref_circle = Circle(radius=0.5) ref_circle.rotate(PI / 2, RIGHT) ref_circle.move_to((1.23, -3.39, 0)) ref_beam_spread = VGroup( Line(ref_beam_points[-1], ref_circle.pfp(a) + np.random.uniform(-0.025, 0.025, 3)) for a in np.arange(0, 1, 0.001) ) ref_beam_spread.match_style(obj_beam_spread) self.play( FadeTransform(obj_beam_name, ref_beam_name), ReplacementTransform(obj_beam, ref_beam), ReplacementTransform(obj_beam_spread, ref_beam_spread), ) self.wait() class ArrowWithQMark(InteractiveScene): def construct(self): arrow = Arrow(3 * LEFT, 3 * RIGHT, path_arc=-PI / 2) q_marks = Tex(R"???", font_size=72) q_marks.next_to(arrow, UP) self.play( Write(arrow), Write(q_marks), run_time=2 ) self.wait() class ProblemSolvingTipNumber1(InteractiveScene): def construct(self): # Title title = Text("Universal problem-solving tip #1", font_size=72) title.to_edge(UP, buff=LARGE_BUFF) underline = Underline(title, buff=-SMALL_BUFF) parts = VGroup(title[text][0] for text in re.split(" |-", title.text)) words = Text("Start with the simplest\nversion of your problem", font_size=72) words.set_color(YELLOW) self.play(LaggedStartMap(FadeIn, parts, shift=0.25 * UP, lag_ratio=0.25, run_time=2)) self.play(ShowCreation(underline)) self.wait() self.play(Write(words), run_time=3) self.wait() class NameElectromagneticField(InteractiveScene): def construct(self): # Test name1 = Text("Electromagetic Field") name2 = Text("Electric Field") for name in [name1, name2]: name.set_backstroke(BLACK, 5) name.scale(1.5) name.to_edge(UP) expl = Text("3d Vector\nat each point") expl.set_x(FRAME_WIDTH / 4) expl.to_edge(UP) arrow = Vector(RIGHT) arrow = Vector(2 * RIGHT) arrow.next_to(expl, LEFT) self.play(Write(name1), run_time=1) self.wait() self.play(TransformMatchingStrings(name1, name2), run_time=1) self.wait() self.play( name2.animate.next_to(arrow, LEFT), GrowArrow(arrow), FadeIn(expl, RIGHT), ) self.wait() class HoldUpDiffractionEquationInAnticipation(TeacherStudentsScene): def construct(self): # Test equation = Tex(R"d \cdot \sin(\theta) = n \lambda", font_size=60) equation.move_to(self.hold_up_spot, DOWN) name = TexText("Diffraction equation") name.next_to(equation, UP, buff=1.5) arrow = Arrow(name, equation) morty = self.teacher morty.body.insert_n_curves(100) self.play( morty.change("raise_right_hand", equation), FadeIn(equation, UP), self.change_students("confused", "confused", "erm", equation) ) self.play( Write(name), GrowArrow(arrow), ) self.wait() self.play( self.change_students("maybe", "confused", "sassy", look_at=self.screen) ) self.wait(3) self.play( morty.says("You can discover\nthis yourself", mode="hooray"), LaggedStartMap(FadeOut, VGroup(equation, arrow, name), shift=UR, lag_ratio=0.2, run_time=2), self.change_students("pondering", "pondering", "thinking", look_at=morty.eyes) ) self.wait(3) class HowLongIsThatSnippet(TeacherStudentsScene): def construct(self): self.play( self.teacher.says("How long is\nthat snippet?"), self.change_students("happy", "tease", "thinking", look_at=self.screen) ) self.wait(3) class HoldUpDiffractionEquation(TeacherStudentsScene): def construct(self): # Test morty = self.teacher equation = Tex(R"d \cdot \sin(\theta) = \lambda", t2c={R"\lambda": TEAL}, font_size=60) equation.move_to(self.hold_up_spot, DOWN) words = Text("Remember this") words.next_to(equation, UP, 1.5) equation.to_edge(RIGHT) arrow = Arrow(words, equation) self.play( morty.change("raise_left_hand", look_at=equation), FadeIn(equation, UP), self.change_students("pondering", "pondering", "pondering", equation) ) self.play( FadeIn(words, lag_ratio=0.1), GrowArrow(arrow), ) self.play(morty.change("tease")) self.wait(3) morty.body.insert_n_curves(100) self.play( self.change_students("thinking", "erm", "pondering", look_at=self.screen), morty.change("raise_right_hand", look_at=self.screen), ) self.wait(4) class AskAboutCenterBeam(InteractiveScene): def construct(self): # Test randy = Randolph() randy.to_edge(DOWN) self.play( randy.thinks("Why is there a\ncentral beam?", mode="confused") ) self.play(Blink(randy)) self.play(randy.animate.look_at(3 * UR)) self.play(randy.animate.look_at(3 * DR)) class DistanceApproximation(InteractiveScene): def construct(self): # Test expr = Tex(R"\sqrt{L^2 + x^2} \approx L + \frac{x^2}{2L}") expr.to_corner(UL) circle = SurroundingRectangle(expr[R"\frac{x^2}{2L}"]) circle.round_corners() circle.set_stroke(RED) words = Text("First order\nTaylor approx.") words.next_to(circle, DOWN, LARGE_BUFF) words.set_color(RED) words.set_backstroke(BLACK, 5) arrow = Arrow(words.get_top(), circle.get_bottom()) arrow.set_color(RED) self.play(Write(expr)) self.wait() self.play( ShowCreation(circle), GrowArrow(arrow), FadeIn(words) ) self.wait() class CircleDiffractionEquation(InteractiveScene): def construct(self): # Add equation self.add(FullScreenRectangle()) equation = Tex( R"{d} \cdot \sin(\theta) = n \lambda", font_size=72, t2c={R"{d}": BLUE, R"\theta": YELLOW, R"\lambda": TEAL} ) equation.set_backstroke(BLACK) title = Text("The Diffraction Equation", font_size=60) title.set_color(GREY_A) title.to_edge(UP, buff=MED_SMALL_BUFF) equation.next_to(title, DOWN, MED_LARGE_BUFF) self.add(title) self.add(equation) self.play( FlashAround(equation, run_time=4, time_width=1.5, buff=MED_SMALL_BUFF), ) self.wait() class DiffractionGratingGreenLaserExampleNumbers(InteractiveScene): def construct(self): # Test lines = VGroup( VGroup( Text("Grating: 500 lines / mm"), Tex(R"\Rightarrow d = 2 \times 10^{-6} \text{m}"), ).arrange(RIGHT), VGroup( Text("Green light wavelength: 500 nm "), Tex(R"\Rightarrow \lambda = 5 \times 10^{-7} \text{m}"), ).arrange(RIGHT), Tex(R"\theta = \sin^{-1}(\lambda / d) = \sin^{-1}\left(5 \times 10^{-7} / 2 \times 10^{-6} \right) \approx 14.5^\circ") ) lines.arrange(DOWN, aligned_edge=LEFT, buff=LARGE_BUFF) lines.to_edge(LEFT) lines[0][1].align_to(lines[1][1], LEFT) self.add(lines) class AnnotateZerothOrderBeam2(InteractiveScene): def construct(self): image = ImageMobject("DiffractionGratingGreenLaser.jpg") # self.add(image.set_height(FRAME_HEIGHT)) # Names points = [ (-0.67, 1.64, 0.0), (3.64, 1.9, 0.0), (-4.9, 1.85, 0.0), (-5.4, 1.01), (2.42, 0.028), ] names = VGroup( Text("Zeroth-order beam"), Text("First-order beams"), Text("Second-order beams"), ) names.next_to(points[0], UP, buff=2.5) names.shift_onto_screen() arrow0 = Arrow(names[0], points[0]) arrows1 = VGroup( Arrow(names[1].get_bottom(), points[1]), Arrow(names[1].get_bottom(), points[2]), ) arrows2 = VGroup( Arrow(names[2].get_bottom(), points[3]), Arrow(names[2].get_bottom(), points[4]), ) VGroup(names, arrow0, arrows1, arrows2).set_fill(GREY_E) self.play( Write(names[0]), GrowArrow(arrow0), run_time=1 ) self.wait() self.remove(arrow0) self.play( TransformMatchingStrings(names[0], names[1], key_map={"Zeroth": "First", "m": "ms"}), TransformFromCopy(arrow0.replicate(2), arrows1), run_time=1 ) self.wait() self.play( TransformMatchingStrings(names[1], names[2], key_map={"First": "Second"}), ReplacementTransform(arrows1, arrows2), run_time=1 ) self.wait() class ExactSpacingQuestion(InteractiveScene): def construct(self): # Test question = Text("What is the exact spacing?", font_size=72) question.set_backstroke() question.to_edge(UP) subq = TexText(R"As a function of $\theta'$") subq.set_color(GREY_A) self.play(Write(question, stroke_color=WHITE)) self.wait() self.play(question.animate.scale(48 / 72).set_x(-0.25 * FRAME_WIDTH)) self.wait() subq.next_to(question, DOWN) self.play(FadeIn(subq, 0.5 * DOWN)) self.wait() class DejaVu(TeacherStudentsScene): def construct(self): # Test stds = self.students self.play( stds[0].change("pondering", self.screen), stds[1].change("pondering", self.screen), stds[2].says("That looks\nfamiliar", bubble_config=dict(direction=LEFT), look_at=self.screen), self.teacher.change("tease"), ) self.wait(2) diff_eq = Tex(R"d \cdot \sin(\theta) = \lambda") diff_eq.next_to(stds[0], UR) self.play( stds[1].change("raise_left_hand", look_at=diff_eq), FadeIn(diff_eq, UP) ) self.look_at(diff_eq) self.play(stds[2].change("pondering", diff_eq)) self.wait(3) class WhatAHologramReconstructs(InteractiveScene): def construct(self): # Test self.add(FullScreenRectangle()) title = Text("What a Hologram reproduces", font_size=60) title.to_edge(UP, buff=MED_SMALL_BUFF) underline = Underline(title, buff=-0.05) items = VGroup( Text("1) Copy of the reference wave"), Text("2) Copy of the object wave"), TexText(R"3) Reflection$^*$ of the object wave"), ) items.scale(0.8) items.arrange(DOWN, buff=1.75, aligned_edge=LEFT) items.next_to(underline, DOWN, LARGE_BUFF) items.to_edge(LEFT) self.play( FadeIn(title), ShowCreation(underline) ) self.play( LaggedStart( (FadeIn(item[:2]) for item in items), lag_ratio=0.05, ) ) self.wait() for n, item in enumerate(items): self.play( items[:n].animate.set_opacity(0.25), FadeIn(item[2:], lag_ratio=0.1) ) self.wait() class AskAboutHigherOrderBeams(TeacherStudentsScene): def construct(self): stds = self.students morty = self.teacher self.play(LaggedStart( stds[0].change('pondering', self.screen), stds[1].says("What about higher\norder beams?", look_at=self.screen), stds[2].change("confused", self.screen), morty.change("tease") )) self.wait() self.play(stds[1].change("sassy", morty.eyes)) self.wait(6) class BinaryVsSinusoidalDiffraction(InteractiveScene): def construct(self): # Add axes top_axes, low_axes = two_axes = VGroup( Axes((0, 4, 0.5), (0, 1, 0.5), width=6, height=1.5) for _ in range(2) ) two_axes.arrange(DOWN, buff=2.0) two_axes.to_edge(LEFT, buff=1.5) for axes in two_axes: y_label = Text("Opacity", font_size=30) y_label.next_to(axes.y_axis, UP, buff=MED_SMALL_BUFF) axes.add(y_label) axes.y_axis.add_numbers(font_size=16, num_decimal_places=1) self.add(two_axes) # Add graphs discontinuities = [*np.arange(5), *(np.arange(5) + 0.2)] discontinuities.sort() top_graph = top_axes.get_graph(self.func1, x_range=(0, 3.99), discontinuities=discontinuities) top_graph.set_stroke(TEAL, 2) low_axes.num_sampled_graph_points_per_tick = 20 low_graph = low_axes.get_graph(self.func2) low_graph.set_stroke(BLUE, 2) graphs = VGroup(top_graph, low_graph) # Add gratings top_grating = self.get_grating(top_axes, self.func1, 1000) low_grating = self.get_grating(low_axes, self.func2, 1000) gratings = VGroup(top_grating, low_grating) # Animate in graphs.set_stroke(width=1) self.add(graphs) for graph, grating in [(top_graph, top_grating), (low_graph, low_grating)]: self.add(grating, graph) self.play( graph.animate.set_stroke(width=2), VShowPassingFlash(graph.copy().set_stroke(width=5), time_width=3, rate_func=linear), # ShowCreation(graph, rate_func=linear), FadeIn(grating, lag_ratio=1e-3), run_time=2 ) self.play( grating.animate.next_to(grating, RIGHT, MED_LARGE_BUFF), run_time=2 ) self.wait() # Labels high_beam_labels = VGroup( Text("Higher order beams", font_size=36).next_to(grating, UP) for grating in gratings ) check = Checkmark().set_color(GREEN).scale(1.5) check.next_to(high_beam_labels[0]) ex = Exmark().set_color(RED).scale(1.5) ex.next_to(high_beam_labels[1]) self.play(LaggedStart( FadeIn(high_beam_labels), Write(check), Write(ex), lag_ratio=0.5 )) self.wait() def get_grating(self, axes, func, n_slits): grating = Rectangle().replicate(n_slits) grating.set_stroke(width=0) grating.set_fill(GREY_D) grating.set_shading(0.25, 0.25, 0) grating.arrange(RIGHT, buff=0) grating.set_shape(axes.x_axis.get_width(), axes.y_axis.get_height()) grating.move_to(axes.c2p(0, 0), DL) for mob in grating: mob.set_opacity(func(axes.x_axis.p2n(mob.get_center()))) # grating.next_to(grating, RIGHT, MED_LARGE_BUFF) return grating def func1(self, x): return 0 if x % 1 < 0.2 else 1 def func2(self, x): return math.sin(TAU * x)**2 class AskWhyForSinusoidalGratingFact(TeacherStudentsScene): def construct(self): # Test stds = self.students morty = self.teacher for pi in self.pi_creatures: pi.body.insert_n_curves(100) self.play(LaggedStart( stds[1].says("Wait, why?", mode="confused", look_at=self.screen), stds[0].change("pondering", self.screen), stds[2].change("maybe", self.screen), )) self.wait() implication = VGroup( Tex(R"\Leftarrow").scale(2), Text("More formal\nholography explanation") ) implication.arrange(RIGHT, buff=0.25) implication.move_to(2.5 * UP + 2.5 * RIGHT) self.play( morty.change("raise_right_hand"), GrowFromPoint(implication, morty.get_corner(UL)) ) self.play(self.change_students("thinking", "sassy", "erm")) self.look_at(self.screen) self.play(stds[1].change("pondering", self.screen)) self.wait(4) class NeedsMoreRigor(TeacherStudentsScene): def construct(self): morty = self.teacher arrow = Vector(LEFT, thickness=4) arrow.move_to(2.5 * UP) words = Text("Sketchy and non-rigorous") words.next_to(arrow) self.play( morty.change("guilty"), self.change_students("erm", "hesitant", "sassy", look_at=self.screen) ) self.play( GrowArrow(arrow), Write(words) ) self.wait(4) class CompareFilmTypes(InteractiveScene): def construct(self): # Test categories = VGroup( Text("Polaroid instant film"), Text("Microfilm"), Text("What we used (Bayfol HX200)"), ) categories[2]["(Bayfol HX200)"].set_color(GREY_B) resolutions = VGroup( Text("10-20 lines per mm"), Text("100-200 lines per mm"), Text("> 5,000 lines per mm"), ) arrows = Vector(RIGHT, thickness=4).replicate(3) last_group = VGroup() for text, res, arrow in zip(categories, resolutions, arrows): arrow = Vector(RIGHT) group = VGroup(text, arrow, res) group.arrange(RIGHT) res.align_to(text, UP) group.to_edge(UP) text.save_state() text.set_x(0) self.play( FadeOut(last_group, 0.5 * UP), FadeIn(text, 0.5 * UP), ) self.wait() self.play( Restore(text), GrowArrow(arrow), FadeIn(res, RIGHT) ) self.wait() last_group = group class TheresADeeperIssue(TeacherStudentsScene): def construct(self): for std in self.students: std.change_mode("pondering") std.look_at(self.screen) self.play( self.teacher.says("There's a\ndeeper issue"), self.change_students("erm", "guilty", "hesitant", look_at=self.teacher.eyes) ) self.wait(2) self.play( self.change_students("pondering", "pondering", 'pondering', look_at=self.screen) ) self.wait(2) class SharpMindedViewer(InteractiveScene): def construct(self): # Test self.add(FullScreenRectangle()) randy = Randolph() randy.to_edge(LEFT) randy.shift(DOWN) self.play(randy.change("sassy", RIGHT)) self.play(Blink(randy)) self.wait(2) self.play(randy.change("confused", RIGHT)) self.wait() self.play(Blink(randy)) self.wait() class WhatThisExplanationLacks(InteractiveScene): def construct(self): # Title title = Text("Gaps in the single-point explanation", font_size=60) title.to_edge(UP, buff=MED_SMALL_BUFF) underline = Underline(title, buff=-0.05) self.play( FadeIn(title, lag_ratio=0.1), ShowCreation(underline), ) self.wait() # Add points points = BulletedList( "How do errors in the various approximations accumulate?", "Why don't higher order beams exist?", "What happens when you change the reference beam angle?", buff=0.5, font_size=48, ) points.next_to(underline, DOWN, buff=0.5) points.to_edge(LEFT, buff=LARGE_BUFF) self.play( LaggedStartMap(FadeIn, points, shift=UP, lag_ratio=0.5) ) self.wait() self.play(points[:2].animate.set_opacity(0.5)) self.wait() class SimplicityToGenerality(InteractiveScene): def construct(self): # Initialize little triangles frame = self.frame surface = Torus(resolution=(49, 49)) surface.set_width(4) verts = surface.get_shader_data()['point'] triangles = VGroup( Polygon(*tri) for tri in zip(verts[0::3], verts[1::3], verts[2::3]) ) triangles.set_stroke(WHITE, 0.5, 0.5) tri1 = triangles[3500] dists = [get_norm(tri.get_center() - tri1.get_center()) for tri in triangles] neighbors = VGroup(triangles[idx] for idx in np.argsort(dists)) ng1 = neighbors[1:10] ng2 = neighbors[10:200] ng3 = neighbors[200:] for group in [ng1, ng2, ng3]: group.save_state() for tri in group: tri.become(tri1) tri.set_stroke(width=0.1, opacity=0.25) ng3.set_stroke(opacity=0.05) frame.reorient(4, 83, 0, (-0.11, -0.05, -0.34), 1.91) self.add(tri1) self.play( LaggedStart( Restore(ng1, lag_ratio=0.3), Restore(ng2, lag_ratio=0.02), Restore(ng3, lag_ratio=3e-4), lag_ratio=0.4 ), frame.animate.reorient(29, 64, 0, (-0.15, 0.02, -0.43), 3.21), run_time=9, ) self.add(triangles) # True surface equation = Tex(R"\left(x^2+y^2+z^2+R^2-r^2\right)^2=4 R^2\left(x^2+y^2\right)") equation.fix_in_frame() equation.to_edge(UP, buff=0.35) new_surface = ParametricSurface( lambda u, v: surface.uv_func(v, u), u_range=(0, TAU), v_range=(0, TAU), resolution=(250, 250) ) new_surface.set_width(4) new_surface.set_opacity(0.5) new_surface.always_sort_to_camera(self.camera) triangles.shuffle() self.play( FadeOut(triangles, scale=0.8, lag_ratio=3e-4), frame.animate.reorient(77, 62, 0, (-0.27, -0.05, -0.23), 4.29), run_time=2 ) self.play( ShowCreation(new_surface, run_time=3), frame.animate.reorient(58, 66, 0, (-0.27, -0.05, -0.23), 4.29).set_anim_args(run_time=4), ) self.play(frame.animate.reorient(50, 79, 0, (-0.27, -0.05, -0.23), 4.29), run_time=3) class ModeledAs2D(InteractiveScene): def construct(self): # Test words = Text("Modeled as 2D") words.to_edge(UP) point = 1.5 * RIGHT arrow = Arrow(words.get_right(), point, path_arc=-180 * DEGREES, thickness=4) self.play( FadeIn(words, 0.25 * UP), DrawBorderThenFill(arrow, run_time=2) ) self.wait() class ThinkingAboutRediscovery(InteractiveScene): def construct(self): # Test randy = Randolph() randy.body.insert_n_curves(100) randy.to_corner(DL) bubble = ThoughtBubble(filler_shape=(5, 2)) bubble.pin_to(randy) bubble = bubble[0] bubble.set_fill(opacity=0) rect = FullScreenRectangle().set_fill(BLACK, 1) rect.append_points([rect.get_points()[-1], *bubble[-1].get_points()]) self.add(rect, randy) self.play( randy.change('pondering'), Write(bubble, stroke_color=WHITE, lag_ratio=0.2) ) self.play(Blink(randy)) self.wait(2) self.play(randy.change('thinking', bubble.get_top())) self.play(Blink(randy)) self.play(randy.change('tease', bubble.get_top())) for _ in range(2): self.play(Blink(randy)) self.wait(2) class IntroduceFormalSection(TeacherStudentsScene): def construct(self): # Test morty = self.teacher stds = self.students self.play(LaggedStart( stds[0].change("sassy", morty.eyes), stds[1].says("Okay but really, why\ndoes it work?", look_at=morty.eyes), stds[2].change("angry", look_at=morty.eyes), morty.change("guilty"), )) self.wait(2) self.play(LaggedStart( morty.change("tease"), stds[0].change("well"), stds[1].debubble(), stds[2].change("hesitant"), lag_ratio=0.5 )) self.wait(2) # Show complex plane plane = ComplexPlane((-3, 3), (-3, 3)) plane.faded_lines.set_stroke(BLUE_E, 1, 0.5) plane.axes.set_stroke(width=1) plane.background_lines.set_stroke(width=1) plane.set_width(3) plane.next_to(self.hold_up_spot, UP) a, b = (2, 1.5) z = complex(a, b) z_dot = GlowDot(plane.n2p(0), color=WHITE) z_dot.set_z_index(1) h_line = Line(plane.n2p(0), plane.n2p(a)) v_line = Line(plane.n2p(a), plane.n2p(z)) h_line.set_stroke(YELLOW, 3) v_line.set_stroke(RED, 3) a_label = Tex(R"a", font_size=24) a_label.match_color(h_line) a_label.next_to(h_line, DOWN, buff=0.1) b_label = Tex(R"bi", font_size=24) b_label.match_color(v_line) b_label.next_to(v_line, RIGHT, buff=0.1) z_label = Tex(R"a + bi", font_size=24) z_label.next_to(v_line.get_end(), UR, SMALL_BUFF) VGroup(a_label, b_label, z_label).set_backstroke(BLACK, 3) self.play( morty.change("raise_right_hand", plane), self.change_students(*3 * ["pondering"], look_at=plane), FadeIn(plane, UP), ) self.play( ShowCreation(h_line), FadeIn(a_label, 0.5 * RIGHT), z_dot.animate.move_to(plane.n2p(a)), ) self.play( ShowCreation(v_line), FadeIn(b_label, 0.5 * UP), z_dot.animate.move_to(plane.n2p(z)), ) self.play( TransformMatchingShapes(VGroup(a_label, b_label).copy(), z_label) ) self.play(self.change_students("erm", "thinking", "well", look_at=plane)) self.wait(2) class HoldUpEquation(InteractiveScene): def construct(self): pass class GaborQuote(InteractiveScene): def construct(self): # Test quote = TexText(R""" ``This was an exercise\\ in serendipity, the art of\\ looking for something and\\ finding something else'' """, font_size=60, alignment="") quote.to_edge(RIGHT) self.play(Write(quote), run_time=2, lag_ratio=0.01) self.play(quote["looking for something"].animate.set_color(BLUE), lag_ratio=0.1) self.play(quote["finding something else"].animate.set_color(TEAL), lag_ratio=0.1) self.wait() class GaborQuote2(InteractiveScene): def construct(self): # Test quote = TexText(R""" ``In holography, nature\\ is on the inventor's side'' """, font_size=60, alignment="") quote.to_edge(RIGHT) self.play(Write(quote), run_time=2, lag_ratio=0.1) self.wait() class ComplexConjugateFact(InteractiveScene): def construct(self): # Show conjugate z = complex(2, 1) plane = ComplexPlane( (-6, 6), (-4, 4), faded_line_ratio=4, background_line_style=dict( stroke_color=BLUE_D, stroke_width=1, ), faded_line_style=dict( stroke_color=BLUE_E, stroke_width=1, stroke_opacity=0.5, ), ) plane.set_height(7) plane.to_edge(DOWN, buff=0.25) plane.add_coordinate_labels(font_size=16) title = Text("Complex plane") title.next_to(plane, UP, buff=SMALL_BUFF) z_arrow = Arrow(plane.get_origin(), plane.n2p(z), buff=0) z_arrow.set_color(YELLOW) z_label = Tex(R"z = a + bi") z_label.next_to(z_arrow.get_end(), UP) z_conj = complex(z.real, -z.imag) z_conj_arrow = Arrow(plane.get_origin(), plane.n2p(z_conj), buff=0) z_conj_arrow.set_color(TEAL) z_conj_label = Tex("z^* = a - bi") z_conj_label.next_to(z_conj_arrow.get_end(), DOWN) conj_label = Text("Complex conjugate") conj_label.next_to(z_conj_label, DOWN, aligned_edge=LEFT) conj_label.set_backstroke(BLACK, 5) self.add(plane, title) self.add(z_arrow, z_label) self.wait() self.play(Write(conj_label, stroke_color=WHITE)) self.play( TransformFromCopy(z_arrow, z_conj_arrow, path_arc=-PI / 2), TransformMatchingStrings(z_label.copy(), z_conj_label, path_arc=-PI / 2), run_time=2 ) self.wait() # Show product product_arrow = Arrow(plane.get_origin(), plane.n2p(z * z_conj), buff=0) product_arrow.set_color(WHITE) product_label = Tex(R"z \cdot z^* = |z|^2") product_label.next_to(product_arrow.get_end(), UP) product_label.shift(0.75 * RIGHT) self.play( TransformFromCopy(z_label[0], product_label[R"z \cdot"][0]), TransformFromCopy(z_conj_label[:2], product_label["z^*"][0]), TransformFromCopy(z_arrow, product_arrow), TransformFromCopy(z_conj_arrow, product_arrow), ) self.play(Write(product_label["= |z|^2"][0])) self.wait() class PrepareComplexAlgebra(InteractiveScene): def construct(self): # Test lines = VGroup( Tex(R"R \cdot (1 - \text{Opacity})"), Tex(R"R \cdot (1 - c|R + O|^2)"), Tex(R"R - c R \cdot |R + O|^2"), ) lines.arrange(DOWN, buff=0.75) lines.to_edge(UP) label = Text("Wave beyond\nthe film") arrow = Vector(LEFT) arrow.next_to(lines[0], RIGHT) label.next_to(arrow, RIGHT) rect = SurroundingRectangle(lines[2][R"R \cdot |R + O|^2"], buff=0.05) rect.set_stroke(TEAL, 2) self.play( FadeIn(label, lag_ratio=0.1), GrowArrow(arrow), FadeIn(lines[0], LEFT), ) self.wait() self.play( TransformMatchingStrings(lines[0].copy(), lines[1]), run_time=2 ) self.wait() self.play( TransformMatchingStrings(lines[1].copy(), lines[2]), run_time=2 ) self.wait() self.play( ShowCreation(rect), lines[:2].animate.set_opacity(0.5), lines[2][R"R - c"].animate.set_opacity(0.5), ) self.wait() class ComplexAlgebra(InteractiveScene): def construct(self): # Add first lines lines = VGroup( Tex(R"R \cdot |R + O|^2"), Tex(R"R \cdot (R + O)(R^* + O^*)"), Tex(R"R \cdot R \cdot R^* + R \cdot R^* \cdot O + R \cdot R \cdot O^*+ R \cdot O \cdot O^*"), Tex(R"\left(|R|^2 + |O|^2 \right) \cdot R + |R|^2 \cdot O + R^2 \cdot O^*"), ) lines[2].scale(0.75) lines.arrange(DOWN, buff=LARGE_BUFF) lines.to_edge(UP) label = Text("Part of the wave\nbeyond the film", font_size=36) arrow = Vector(LEFT) arrow.next_to(lines[0], RIGHT) label.next_to(arrow, RIGHT) label.shift_onto_screen() self.add(lines[0]) self.play( Write(label), GrowArrow(arrow) ) self.wait() self.play(LaggedStart( TransformFromCopy(lines[0][:-1], lines[1][R"R \cdot (R + O)"][0]), TransformFromCopy(lines[0]["|R + O|"][0].copy(), lines[1]["(R^* + O^*)"][0]), lag_ratio=0.1, run_time=2 )) self.wait() # FOIL expansion R0 = lines[1]["R"][0] R = lines[1]["R"][1] O = lines[1]["O"][0] Rc = lines[1]["R^*"][0] Oc = lines[1]["O^*"][0] l1_groups = [ VGroup(R0, R, Rc), VGroup(R0, O, Rc), VGroup(R0, R, Oc), VGroup(R0, O, Oc), ] l2_groups = [ lines[2][substr] for substr in [ R"R \cdot R \cdot R^*", R"R \cdot R^* \cdot O", R"R \cdot R \cdot O^*", R"R \cdot O \cdot O^*", ] ] plusses = lines[2]["+"] plusses.add_to_back(VectorizedPoint()) pre_rects = VGroup(map(self.get_term_rect, l1_groups[0])) post_rect = self.get_term_rect(l2_groups[0]) VGroup(pre_rects, post_rect).set_stroke(width=0, opacity=0) self.add(pre_rects, post_rect) for l1_group, l2_group, plus in zip(l1_groups, l2_groups, plusses): self.play( Transform(pre_rects, VGroup(map(self.get_term_rect, l1_group))), Transform(post_rect, self.get_term_rect(l2_group)), FadeIn(l2_group), FadeIn(plus), ) self.wait(0.5) self.add(lines[2]) self.play( FadeOut(pre_rects), FadeOut(post_rect), ) self.wait() # Highlight conjugate pairs pair_rects = VGroup( self.get_term_rect(lines[2][R"R \cdot R^*"][0]), self.get_term_rect(lines[2][R"R \cdot R^*"][1]), self.get_term_rect(lines[2][R"O \cdot O^*"]), ) pair_rects.set_stroke(RED, 2) real_label = Text("Real numbers") real_label.next_to(lines[2], DOWN, buff=1.5) real_label.set_color(RED) arrows = VGroup( Arrow(real_label, rect.get_bottom()) for rect in pair_rects ) arrows.set_color(RED) self.play(ShowCreation(pair_rects, lag_ratio=0.1)) self.play( FadeIn(real_label, lag_ratio=0.1), LaggedStartMap(GrowArrow, arrows) ) self.wait() self.play( FadeOut(real_label), FadeOut(arrows), FadeOut(pair_rects), ) self.wait() # Organize into the last line lines[3].next_to(lines[2], DOWN, buff=1.5) lines[3].set_opacity(1) l3_groups = [ lines[3][R"\left(|R|^2 + |O|^2 \right) \cdot R"], lines[3][R"|R|^2 \cdot O"], lines[3][R"R^2 \cdot O^*"], ] l2_plusses = lines[2]["+"] l3_plusses = lines[3]["+"] l2_rects = VGroup(map(self.get_term_rect, l2_groups)) l3_rects = VGroup(map(self.get_term_rect, l3_groups)) l3_rects[2].match_height(l3_rects, stretch=True, about_edge=UP) box1_lines = VGroup( self.connecting_line(l2_rects[0], l3_rects[0]), self.connecting_line(l2_rects[3], l3_rects[0]), ) box2_line = self.connecting_line(l2_rects[1], l3_rects[1]) box3_line = self.connecting_line(l2_rects[2], l3_rects[2]) real_brace1 = Brace(lines[3][R"\left(|R|^2 + |O|^2 \right)"], DOWN) real_brace2 = Brace(lines[3][R"|R|^2"][1], DOWN) real_label = real_brace1.get_text("Some real number", font_size=36) fade_opacity = 0.5 self.play( ShowCreation(box1_lines, lag_ratio=0.5), FadeIn(l2_rects[0]), FadeIn(l2_rects[3]), FadeTransform(l2_groups[0].copy(), l3_groups[0], time_span=(0.5, 2)), FadeTransform(l2_groups[3].copy(), l3_groups[0], time_span=(1, 2)), FadeIn(l3_rects[0], time_span=(1, 2)), l2_groups[1].animate.set_opacity(fade_opacity), l2_groups[2].animate.set_opacity(fade_opacity), l2_plusses.animate.set_opacity(fade_opacity), run_time=2 ) self.wait() self.play( GrowFromCenter(real_brace1), FadeIn(real_label, shift=0.25 * DOWN) ) self.wait() self.play( box1_lines.animate.set_stroke(WHITE, 1, 0.5), VGroup(l2_rects[0], l2_rects[3], l3_rects[0]).animate.set_stroke(GREY, 1, 0.5), l2_groups[1].animate.set_opacity(1), l2_groups[0].animate.set_opacity(fade_opacity), l2_groups[3].animate.set_opacity(fade_opacity), l3_groups[0].animate.set_opacity(fade_opacity), FadeOut(real_brace1), real_label.animate.set_opacity(fade_opacity), ) self.play( FadeIn(l2_rects[1]), ShowCreation(box2_line), FadeIn(l3_rects[1], time_span=(0.5, 1.5)), TransformMatchingShapes(l2_groups[1].copy(), l3_groups[1], run_time=1), FadeIn(l3_plusses[1]), ) self.wait() self.play( GrowFromCenter(real_brace2), real_label.animate.next_to(real_brace2, DOWN).set_opacity(1) ) self.wait() self.play( box2_line.animate.set_stroke(WHITE, 1, 0.5), VGroup(l2_rects[1], l3_rects[1]).animate.set_stroke(GREY, 1, 0.5), l2_groups[2].animate.set_opacity(1), l2_groups[1].animate.set_opacity(fade_opacity), l3_groups[1].animate.set_opacity(fade_opacity), l3_plusses[1].animate.set_opacity(fade_opacity), FadeOut(real_brace2), FadeOut(real_label), ) self.play( FadeTransform(l2_groups[2].copy(), l3_groups[2], run_time=1.5), ShowCreation(box3_line, run_time=1.5), FadeIn(l2_rects[1]), FadeIn(l3_rects[2], time_span=(0.5, 1.5)), FadeIn(l3_plusses[2]) ) self.wait() # Bring back self.play( FadeOut(VGroup(box1_lines, box2_line, box3_line)), FadeOut(l2_rects), l3_rects.animate.set_stroke(TEAL, 1, 1), lines[2].animate.set_opacity(0.5), lines[3].animate.set_opacity(1), ) self.wait() def get_term_rect(self, term): rect = SurroundingRectangle(term) rect.round_corners() rect.set_stroke(TEAL, 2) return rect def connecting_line(self, high_box, low_box): return CubicBezier( high_box.get_bottom(), high_box.get_bottom() + 1.0 * DOWN, low_box.get_top() + 1.0 * UP, low_box.get_top(), ).set_stroke(WHITE, 2) class PlaneAfterFilm(InteractiveScene): def construct(self): # Test image = ImageMobject("FilmFromBehind") image.set_height(FRAME_HEIGHT) image.set_height(FRAME_HEIGHT) image.fix_in_frame() # self.add(image) rect = Polygon( (2.56, -0.12, 0.0), (5.69, -2.51, 0.0), (6.25, 1.31, 0.0), (2.72, 2.62, 0.0), ) rect.set_fill(BLACK, 0.75) rect.set_stroke(BLUE, 10) rect.fix_in_frame() words = Text("True on this\n2D Plane") self.set_floor_plane("xz") self.frame.reorient(73, -24, 0, (-1.53, -0.68, 4.14), 9.19) self.play( DrawBorderThenFill(rect), FadeIn(words), ) self.wait() class LookingAtScreen(TeacherStudentsScene): def construct(self): self.play( self.change_students("confused", "pondering", "maybe", look_at=self.screen), self.teacher.change("well") ) self.wait(5) class EndScreen(PatreonEndScreen): pass # Old stubs class DoubleSlitSupplementaryGraphs(InteractiveScene): def construct(self): # Setup all three axes, with labels # Show constructive interference # Show destructive interference ... class DistApproximations(InteractiveScene): def construct(self): # Show sqrt(L^2 + x^2) approx L + x/(2L) approx L pass class DiffractionEquation(InteractiveScene): def construct(self): # Add equation equation = Tex(R"{d} \cdot \sin(\theta) = \lambda", font_size=60) equation.set_backstroke(BLACK) arrow = Vector(DOWN, thickness=4) arrow.set_color(BLUE) d, theta, lam = syms = [equation[s][0] for s in [R"{d}", R"\theta", R"\lambda"]] colors = [BLUE, YELLOW, TEAL] arrow.next_to(d, UP, LARGE_BUFF) arrow.set_fill(opacity=0) self.add(equation) for sym, color in zip(syms, colors): self.play( FlashAround(sym, color=color, time_span=(0.25, 1.25)), sym.animate.set_fill(color), arrow.animate.next_to(sym, UP).set_fill(color, 1), ) self.wait() self.play(FadeOut(arrow))