2017-08-24 11:44:06 -07:00
|
|
|
from helpers import *
|
|
|
|
|
|
|
|
from mobject.tex_mobject import TexMobject
|
|
|
|
from mobject import Mobject
|
|
|
|
from mobject.image_mobject import ImageMobject
|
|
|
|
from mobject.vectorized_mobject import *
|
|
|
|
|
|
|
|
from animation.animation import Animation
|
|
|
|
from animation.transform import *
|
|
|
|
from animation.simple_animations import *
|
2017-08-24 23:12:25 -07:00
|
|
|
from animation.continual_animation import *
|
2017-08-24 11:44:06 -07:00
|
|
|
from animation.playground import *
|
|
|
|
from topics.geometry import *
|
|
|
|
from topics.characters import *
|
|
|
|
from topics.functions import *
|
|
|
|
from topics.fractals import *
|
|
|
|
from topics.number_line import *
|
|
|
|
from topics.combinatorics import *
|
|
|
|
from topics.numerals import *
|
|
|
|
from topics.three_dimensions import *
|
|
|
|
from topics.objects import *
|
|
|
|
from topics.probability import *
|
|
|
|
from topics.complex_numbers import *
|
|
|
|
from scene import Scene
|
|
|
|
from scene.reconfigurable_scene import ReconfigurableScene
|
|
|
|
from scene.zoomed_scene import *
|
|
|
|
from camera import Camera
|
|
|
|
from mobject.svg_mobject import *
|
|
|
|
from mobject.tex_mobject import *
|
|
|
|
|
2017-09-06 20:18:19 -07:00
|
|
|
|
2017-08-24 11:44:06 -07:00
|
|
|
E_COLOR = BLUE
|
2017-08-25 17:56:55 -07:00
|
|
|
M_COLOR = YELLOW
|
2017-08-24 11:44:06 -07:00
|
|
|
|
|
|
|
class OscillatingVector(ContinualAnimation):
|
|
|
|
CONFIG = {
|
|
|
|
"tail" : ORIGIN,
|
|
|
|
"frequency" : 1,
|
2017-08-27 23:52:28 -07:00
|
|
|
"A_vect" : [1, 0, 0],
|
|
|
|
"phi_vect" : [0, 0, 0],
|
2017-08-24 23:12:25 -07:00
|
|
|
"vector_to_be_added_to" : None,
|
2017-08-24 11:44:06 -07:00
|
|
|
}
|
|
|
|
def setup(self):
|
|
|
|
self.vector = self.mobject
|
|
|
|
|
|
|
|
def update_mobject(self, dt):
|
|
|
|
f = self.frequency
|
2017-08-24 12:38:37 -07:00
|
|
|
t = self.internal_time
|
2017-08-24 11:44:06 -07:00
|
|
|
angle = 2*np.pi*f*t
|
|
|
|
vect = np.array([
|
2017-08-27 23:52:28 -07:00
|
|
|
A*np.exp(complex(0, angle + phi))
|
|
|
|
for A, phi in zip(self.A_vect, self.phi_vect)
|
2017-08-24 11:44:06 -07:00
|
|
|
]).real
|
2017-08-24 23:12:25 -07:00
|
|
|
self.update_tail()
|
2017-08-24 11:44:06 -07:00
|
|
|
self.vector.put_start_and_end_on(self.tail, self.tail+vect)
|
|
|
|
|
2017-08-24 23:12:25 -07:00
|
|
|
def update_tail(self):
|
|
|
|
if self.vector_to_be_added_to is not None:
|
|
|
|
self.tail = self.vector_to_be_added_to.get_end()
|
|
|
|
|
|
|
|
class OscillatingVectorComponents(ContinualAnimationGroup):
|
|
|
|
CONFIG = {
|
|
|
|
"tip_to_tail" : False,
|
|
|
|
}
|
|
|
|
def __init__(self, oscillating_vector, **kwargs):
|
|
|
|
digest_config(self, kwargs)
|
|
|
|
vx = Vector(UP, color = GREEN).fade()
|
|
|
|
vy = Vector(UP, color = RED).fade()
|
|
|
|
kwargs = {
|
|
|
|
"frequency" : oscillating_vector.frequency,
|
|
|
|
"tail" : oscillating_vector.tail,
|
|
|
|
}
|
|
|
|
ovx = OscillatingVector(
|
|
|
|
vx,
|
|
|
|
A_x = oscillating_vector.A_x,
|
|
|
|
phi_x = oscillating_vector.phi_x,
|
|
|
|
A_y = 0,
|
|
|
|
phi_y = 0,
|
|
|
|
**kwargs
|
|
|
|
)
|
|
|
|
ovy = OscillatingVector(
|
|
|
|
vy,
|
|
|
|
A_x = 0,
|
|
|
|
phi_x = 0,
|
|
|
|
A_y = oscillating_vector.A_y,
|
|
|
|
phi_y = oscillating_vector.phi_y,
|
|
|
|
**kwargs
|
|
|
|
)
|
|
|
|
components = [ovx, ovy]
|
|
|
|
self.vectors = VGroup(ovx.vector, ovy.vector)
|
|
|
|
if self.tip_to_tail:
|
|
|
|
ovy.vector_to_be_added_to = ovx.vector
|
|
|
|
else:
|
|
|
|
self.lines = VGroup()
|
|
|
|
for ov1, ov2 in (ovx, ovy), (ovy, ovx):
|
|
|
|
ov_line = ov1.copy()
|
|
|
|
ov_line.mobject = ov_line.vector = DashedLine(
|
|
|
|
UP, DOWN, color = ov1.vector.get_color()
|
|
|
|
)
|
|
|
|
ov_line.vector_to_be_added_to = ov2.vector
|
|
|
|
components.append(ov_line)
|
|
|
|
self.lines.add(ov_line.line)
|
|
|
|
|
|
|
|
ContinualAnimationGroup.__init__(self, *components, **kwargs)
|
|
|
|
|
|
|
|
class EMWave(ContinualAnimationGroup):
|
|
|
|
CONFIG = {
|
2017-08-25 17:56:55 -07:00
|
|
|
"wave_number" : 1,
|
2017-08-24 23:12:25 -07:00
|
|
|
"frequency" : 0.25,
|
|
|
|
"n_vectors" : 40,
|
|
|
|
"propogation_direction" : RIGHT,
|
2017-08-30 13:16:08 -07:00
|
|
|
"start_point" : SPACE_WIDTH*LEFT + DOWN + OUT,
|
2017-08-24 23:12:25 -07:00
|
|
|
"length" : 2*SPACE_WIDTH,
|
|
|
|
"amplitude" : 1,
|
|
|
|
"rotation" : 0,
|
2017-08-27 23:52:28 -07:00
|
|
|
"A_vect" : [0, 0, 1],
|
|
|
|
"phi_vect" : [0, 0, 0],
|
2017-08-30 13:16:08 -07:00
|
|
|
"requires_start_up" : False,
|
2017-08-24 23:12:25 -07:00
|
|
|
}
|
|
|
|
def __init__(self, **kwargs):
|
|
|
|
digest_config(self, kwargs)
|
2017-08-28 10:52:49 -07:00
|
|
|
if not all(self.propogation_direction == RIGHT):
|
|
|
|
self.matrix_transform = np.dot(
|
|
|
|
z_to_vector(self.propogation_direction),
|
|
|
|
np.linalg.inv(z_to_vector(RIGHT)),
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
self.matrix_transform = None
|
2017-08-24 23:12:25 -07:00
|
|
|
|
|
|
|
vector_oscillations = []
|
|
|
|
self.E_vects = VGroup()
|
|
|
|
self.M_vects = VGroup()
|
|
|
|
|
2017-08-27 23:52:28 -07:00
|
|
|
self.A_vect = np.array(self.A_vect)/np.linalg.norm(self.A_vect)
|
|
|
|
self.A_vect *= self.amplitude
|
2017-08-24 23:12:25 -07:00
|
|
|
|
|
|
|
for alpha in np.linspace(0, 1, self.n_vectors):
|
2017-08-27 23:52:28 -07:00
|
|
|
tail = interpolate(ORIGIN, self.length*RIGHT, alpha)
|
2017-08-25 17:56:55 -07:00
|
|
|
phase = -alpha*self.length*self.wave_number
|
2017-08-27 23:52:28 -07:00
|
|
|
kwargs = {
|
|
|
|
"phi_vect" : np.array(self.phi_vect) + phase,
|
|
|
|
"frequency" : self.frequency,
|
|
|
|
"tail" : np.array(tail),
|
|
|
|
}
|
2017-08-24 23:12:25 -07:00
|
|
|
E_ov = OscillatingVector(
|
2017-08-27 23:52:28 -07:00
|
|
|
Vector(
|
|
|
|
OUT, color = E_COLOR,
|
|
|
|
normal_vector = UP,
|
|
|
|
),
|
|
|
|
A_vect = self.A_vect,
|
|
|
|
**kwargs
|
2017-08-24 23:12:25 -07:00
|
|
|
)
|
|
|
|
M_ov = OscillatingVector(
|
2017-08-27 23:52:28 -07:00
|
|
|
Vector(
|
|
|
|
UP, color = M_COLOR,
|
|
|
|
normal_vector = OUT,
|
|
|
|
),
|
|
|
|
A_vect = rotate_vector(self.A_vect, np.pi/2, RIGHT),
|
|
|
|
**kwargs
|
2017-08-24 23:12:25 -07:00
|
|
|
)
|
|
|
|
vector_oscillations += [E_ov, M_ov]
|
|
|
|
self.E_vects.add(E_ov.vector)
|
|
|
|
self.M_vects.add(M_ov.vector)
|
|
|
|
ContinualAnimationGroup.__init__(self, *vector_oscillations)
|
|
|
|
|
|
|
|
def update_mobject(self, dt):
|
2017-08-30 13:16:08 -07:00
|
|
|
if self.requires_start_up:
|
|
|
|
n_wave_lengths = self.length / (2*np.pi*self.wave_number)
|
|
|
|
prop_time = n_wave_lengths/self.frequency
|
|
|
|
middle_alpha = interpolate(
|
|
|
|
0.4, 1.4,
|
|
|
|
self.external_time / prop_time
|
|
|
|
)
|
|
|
|
new_smooth = squish_rate_func(smooth, 0.4, 0.6)
|
|
|
|
|
|
|
|
ovs = self.continual_animations
|
|
|
|
for ov, alpha in zip(ovs, np.linspace(0, 1, len(ovs))):
|
|
|
|
epsilon = 0.0001
|
|
|
|
new_amplitude = np.clip(
|
|
|
|
new_smooth(middle_alpha - alpha), epsilon, 1
|
|
|
|
)
|
|
|
|
norm = np.linalg.norm(ov.A_vect)
|
|
|
|
if norm != 0:
|
|
|
|
ov.A_vect = new_amplitude * np.array(ov.A_vect) / norm
|
|
|
|
|
2017-08-24 23:12:25 -07:00
|
|
|
ContinualAnimationGroup.update_mobject(self, dt)
|
2017-08-27 23:52:28 -07:00
|
|
|
self.mobject.rotate(self.rotation, RIGHT)
|
2017-08-28 10:52:49 -07:00
|
|
|
if self.matrix_transform:
|
|
|
|
self.mobject.apply_matrix(self.matrix_transform)
|
2017-08-24 23:12:25 -07:00
|
|
|
self.mobject.shift(self.start_point)
|
|
|
|
|
|
|
|
class WavePacket(Animation):
|
|
|
|
CONFIG = {
|
|
|
|
"EMWave_config" : {
|
|
|
|
"wave_number" : 0,
|
|
|
|
"start_point" : SPACE_WIDTH*LEFT,
|
2017-08-27 23:52:28 -07:00
|
|
|
"phi_vect" : np.ones(3)*np.pi/4,
|
2017-08-24 23:12:25 -07:00
|
|
|
},
|
2017-08-25 17:56:55 -07:00
|
|
|
"em_wave" : None,
|
2017-08-24 23:12:25 -07:00
|
|
|
"run_time" : 4,
|
|
|
|
"rate_func" : None,
|
|
|
|
"packet_width" : 6,
|
|
|
|
"include_E_vects" : True,
|
|
|
|
"include_M_vects" : True,
|
|
|
|
"filter_distance" : SPACE_WIDTH,
|
|
|
|
"get_filtered" : False,
|
2017-08-25 17:56:55 -07:00
|
|
|
"remover" : True,
|
2017-08-24 23:12:25 -07:00
|
|
|
}
|
|
|
|
def __init__(self, **kwargs):
|
|
|
|
digest_config(self, kwargs)
|
2017-08-25 17:56:55 -07:00
|
|
|
em_wave = self.em_wave
|
|
|
|
if em_wave is None:
|
|
|
|
em_wave = EMWave(**self.EMWave_config)
|
|
|
|
em_wave.update(0)
|
|
|
|
self.em_wave = em_wave
|
2017-08-24 23:12:25 -07:00
|
|
|
|
|
|
|
self.vects = VGroup()
|
|
|
|
if self.include_E_vects:
|
|
|
|
self.vects.add(*em_wave.E_vects)
|
|
|
|
if self.include_M_vects:
|
|
|
|
self.vects.add(*em_wave.M_vects)
|
|
|
|
for vect in self.vects:
|
|
|
|
vect.save_state()
|
|
|
|
|
|
|
|
u = em_wave.propogation_direction
|
|
|
|
self.wave_packet_start, self.wave_packet_end = [
|
|
|
|
em_wave.start_point - u*self.packet_width/2,
|
|
|
|
em_wave.start_point + u*(em_wave.length + self.packet_width/2)
|
|
|
|
]
|
|
|
|
Animation.__init__(self, self.vects, **kwargs)
|
|
|
|
|
|
|
|
def update_mobject(self, alpha):
|
|
|
|
packet_center = interpolate(
|
|
|
|
self.wave_packet_start,
|
|
|
|
self.wave_packet_end,
|
|
|
|
alpha
|
|
|
|
)
|
|
|
|
em_wave = self.em_wave
|
|
|
|
for vect in self.vects:
|
|
|
|
tail = vect.get_start()
|
|
|
|
distance_from_packet = np.dot(
|
|
|
|
tail - packet_center,
|
|
|
|
em_wave.propogation_direction
|
|
|
|
)
|
2017-08-25 17:56:55 -07:00
|
|
|
A = em_wave.amplitude*self.E_func(distance_from_packet)
|
2017-08-24 23:12:25 -07:00
|
|
|
distance_from_start = np.linalg.norm(tail - em_wave.start_point)
|
|
|
|
if self.get_filtered and distance_from_start > self.filter_distance:
|
|
|
|
A = 0
|
|
|
|
vect.restore()
|
|
|
|
vect.scale(A/vect.get_length(), about_point = tail)
|
|
|
|
|
2017-08-25 17:56:55 -07:00
|
|
|
def E_func(self, x):
|
2017-08-27 23:52:28 -07:00
|
|
|
return np.sin(x)*np.exp(-0.25*x*x)
|
2017-08-24 23:12:25 -07:00
|
|
|
|
|
|
|
class FilterLabel(TexMobject):
|
|
|
|
def __init__(self, tex, degrees, **kwargs):
|
|
|
|
TexMobject.__init__(self, tex + " \\uparrow", **kwargs)
|
|
|
|
self[-1].rotate(-degrees * np.pi / 180)
|
|
|
|
|
|
|
|
class PolarizingFilter(Circle):
|
|
|
|
CONFIG = {
|
|
|
|
"stroke_color" : DARK_GREY,
|
|
|
|
"fill_color" : LIGHT_GREY,
|
|
|
|
"fill_opacity" : 0.5,
|
|
|
|
"label_tex" : None,
|
|
|
|
"filter_angle" : 0,
|
2017-08-25 17:56:55 -07:00
|
|
|
"include_arrow_label" : True,
|
2017-08-31 00:16:08 -07:00
|
|
|
"arrow_length" : 0.7,
|
2017-08-24 23:12:25 -07:00
|
|
|
}
|
|
|
|
def __init__(self, **kwargs):
|
|
|
|
Circle.__init__(self, **kwargs)
|
|
|
|
|
|
|
|
if self.label_tex:
|
|
|
|
self.label = TexMobject(self.label_tex)
|
2017-08-30 20:05:25 -07:00
|
|
|
self.label.next_to(self.get_top(), DOWN, MED_SMALL_BUFF)
|
2017-08-24 23:12:25 -07:00
|
|
|
self.add(self.label)
|
|
|
|
|
2017-08-25 17:56:55 -07:00
|
|
|
arrow = Arrow(
|
2017-08-30 20:05:25 -07:00
|
|
|
ORIGIN, self.arrow_length*UP,
|
2017-08-25 17:56:55 -07:00
|
|
|
color = WHITE,
|
|
|
|
buff = 0,
|
|
|
|
)
|
2017-08-24 23:12:25 -07:00
|
|
|
arrow.shift(self.get_top())
|
|
|
|
arrow.rotate(-self.filter_angle)
|
|
|
|
self.add(arrow)
|
|
|
|
self.arrow = arrow
|
2017-08-25 17:56:55 -07:00
|
|
|
shade_in_3d(self)
|
2017-08-24 23:12:25 -07:00
|
|
|
|
2017-08-25 17:56:55 -07:00
|
|
|
if self.include_arrow_label:
|
|
|
|
arrow_label = TexMobject(
|
|
|
|
"%.1f^\\circ"%(self.filter_angle*180/np.pi)
|
|
|
|
)
|
|
|
|
arrow_label.add_background_rectangle()
|
|
|
|
arrow_label.next_to(arrow.get_tip(), UP)
|
|
|
|
self.add(arrow_label)
|
|
|
|
self.arrow_label = arrow_label
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-08-30 13:16:08 -07:00
|
|
|
################
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-09-01 10:41:27 -07:00
|
|
|
|
|
|
|
class FilterScene(ThreeDScene):
|
|
|
|
CONFIG = {
|
|
|
|
"filter_x_coordinates" : [0],
|
|
|
|
"pol_filter_configs" : [{}],
|
|
|
|
"EMWave_config" : {
|
|
|
|
"start_point" : SPACE_WIDTH*LEFT + DOWN+OUT
|
|
|
|
},
|
2017-09-01 18:57:38 -07:00
|
|
|
"axes_config" : {},
|
2017-09-01 10:41:27 -07:00
|
|
|
"start_phi" : 0.8*np.pi/2,
|
|
|
|
"start_theta" : -0.6*np.pi,
|
|
|
|
"ambient_rotation_rate" : 0.01,
|
|
|
|
}
|
|
|
|
def setup(self):
|
2017-09-01 18:57:38 -07:00
|
|
|
self.axes = ThreeDAxes(**self.axes_config)
|
2017-09-01 10:41:27 -07:00
|
|
|
self.add(self.axes)
|
|
|
|
for x in range(len(self.filter_x_coordinates) - len(self.pol_filter_configs)):
|
|
|
|
self.pol_filter_configs.append({})
|
|
|
|
self.pol_filters = VGroup(*[
|
|
|
|
PolarizingFilter(**config)
|
|
|
|
for config in self.pol_filter_configs
|
|
|
|
])
|
|
|
|
self.pol_filters.rotate(np.pi/2, RIGHT)
|
|
|
|
self.pol_filters.rotate(-np.pi/2, OUT)
|
2017-09-06 20:18:19 -07:00
|
|
|
pol_filter_shift = np.array(self.EMWave_config["start_point"])
|
|
|
|
pol_filter_shift[0] = 0
|
|
|
|
self.pol_filters.shift(pol_filter_shift)
|
2017-09-01 10:41:27 -07:00
|
|
|
for x, pf in zip(self.filter_x_coordinates, self.pol_filters):
|
|
|
|
pf.shift(x*RIGHT)
|
|
|
|
self.add(self.pol_filters)
|
|
|
|
self.pol_filter = self.pol_filters[0]
|
|
|
|
|
|
|
|
self.set_camera_position(self.start_phi, self.start_theta)
|
|
|
|
if self.ambient_rotation_rate > 0:
|
|
|
|
self.begin_ambient_camera_rotation(self.ambient_rotation_rate)
|
|
|
|
|
|
|
|
def get_filter_absorbtion_animation(self, pol_filter, photon):
|
|
|
|
x = pol_filter.get_center()[0]
|
|
|
|
alpha = (x + SPACE_WIDTH) / (2*SPACE_WIDTH)
|
|
|
|
return ApplyMethod(
|
|
|
|
pol_filter.set_fill, RED,
|
|
|
|
run_time = photon.run_time,
|
|
|
|
rate_func = squish_rate_func(there_and_back, alpha - 0.1, alpha + 0.1)
|
|
|
|
)
|
|
|
|
|
|
|
|
class DirectionOfPolarizationScene(FilterScene):
|
|
|
|
CONFIG = {
|
|
|
|
"pol_filter_configs" : [{
|
|
|
|
"include_arrow_label" : False,
|
|
|
|
}],
|
|
|
|
"target_theta" : -0.97*np.pi,
|
|
|
|
"target_phi" : 0.9*np.pi/2,
|
|
|
|
"ambient_rotation_rate" : 0.005,
|
|
|
|
"apply_filter" : False,
|
|
|
|
}
|
|
|
|
def setup(self):
|
|
|
|
self.reference_line = Line(ORIGIN, RIGHT)
|
|
|
|
self.reference_line.set_stroke(width = 0)
|
|
|
|
self.em_wave = EMWave(**self.EMWave_config)
|
|
|
|
self.add(self.em_wave)
|
|
|
|
|
|
|
|
FilterScene.setup(self)
|
|
|
|
|
|
|
|
def change_polarization_direction(self, angle, **kwargs):
|
|
|
|
added_anims = kwargs.get("added_anims", [])
|
|
|
|
self.play(
|
|
|
|
ApplyMethod(
|
|
|
|
self.reference_line.rotate, angle,
|
|
|
|
**kwargs
|
|
|
|
),
|
|
|
|
*added_anims
|
|
|
|
)
|
|
|
|
|
2017-09-06 20:18:19 -07:00
|
|
|
def setup_rectangles(self):
|
|
|
|
rect1 = Rectangle(
|
|
|
|
height = 2*self.em_wave.amplitude,
|
|
|
|
width = SPACE_WIDTH + 0.25,
|
|
|
|
stroke_color = BLUE,
|
|
|
|
fill_color = BLUE,
|
|
|
|
fill_opacity = 0.2,
|
|
|
|
)
|
|
|
|
rect1.rotate(np.pi/2, RIGHT)
|
|
|
|
pf_copy = self.pol_filter.deepcopy()
|
|
|
|
pf_copy.remove(pf_copy.arrow)
|
|
|
|
center = pf_copy.get_center()
|
|
|
|
rect1.move_to(center, RIGHT)
|
|
|
|
rect2 = rect1.copy()
|
|
|
|
rect2.move_to(center, LEFT)
|
|
|
|
|
|
|
|
self.rectangles = VGroup(rect1, rect2)
|
|
|
|
|
2017-09-01 10:41:27 -07:00
|
|
|
def continual_update(self, *args, **kwargs):
|
|
|
|
reference_angle = self.reference_line.get_angle()
|
|
|
|
self.em_wave.rotation = reference_angle
|
|
|
|
FilterScene.continual_update(self, *args, **kwargs)
|
|
|
|
if self.apply_filter:
|
2017-09-06 20:18:19 -07:00
|
|
|
self.apply_filters()
|
|
|
|
self.update_rectangles()
|
2017-09-01 10:41:27 -07:00
|
|
|
|
2017-09-06 20:18:19 -07:00
|
|
|
def apply_filters(self):
|
|
|
|
vect_groups = [self.em_wave.E_vects, self.em_wave.M_vects]
|
|
|
|
filters = sorted(
|
|
|
|
self.pol_filters,
|
|
|
|
lambda pf1, pf2 : cmp(
|
|
|
|
pf1.get_center()[0],
|
|
|
|
pf2.get_center()[0],
|
|
|
|
)
|
|
|
|
)
|
|
|
|
for pol_filter in filters:
|
|
|
|
filter_x = pol_filter.arrow.get_center()[0]
|
|
|
|
for vect_group, angle in zip(vect_groups, [0, -np.pi/2]):
|
|
|
|
proj_vect = rotate_vector(
|
|
|
|
OUT, pol_filter.filter_angle + angle, RIGHT,
|
|
|
|
)
|
|
|
|
proj_matrix = np.array([RIGHT] + [
|
|
|
|
proj_vect*np.dot(proj_vect, basis)
|
|
|
|
for basis in UP, OUT
|
|
|
|
]).T
|
|
|
|
for vect in vect_group:
|
|
|
|
start, end = vect.get_start_and_end()
|
|
|
|
if start[0] > filter_x:
|
|
|
|
vect.apply_matrix(proj_matrix)
|
|
|
|
vect.shift(start - vect.get_start())
|
|
|
|
vect.set_tip_points(vect.tip)
|
|
|
|
vect.set_rectangular_stem_points()
|
|
|
|
|
|
|
|
def update_rectangles(self):
|
|
|
|
if self.rectangles not in self.mobjects:
|
|
|
|
return
|
|
|
|
|
|
|
|
r1, r2 = self.rectangles
|
|
|
|
|
|
|
|
target_angle = self.reference_line.get_angle()
|
|
|
|
anchors = r1.get_anchors()
|
|
|
|
vect = anchors[0] - anchors[3]
|
|
|
|
curr_angle = angle_of_vector([vect[2], -vect[1]])
|
|
|
|
r1.rotate_in_place(target_angle - curr_angle, RIGHT)
|
|
|
|
|
|
|
|
epsilon = 0.001
|
|
|
|
curr_depth = max(r2.get_depth(), epsilon)
|
|
|
|
target_depth = max(
|
|
|
|
2*self.em_wave.amplitude*abs(np.cos(target_angle)),
|
|
|
|
epsilon
|
|
|
|
)
|
|
|
|
r2.stretch_in_place(target_depth/curr_depth, 2)
|
2017-09-01 10:41:27 -07:00
|
|
|
|
|
|
|
################
|
|
|
|
|
2017-08-30 13:16:08 -07:00
|
|
|
class IntroduceElectricField(PiCreatureScene):
|
|
|
|
CONFIG = {
|
|
|
|
"vector_field_colors" : [BLUE_B, BLUE_D],
|
|
|
|
"max_vector_length" : 0.9,
|
|
|
|
}
|
2017-08-24 11:44:06 -07:00
|
|
|
def construct(self):
|
2017-08-30 13:16:08 -07:00
|
|
|
self.write_title()
|
|
|
|
self.draw_field()
|
|
|
|
self.add_particle()
|
|
|
|
self.let_particle_wander()
|
2017-08-24 23:12:25 -07:00
|
|
|
|
2017-08-30 13:16:08 -07:00
|
|
|
def write_title(self):
|
|
|
|
morty = self.pi_creature
|
|
|
|
|
|
|
|
title = TextMobject(
|
|
|
|
"Electro", "magnetic", " field",
|
|
|
|
arg_separator = ""
|
|
|
|
)
|
|
|
|
title.next_to(morty, UP+LEFT)
|
|
|
|
electric = TextMobject("Electric")
|
|
|
|
electric.next_to(title[-1], LEFT)
|
|
|
|
electric.highlight(BLUE)
|
|
|
|
|
|
|
|
title.save_state()
|
|
|
|
title.shift(DOWN)
|
|
|
|
title.fade(1)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
title.restore,
|
|
|
|
morty.change, "raise_right_hand",
|
|
|
|
)
|
|
|
|
self.play(
|
|
|
|
title[0].highlight, BLUE,
|
|
|
|
title[1].highlight, YELLOW,
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.play(
|
|
|
|
ShrinkToCenter(title[1]),
|
|
|
|
Transform(title[0], electric)
|
|
|
|
)
|
|
|
|
|
|
|
|
title.add_background_rectangle()
|
|
|
|
self.title = title
|
|
|
|
|
|
|
|
def draw_field(self):
|
|
|
|
morty = self.pi_creature
|
|
|
|
vector_field = self.get_vector_field()
|
|
|
|
self.play(
|
|
|
|
LaggedStart(
|
|
|
|
ShowCreation, vector_field,
|
|
|
|
run_time = 3
|
|
|
|
),
|
|
|
|
self.title.center,
|
|
|
|
self.title.scale, 1.5,
|
|
|
|
self.title.to_edge, UP,
|
|
|
|
morty.change, "happy", ORIGIN,
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
self.vector_field = vector_field
|
|
|
|
|
|
|
|
def add_particle(self):
|
|
|
|
morty = self.pi_creature
|
|
|
|
point = UP+LEFT + SMALL_BUFF*(UP+RIGHT)
|
|
|
|
particle = self.get_particle()
|
|
|
|
particle.move_to(point)
|
|
|
|
|
|
|
|
vector = self.get_vector(particle.get_center())
|
|
|
|
vector.highlight(RED)
|
|
|
|
vector.scale(1.5, about_point = point)
|
|
|
|
vector.shift(SMALL_BUFF*vector.get_vector())
|
|
|
|
force = TextMobject("Force")
|
|
|
|
force.next_to(ORIGIN, UP+RIGHT, SMALL_BUFF)
|
|
|
|
force.rotate(vector.get_angle())
|
|
|
|
force.shift(vector.get_start())
|
|
|
|
|
|
|
|
particle.save_state()
|
|
|
|
particle.move_to(morty.get_left() + 0.5*UP + 0.2*RIGHT)
|
|
|
|
particle.fade(1)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
particle.restore,
|
|
|
|
morty.change, "raise_right_hand",
|
|
|
|
)
|
|
|
|
self.play(morty.change, "thinking", particle)
|
|
|
|
self.play(
|
|
|
|
ShowCreation(vector),
|
|
|
|
Write(force, run_time = 1),
|
|
|
|
)
|
2017-08-27 23:52:28 -07:00
|
|
|
self.dither(2)
|
2017-08-24 23:12:25 -07:00
|
|
|
|
2017-08-30 13:16:08 -07:00
|
|
|
self.particle = particle
|
|
|
|
self.force_vector = VGroup(vector, force)
|
|
|
|
|
|
|
|
def let_particle_wander(self):
|
|
|
|
possible_points = [v.get_start() for v in self.vector_field]
|
|
|
|
points = random.sample(possible_points, 45)
|
|
|
|
points.append(3*UP+3*LEFT)
|
|
|
|
particles = VGroup(self.particle, *[
|
|
|
|
self.particle.copy().move_to(point)
|
|
|
|
for point in points
|
|
|
|
])
|
|
|
|
for particle in particles:
|
|
|
|
particle.velocity = np.zeros(3)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
FadeOut(self.force_vector),
|
|
|
|
LaggedStart(FadeIn, VGroup(*particles[1:]))
|
|
|
|
)
|
|
|
|
self.moving_particles = particles
|
|
|
|
self.add_foreground_mobjects(self.moving_particles, self.pi_creature)
|
|
|
|
self.always_continually_update = True
|
|
|
|
self.dither(10)
|
|
|
|
|
|
|
|
###
|
|
|
|
|
2017-09-01 10:41:27 -07:00
|
|
|
def continual_update(self, *args, **kwargs):
|
|
|
|
Scene.continual_update(self, *args, **kwargs)
|
2017-08-30 13:16:08 -07:00
|
|
|
if hasattr(self, "moving_particles"):
|
|
|
|
dt = self.frame_duration
|
|
|
|
for p in self.moving_particles:
|
|
|
|
vect = self.field_function(p.get_center())
|
|
|
|
p.velocity += vect*dt
|
|
|
|
p.shift(p.velocity*dt)
|
|
|
|
self.pi_creature.look_at(self.moving_particles[-1])
|
|
|
|
|
|
|
|
def get_particle(self):
|
|
|
|
particle = Circle(radius = 0.2)
|
|
|
|
particle.set_stroke(RED, 3)
|
|
|
|
particle.set_fill(RED, 0.5)
|
|
|
|
plus = TexMobject("+")
|
|
|
|
plus.scale(0.7)
|
|
|
|
plus.move_to(particle)
|
|
|
|
particle.add(plus)
|
|
|
|
return particle
|
|
|
|
|
|
|
|
def get_vector_field(self):
|
|
|
|
result = VGroup(*[
|
|
|
|
self.get_vector(point)
|
|
|
|
for x in np.arange(-9, 9)
|
|
|
|
for y in np.arange(-5, 5)
|
|
|
|
for point in [x*RIGHT + y*UP]
|
|
|
|
])
|
|
|
|
shading_list = list(result)
|
|
|
|
shading_list.sort(
|
|
|
|
lambda m1, m2 : cmp(m1.get_length(), m2.get_length())
|
|
|
|
)
|
|
|
|
VGroup(*shading_list).gradient_highlight(*self.vector_field_colors)
|
|
|
|
result.set_fill(opacity = 0.75)
|
|
|
|
result.sort_submobjects(np.linalg.norm)
|
|
|
|
|
|
|
|
return result
|
2017-08-24 23:12:25 -07:00
|
|
|
|
2017-08-30 13:16:08 -07:00
|
|
|
def get_vector(self, point):
|
|
|
|
return Vector(self.field_function(point)).shift(point)
|
2017-08-27 23:52:28 -07:00
|
|
|
|
2017-08-30 13:16:08 -07:00
|
|
|
def field_function(self, point):
|
|
|
|
x, y = point[:2]
|
|
|
|
result = y*RIGHT + np.sin(x)*UP
|
|
|
|
return self.normalized(result)
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-08-30 13:16:08 -07:00
|
|
|
def normalized(self, vector):
|
|
|
|
norm = np.linalg.norm(vector) or 1
|
|
|
|
target_length = self.max_vector_length * sigmoid(0.1*norm)
|
|
|
|
return target_length * vector/norm
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-08-30 13:16:08 -07:00
|
|
|
class IntroduceMagneticField(IntroduceElectricField, ThreeDScene):
|
|
|
|
CONFIG = {
|
|
|
|
"vector_field_colors" : [YELLOW_C, YELLOW_D]
|
|
|
|
}
|
|
|
|
def setup(self):
|
|
|
|
IntroduceElectricField.setup(self)
|
|
|
|
self.remove(self.pi_creature)
|
|
|
|
|
|
|
|
def construct(self):
|
|
|
|
self.set_camera_position(0.1, -np.pi/2)
|
|
|
|
self.add_title()
|
|
|
|
self.add_vector_field()
|
|
|
|
self.introduce_moving_charge()
|
|
|
|
self.show_force()
|
|
|
|
# self.many_charges()
|
|
|
|
|
|
|
|
def add_title(self):
|
|
|
|
title = TextMobject("Magnetic", "field")
|
|
|
|
title[0].highlight(YELLOW)
|
|
|
|
title.scale(1.5)
|
|
|
|
title.to_edge(UP)
|
|
|
|
title.add_background_rectangle()
|
|
|
|
|
|
|
|
self.add(title)
|
|
|
|
self.title = title
|
|
|
|
|
|
|
|
def add_vector_field(self):
|
|
|
|
vector_field = self.get_vector_field()
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
LaggedStart(ShowCreation, vector_field, run_time = 3),
|
|
|
|
Animation(self.title)
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
def introduce_moving_charge(self):
|
|
|
|
point = 3*RIGHT + UP
|
|
|
|
particle = self.get_particle()
|
|
|
|
particle.move_to(point)
|
|
|
|
|
|
|
|
velocity = Vector(2*RIGHT).shift(particle.get_right())
|
|
|
|
velocity.highlight(WHITE)
|
|
|
|
velocity_word = TextMobject("Velocity")
|
|
|
|
velocity_word.highlight(velocity.get_color())
|
|
|
|
velocity_word.add_background_rectangle()
|
|
|
|
velocity_word.next_to(velocity, UP, 0, LEFT)
|
|
|
|
|
|
|
|
M_vect = self.get_vector(point)
|
|
|
|
M_vect.highlight(YELLOW)
|
|
|
|
M_vect.shift(SMALL_BUFF*M_vect.get_vector())
|
|
|
|
|
|
|
|
particle.save_state()
|
|
|
|
particle.shift(2*SPACE_WIDTH*LEFT)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
particle.restore,
|
|
|
|
run_time = 2,
|
|
|
|
rate_func = None,
|
|
|
|
)
|
|
|
|
self.add(velocity)
|
|
|
|
self.play(Write(velocity_word, run_time = 0.5))
|
|
|
|
# self.play(ShowCreation(M_vect))
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
self.particle = particle
|
|
|
|
|
|
|
|
def show_force(self):
|
|
|
|
point = self.particle.get_center()
|
|
|
|
F_vect = Vector(
|
|
|
|
3*np.cross(self.field_function(point), RIGHT),
|
|
|
|
color = GREEN
|
|
|
|
)
|
|
|
|
F_vect.shift(point)
|
|
|
|
F_word = TextMobject("Force")
|
|
|
|
F_word.rotate(np.pi/2, RIGHT)
|
|
|
|
F_word.next_to(F_vect, OUT)
|
|
|
|
F_word.highlight(F_vect.get_color())
|
|
|
|
F_eq = TexMobject(
|
|
|
|
"=","q", "\\textbf{v}", "\\times", "\\textbf{B}"
|
|
|
|
)
|
|
|
|
F_eq.highlight_by_tex_to_color_map({
|
|
|
|
"q" : RED,
|
|
|
|
"B" : YELLOW,
|
|
|
|
})
|
|
|
|
F_eq.rotate(np.pi/2, RIGHT)
|
|
|
|
F_eq.next_to(F_word, RIGHT)
|
|
|
|
|
|
|
|
|
|
|
|
self.move_camera(0.8*np.pi/2, -0.55*np.pi)
|
|
|
|
self.begin_ambient_camera_rotation()
|
|
|
|
self.play(ShowCreation(F_vect))
|
|
|
|
self.play(Write(F_word))
|
|
|
|
self.dither()
|
|
|
|
self.play(Write(F_eq))
|
|
|
|
self.dither(8)
|
|
|
|
|
|
|
|
def many_charges(self):
|
|
|
|
charges = VGroup()
|
|
|
|
for y in range(2, 3):
|
|
|
|
charge = self.get_particle()
|
|
|
|
charge.move_to(3*LEFT + y*UP)
|
|
|
|
charge.velocity = (2*RIGHT).astype('float')
|
|
|
|
charges.add(charge)
|
|
|
|
|
|
|
|
self.revert_to_original_skipping_status()
|
|
|
|
self.add_foreground_mobjects(*charges)
|
|
|
|
self.moving_particles = charges
|
|
|
|
self.dither(5)
|
|
|
|
|
|
|
|
|
|
|
|
###
|
|
|
|
|
2017-09-01 10:41:27 -07:00
|
|
|
def continual_update(self, *args, **kwargs):
|
|
|
|
Scene.continual_update(self, *args, **kwargs)
|
2017-08-30 13:16:08 -07:00
|
|
|
if hasattr(self, "moving_particles"):
|
|
|
|
dt = self.frame_duration
|
|
|
|
for p in self.moving_particles:
|
|
|
|
M_vect = self.field_function(p.get_center())
|
|
|
|
F_vect = 3*np.cross(p.velocity, M_vect)
|
|
|
|
p.velocity += F_vect*dt
|
|
|
|
p.shift(p.velocity*dt)
|
|
|
|
|
|
|
|
def field_function(self, point):
|
|
|
|
x, y = point[:2]
|
|
|
|
y += 0.5
|
|
|
|
gauss = lambda r : np.exp(-0.5*r**2)
|
|
|
|
result = (y**2 - 1)*RIGHT + x*(gauss(y+2) - gauss(y-2))*UP
|
|
|
|
return self.normalized(result)
|
|
|
|
|
|
|
|
class CurlRelationBetweenFields(ThreeDScene):
|
|
|
|
def construct(self):
|
|
|
|
self.add_axes()
|
|
|
|
self.loop_in_E()
|
|
|
|
self.loop_in_M()
|
|
|
|
self.second_loop_in_E()
|
|
|
|
|
|
|
|
def add_axes(self):
|
|
|
|
self.add(ThreeDAxes(x_axis_radius = SPACE_WIDTH))
|
|
|
|
|
|
|
|
def loop_in_E(self):
|
|
|
|
E_vects = VGroup(*[
|
|
|
|
Vector(0.5*rotate_vector(vect, np.pi/2)).shift(vect)
|
|
|
|
for vect in compass_directions(8)
|
|
|
|
])
|
|
|
|
E_vects.highlight(E_COLOR)
|
|
|
|
point = 1.2*RIGHT + 2*UP + OUT
|
|
|
|
E_vects.shift(point)
|
|
|
|
|
|
|
|
M_vect = Vector(
|
|
|
|
IN,
|
|
|
|
normal_vector = DOWN,
|
|
|
|
color = M_COLOR
|
|
|
|
)
|
|
|
|
M_vect.shift(point)
|
|
|
|
M_vect.save_state()
|
|
|
|
M_vect.scale(0.01, about_point = M_vect.get_start())
|
|
|
|
|
|
|
|
self.play(ShowCreation(E_vects, run_time = 2))
|
|
|
|
self.dither()
|
|
|
|
self.move_camera(0.8*np.pi/2, -0.45*np.pi)
|
|
|
|
self.begin_ambient_camera_rotation()
|
|
|
|
self.play(M_vect.restore, run_time = 3, rate_func = None)
|
|
|
|
self.dither(3)
|
|
|
|
|
|
|
|
self.E_vects = E_vects
|
|
|
|
self.E_circle_center = point
|
|
|
|
self.M_vect = M_vect
|
|
|
|
|
|
|
|
def loop_in_M(self):
|
|
|
|
M_vects = VGroup(*[
|
|
|
|
Vector(
|
|
|
|
rotate_vector(vect, np.pi/2),
|
|
|
|
normal_vector = IN,
|
|
|
|
color = M_COLOR
|
|
|
|
).shift(vect)
|
|
|
|
for vect in compass_directions(8, LEFT)[1:]
|
|
|
|
])
|
|
|
|
M_vects.rotate(np.pi/2, RIGHT)
|
|
|
|
new_point = self.E_circle_center + RIGHT
|
|
|
|
M_vects.shift(new_point)
|
|
|
|
|
|
|
|
E_vect = self.E_vects[0]
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
ShowCreation(M_vects, run_time = 2),
|
|
|
|
*map(FadeOut, self.E_vects[1:])
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.play(
|
|
|
|
E_vect.rotate, np.pi, RIGHT, [], new_point,
|
|
|
|
E_vect.scale_about_point, 3, new_point,
|
|
|
|
run_time = 4,
|
|
|
|
rate_func = None,
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
self.M_circle_center = new_point
|
|
|
|
M_vects.add(self.M_vect)
|
|
|
|
self.M_vects = M_vects
|
|
|
|
self.E_vect = E_vect
|
|
|
|
|
|
|
|
def second_loop_in_E(self):
|
|
|
|
E_vects = VGroup(*[
|
|
|
|
Vector(1.5*rotate_vector(vect, np.pi/2)).shift(vect)
|
|
|
|
for vect in compass_directions(8, LEFT)[1:]
|
|
|
|
])
|
|
|
|
E_vects.highlight(E_COLOR)
|
|
|
|
point = self.M_circle_center + RIGHT
|
|
|
|
E_vects.shift(point)
|
|
|
|
|
|
|
|
M_vect = self.M_vects[3]
|
|
|
|
self.M_vects.remove(M_vect)
|
|
|
|
|
|
|
|
self.play(FadeOut(self.M_vects))
|
|
|
|
self.play(ShowCreation(E_vects), Animation(M_vect))
|
|
|
|
self.play(
|
|
|
|
M_vect.rotate, np.pi, RIGHT, [], point,
|
|
|
|
run_time = 5,
|
|
|
|
rate_func = None,
|
|
|
|
)
|
|
|
|
self.dither(3)
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-08-30 13:16:08 -07:00
|
|
|
class WriteCurlEquations(Scene):
|
|
|
|
def construct(self):
|
|
|
|
eq1 = TexMobject(
|
|
|
|
"\\nabla \\times", "\\textbf{E}", "=",
|
|
|
|
"-\\frac{1}{c}",
|
|
|
|
"\\frac{\\partial \\textbf{B}}{\\partial t}"
|
|
|
|
)
|
|
|
|
eq2 = TexMobject(
|
|
|
|
"\\nabla \\times", "\\textbf{B}", "=^*",
|
|
|
|
"\\frac{1}{c}",
|
|
|
|
"\\frac{\\partial \\textbf{E}}{\\partial t}"
|
|
|
|
)
|
|
|
|
footnote = TextMobject("*Ignoring currents")
|
|
|
|
footnote.scale(0.7)
|
|
|
|
eqs = VGroup(eq1, eq2, footnote)
|
|
|
|
eqs.arrange_submobjects(DOWN, buff = LARGE_BUFF)
|
|
|
|
eqs.scale_to_fit_height(2*SPACE_HEIGHT - 1)
|
|
|
|
for eq in eqs:
|
|
|
|
eq.highlight_by_tex_to_color_map({
|
|
|
|
"E" : E_COLOR,
|
|
|
|
"B" : M_COLOR,
|
|
|
|
})
|
|
|
|
|
|
|
|
self.play(Write(eq1, run_time = 2))
|
|
|
|
self.dither(3)
|
|
|
|
self.play(Write(eq2, run_time = 2))
|
|
|
|
self.play(FadeIn(footnote))
|
|
|
|
self.dither(3)
|
|
|
|
|
|
|
|
class IntroduceEMWave(ThreeDScene):
|
|
|
|
CONFIG = {
|
|
|
|
"EMWave_config" : {
|
|
|
|
"requires_start_up" : True
|
|
|
|
}
|
|
|
|
}
|
|
|
|
def setup(self):
|
|
|
|
self.axes = ThreeDAxes()
|
|
|
|
self.add(self.axes)
|
|
|
|
self.em_wave = EMWave(**self.EMWave_config)
|
|
|
|
self.add(self.em_wave)
|
|
|
|
self.set_camera_position(0.8*np.pi/2, -0.7*np.pi)
|
|
|
|
self.begin_ambient_camera_rotation()
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-08-30 13:16:08 -07:00
|
|
|
def construct(self):
|
|
|
|
words = TextMobject(
|
|
|
|
"Electro", "magnetic", " radiation",
|
|
|
|
arg_separator = ""
|
|
|
|
)
|
|
|
|
words.highlight_by_tex_to_color_map({
|
|
|
|
"Electro" : E_COLOR,
|
|
|
|
"magnetic" : M_COLOR,
|
|
|
|
})
|
|
|
|
words.next_to(ORIGIN, LEFT, MED_LARGE_BUFF)
|
|
|
|
words.to_edge(UP)
|
|
|
|
words.rotate(np.pi/2, RIGHT)
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-08-30 13:16:08 -07:00
|
|
|
self.dither(7)
|
|
|
|
self.play(Write(words, run_time = 2))
|
|
|
|
self.dither(20)
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-08-30 13:16:08 -07:00
|
|
|
#####
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-08-30 13:16:08 -07:00
|
|
|
class SimpleEMWave(IntroduceEMWave):
|
|
|
|
def construct(self):
|
|
|
|
self.dither(30)
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-08-30 13:16:08 -07:00
|
|
|
class ListRelevantWaveIdeas(TeacherStudentsScene):
|
|
|
|
def construct(self):
|
|
|
|
title = TextMobject("Wave","topics")
|
|
|
|
title.to_corner(UP + LEFT, LARGE_BUFF)
|
|
|
|
title.highlight(BLUE)
|
|
|
|
h_line = Line(title.get_left(), title.get_right())
|
|
|
|
h_line.next_to(title, DOWN, SMALL_BUFF)
|
|
|
|
|
|
|
|
topics = VGroup(*map(TextMobject, [
|
|
|
|
"- Superposition",
|
|
|
|
"- Amplitudes",
|
2017-08-31 23:20:16 -07:00
|
|
|
"- How phase influences addition",
|
2017-08-30 13:16:08 -07:00
|
|
|
]))
|
|
|
|
topics.scale(0.8)
|
|
|
|
topics.arrange_submobjects(DOWN, aligned_edge = LEFT)
|
|
|
|
topics.next_to(h_line, DOWN, aligned_edge = LEFT)
|
|
|
|
|
|
|
|
quantum = TextMobject("Quantum")
|
|
|
|
quantum.highlight(GREEN)
|
|
|
|
quantum.move_to(title[0], LEFT)
|
|
|
|
|
|
|
|
wave_point = self.teacher.get_corner(UP+LEFT) + 2*UP
|
|
|
|
self.play(
|
|
|
|
Animation(VectorizedPoint(wave_point)),
|
|
|
|
self.teacher.change, "raise_right_hand"
|
|
|
|
)
|
|
|
|
self.dither(2)
|
|
|
|
self.play(
|
|
|
|
Write(title, run_time = 2),
|
|
|
|
ShowCreation(h_line)
|
|
|
|
)
|
|
|
|
self.change_student_modes(
|
|
|
|
*["pondering"]*3,
|
|
|
|
added_anims = [LaggedStart(
|
|
|
|
FadeIn, topics,
|
|
|
|
run_time = 3
|
|
|
|
)],
|
|
|
|
look_at_arg = title
|
|
|
|
)
|
|
|
|
self.play(
|
|
|
|
Animation(title),
|
|
|
|
self.teacher.change, "happy"
|
|
|
|
)
|
|
|
|
self.play(
|
|
|
|
title[0].next_to, quantum.copy(), UP, MED_SMALL_BUFF, LEFT,
|
|
|
|
title[0].fade, 0.5,
|
|
|
|
title[1].next_to, quantum.copy(), RIGHT, 2*SMALL_BUFF,
|
|
|
|
Write(quantum),
|
|
|
|
)
|
|
|
|
self.dither(5)
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-08-30 18:33:55 -07:00
|
|
|
class DirectWaveOutOfScreen(IntroduceEMWave):
|
|
|
|
CONFIG = {
|
|
|
|
"EMWave_config" : {
|
|
|
|
"requires_start_up" : False,
|
|
|
|
"amplitude" : 2,
|
|
|
|
"start_point" : SPACE_WIDTH*LEFT,
|
|
|
|
"A_vect" : [0, 1, 0],
|
|
|
|
"start_up_time" : 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
def setup(self):
|
|
|
|
IntroduceEMWave.setup(self)
|
|
|
|
self.remove(self.axes)
|
|
|
|
for ov in self.em_wave.continual_animations:
|
|
|
|
ov.vector.normal_vector = RIGHT
|
|
|
|
self.set_camera_position(0.9*np.pi/2, -0.3*np.pi)
|
|
|
|
|
|
|
|
def construct(self):
|
|
|
|
self.move_into_position()
|
2017-09-06 20:18:19 -07:00
|
|
|
self.fade_M_vects()
|
|
|
|
self.fade_all_but_last_E_vects()
|
2017-08-30 18:33:55 -07:00
|
|
|
|
|
|
|
def move_into_position(self):
|
|
|
|
self.dither(2)
|
|
|
|
self.continual_update()
|
|
|
|
faded_vectors = VGroup(*[
|
|
|
|
ov.vector
|
|
|
|
for ov in self.em_wave.continual_animations[:-2]
|
|
|
|
])
|
|
|
|
self.move_camera(
|
|
|
|
0.99*np.pi/2, -0.01,
|
|
|
|
run_time = 2,
|
|
|
|
added_anims = [faded_vectors.set_fill, None, 0.5]
|
|
|
|
)
|
|
|
|
self.stop_ambient_camera_rotation()
|
|
|
|
self.move_camera(
|
|
|
|
np.pi/2, 0,
|
|
|
|
added_anims = [faded_vectors.set_fill, None, 0.05],
|
|
|
|
run_time = 2,
|
|
|
|
)
|
2017-09-06 20:18:19 -07:00
|
|
|
|
|
|
|
def fade_M_vects(self):
|
2017-08-30 18:33:55 -07:00
|
|
|
self.play(
|
|
|
|
self.em_wave.M_vects.set_fill, None, 0
|
|
|
|
)
|
|
|
|
self.dither(2)
|
2017-09-06 20:18:19 -07:00
|
|
|
|
|
|
|
def fade_all_but_last_E_vects(self):
|
2017-08-30 18:33:55 -07:00
|
|
|
self.play(faded_vectors.set_fill, None, 0)
|
|
|
|
self.dither(4)
|
|
|
|
|
|
|
|
class ShowVectorEquation(Scene):
|
2017-08-31 23:20:16 -07:00
|
|
|
CONFIG = {
|
|
|
|
"f_color" : RED,
|
|
|
|
"phi_color" : MAROON_B,
|
|
|
|
"A_color" : GREEN,
|
|
|
|
}
|
2017-08-30 18:33:55 -07:00
|
|
|
def construct(self):
|
|
|
|
self.add_vector()
|
|
|
|
self.add_plane()
|
|
|
|
self.write_horizontally_polarized()
|
|
|
|
self.write_components()
|
|
|
|
self.show_graph()
|
|
|
|
self.add_phi()
|
|
|
|
self.add_amplitude()
|
|
|
|
self.add_kets()
|
|
|
|
self.switch_to_vertically_polarized_light()
|
|
|
|
|
|
|
|
def add_vector(self):
|
|
|
|
self.vector = Vector(2*RIGHT, color = E_COLOR)
|
|
|
|
self.oscillating_vector = OscillatingVector(
|
|
|
|
self.vector,
|
|
|
|
A_vect = [2, 0, 0],
|
|
|
|
frequency = 0.25,
|
|
|
|
)
|
|
|
|
self.add(self.oscillating_vector)
|
|
|
|
self.dither(3)
|
|
|
|
|
|
|
|
def add_plane(self):
|
2017-08-31 23:20:16 -07:00
|
|
|
xy_plane = NumberPlane(
|
|
|
|
axes_color = LIGHT_GREY,
|
|
|
|
color = DARK_GREY,
|
|
|
|
secondary_color = DARK_GREY,
|
|
|
|
x_unit_size = 2,
|
|
|
|
y_unit_size = 2,
|
|
|
|
)
|
|
|
|
xy_plane.add_coordinates()
|
|
|
|
xy_plane.add(xy_plane.get_axis_labels())
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
Write(xy_plane),
|
|
|
|
Animation(self.vector)
|
|
|
|
)
|
|
|
|
self.dither(2)
|
2017-09-06 20:18:19 -07:00
|
|
|
self.xy_plane = xy_plane
|
2017-08-30 18:33:55 -07:00
|
|
|
|
|
|
|
def write_horizontally_polarized(self):
|
2017-09-01 10:41:27 -07:00
|
|
|
words = TextMobject(
|
|
|
|
"``", "Horizontally", " polarized", "''",
|
|
|
|
arg_separator = ""
|
|
|
|
)
|
2017-08-31 23:20:16 -07:00
|
|
|
words.next_to(ORIGIN, LEFT)
|
|
|
|
words.to_edge(UP)
|
|
|
|
words.add_background_rectangle()
|
|
|
|
|
|
|
|
self.play(Write(words, run_time = 3))
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
self.horizontally_polarized_words = words
|
2017-08-30 18:33:55 -07:00
|
|
|
|
|
|
|
def write_components(self):
|
2017-08-31 23:20:16 -07:00
|
|
|
x, y = components = VGroup(
|
|
|
|
TexMobject("\\cos(", "2\\pi", "f_x", "t", "+ ", "\\phi_x", ")"),
|
2017-09-01 10:41:27 -07:00
|
|
|
TexMobject("0", "")
|
2017-08-31 23:20:16 -07:00
|
|
|
)
|
|
|
|
components.arrange_submobjects(DOWN)
|
|
|
|
lb, rb = brackets = TexMobject("[]")
|
|
|
|
brackets.scale_to_fit_height(components.get_height() + SMALL_BUFF)
|
|
|
|
lb.next_to(components, LEFT, buff = 0.3)
|
|
|
|
rb.next_to(components, RIGHT, buff = 0.3)
|
|
|
|
E, equals = E_equals = TexMobject(
|
|
|
|
"\\vec{\\textbf{E}}", "="
|
|
|
|
)
|
|
|
|
E.highlight(E_COLOR)
|
|
|
|
E_equals.next_to(brackets, LEFT)
|
|
|
|
E_equals.add_background_rectangle()
|
|
|
|
brackets.add_background_rectangle()
|
|
|
|
group = VGroup(E_equals, brackets, components)
|
|
|
|
group.next_to(
|
|
|
|
self.horizontally_polarized_words,
|
|
|
|
DOWN, MED_LARGE_BUFF, RIGHT
|
|
|
|
)
|
|
|
|
|
|
|
|
x_without_phi = TexMobject("\\cos(", "2\\pi", "f_x", "t", ")")
|
|
|
|
x_without_phi.move_to(x)
|
|
|
|
for mob in x, x_without_phi:
|
|
|
|
mob.highlight_by_tex_to_color_map({
|
|
|
|
"f_x" : self.f_color,
|
|
|
|
"phi_x" : self.phi_color,
|
|
|
|
})
|
|
|
|
|
|
|
|
def update_brace(brace):
|
|
|
|
brace.stretch_to_fit_width(
|
|
|
|
max(self.vector.get_width(), 0.001)
|
|
|
|
)
|
|
|
|
brace.next_to(self.vector.get_center(), DOWN, SMALL_BUFF)
|
|
|
|
return brace
|
|
|
|
moving_brace = ContinualUpdateFromFunc(
|
|
|
|
Brace(Line(LEFT, RIGHT), DOWN), update_brace
|
|
|
|
)
|
|
|
|
moving_x_without_phi = ContinualUpdateFromFunc(
|
|
|
|
x_without_phi.copy().add_background_rectangle(),
|
|
|
|
lambda m : m.next_to(moving_brace.mobject, DOWN, SMALL_BUFF)
|
|
|
|
)
|
|
|
|
|
|
|
|
self.play(Write(E_equals), Write(brackets))
|
|
|
|
y.save_state()
|
|
|
|
y.move_to(self.horizontally_polarized_words)
|
|
|
|
y.set_fill(opacity = 0)
|
|
|
|
self.play(y.restore)
|
|
|
|
self.dither()
|
|
|
|
self.add(moving_brace, moving_x_without_phi)
|
|
|
|
self.play(
|
|
|
|
FadeIn(moving_brace.mobject),
|
|
|
|
FadeIn(x_without_phi),
|
|
|
|
FadeIn(moving_x_without_phi.mobject),
|
|
|
|
submobject_mode = "lagged_start",
|
|
|
|
run_time = 2,
|
|
|
|
)
|
|
|
|
self.dither(3)
|
|
|
|
self.play(
|
|
|
|
FadeOut(moving_brace.mobject),
|
|
|
|
FadeOut(moving_x_without_phi.mobject),
|
|
|
|
)
|
|
|
|
self.remove(moving_brace, moving_x_without_phi)
|
|
|
|
|
|
|
|
self.E_equals = E_equals
|
|
|
|
self.brackets = brackets
|
|
|
|
self.x_without_phi = x_without_phi
|
|
|
|
self.components = components
|
2017-08-30 18:33:55 -07:00
|
|
|
|
|
|
|
def show_graph(self):
|
2017-08-31 23:20:16 -07:00
|
|
|
axes = Axes(
|
|
|
|
x_min = -0.5,
|
|
|
|
x_max = 5.2,
|
|
|
|
y_min = -1.5,
|
|
|
|
y_max = 1.5,
|
|
|
|
)
|
|
|
|
axes.x_axis.add_numbers(*range(1, 6))
|
|
|
|
t = TexMobject("t")
|
|
|
|
t.next_to(axes.x_axis, UP, SMALL_BUFF, RIGHT)
|
|
|
|
cos = self.x_without_phi.copy()
|
|
|
|
cos.next_to(axes.y_axis, RIGHT, SMALL_BUFF, UP)
|
|
|
|
cos_arg = VGroup(*cos[1:-1])
|
|
|
|
fx_equals_1 = TexMobject("f_x", "= 1")
|
|
|
|
fx_equals_fourth = TexMobject("f_x", "= 0.25")
|
|
|
|
fx_group = VGroup(fx_equals_1, fx_equals_fourth)
|
|
|
|
for fx in fx_group:
|
|
|
|
fx[0].highlight(self.f_color)
|
|
|
|
fx.move_to(axes, UP+RIGHT)
|
|
|
|
high_f_graph, low_f_graph = graphs = VGroup(*[
|
|
|
|
FunctionGraph(
|
|
|
|
lambda x : np.cos(2*np.pi*f*x),
|
|
|
|
color = E_COLOR,
|
|
|
|
x_min = 0,
|
|
|
|
x_max = 4/f,
|
|
|
|
num_steps = 20/f,
|
|
|
|
)
|
|
|
|
for f in 1, 0.25,
|
|
|
|
])
|
|
|
|
|
|
|
|
group = VGroup(axes, t, cos, high_f_graph, *fx_group)
|
|
|
|
rect = SurroundingRectangle(
|
|
|
|
group,
|
|
|
|
buff = MED_LARGE_BUFF,
|
|
|
|
stroke_color = WHITE,
|
|
|
|
stroke_width = 3,
|
|
|
|
fill_color = BLACK,
|
|
|
|
fill_opacity = 0.9
|
|
|
|
)
|
|
|
|
group.add_to_back(rect)
|
|
|
|
group.scale(0.8)
|
|
|
|
group.to_corner(UP+RIGHT, buff = -SMALL_BUFF)
|
|
|
|
group.remove(*it.chain(fx_group, graphs))
|
|
|
|
low_f_graph.scale(0.8)
|
|
|
|
low_f_graph.move_to(high_f_graph, LEFT)
|
|
|
|
|
|
|
|
cos_arg_rect = SurroundingRectangle(cos_arg)
|
|
|
|
|
|
|
|
new_ov = OscillatingVector(
|
|
|
|
Vector(RIGHT, color = E_COLOR),
|
|
|
|
A_vect = [2, 0, 0],
|
|
|
|
frequency = 1,
|
|
|
|
start_up_time = 0,
|
|
|
|
)
|
|
|
|
|
|
|
|
self.play(FadeIn(group))
|
|
|
|
self.play(
|
|
|
|
ReplacementTransform(
|
|
|
|
self.components[0].get_part_by_tex("f_x").copy(),
|
|
|
|
fx_equals_1
|
|
|
|
),
|
|
|
|
)
|
|
|
|
self.dither(4 - (self.oscillating_vector.internal_time%4))
|
|
|
|
self.remove(self.oscillating_vector)
|
|
|
|
self.add(new_ov)
|
|
|
|
self.play(ShowCreation(
|
|
|
|
high_f_graph, run_time = 4,
|
|
|
|
rate_func = None,
|
|
|
|
))
|
|
|
|
self.dither()
|
|
|
|
self.play(FadeOut(new_ov.vector))
|
|
|
|
self.remove(new_ov)
|
|
|
|
self.add(self.oscillating_vector)
|
|
|
|
self.play(
|
|
|
|
ReplacementTransform(*fx_group),
|
|
|
|
ReplacementTransform(*graphs),
|
|
|
|
FadeOut(new_ov.vector),
|
|
|
|
FadeIn(self.vector)
|
|
|
|
)
|
|
|
|
self.dither(4)
|
|
|
|
self.play(ShowCreation(cos_arg_rect))
|
|
|
|
self.play(FadeOut(cos_arg_rect))
|
|
|
|
self.dither(5)
|
|
|
|
|
|
|
|
self.corner_group = group
|
|
|
|
self.fx_equals_fourth = fx_equals_fourth
|
|
|
|
self.corner_cos = cos
|
|
|
|
self.low_f_graph = low_f_graph
|
|
|
|
self.graph_axes = axes
|
2017-08-30 18:33:55 -07:00
|
|
|
|
|
|
|
def add_phi(self):
|
2017-08-31 23:20:16 -07:00
|
|
|
corner_cos = self.corner_cos
|
|
|
|
corner_phi = TexMobject("+", "\\phi_x")
|
|
|
|
corner_phi.highlight_by_tex("phi", self.phi_color)
|
|
|
|
corner_phi.scale(0.8)
|
|
|
|
corner_phi.next_to(corner_cos[-2], RIGHT, SMALL_BUFF)
|
|
|
|
|
|
|
|
x, y = self.components
|
|
|
|
x_without_phi = self.x_without_phi
|
|
|
|
|
|
|
|
words = TextMobject("``Phase shift''")
|
|
|
|
words.next_to(ORIGIN, UP+LEFT)
|
|
|
|
words.highlight(self.phi_color)
|
|
|
|
words.add_background_rectangle()
|
|
|
|
arrow = Arrow(words.get_top(), x[-2])
|
|
|
|
arrow.highlight(WHITE)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
ReplacementTransform(
|
|
|
|
VGroup(*x_without_phi[:-1]),
|
|
|
|
VGroup(*x[:-3]),
|
|
|
|
),
|
|
|
|
ReplacementTransform(x_without_phi[-1], x[-1]),
|
|
|
|
Write(VGroup(*x[-3:-1])),
|
|
|
|
corner_cos[-1].next_to, corner_phi.copy(), RIGHT, SMALL_BUFF,
|
|
|
|
Write(corner_phi),
|
|
|
|
FadeOut(self.fx_equals_fourth),
|
|
|
|
)
|
|
|
|
self.play(self.low_f_graph.shift, MED_LARGE_BUFF*LEFT)
|
|
|
|
self.play(
|
|
|
|
Write(words, run_time = 1),
|
|
|
|
ShowCreation(arrow)
|
|
|
|
)
|
|
|
|
self.dither(3)
|
|
|
|
self.play(*map(FadeOut, [words, arrow]))
|
|
|
|
|
|
|
|
self.corner_cos.add(corner_phi)
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-08-30 18:33:55 -07:00
|
|
|
def add_amplitude(self):
|
2017-08-31 23:20:16 -07:00
|
|
|
x, y = self.components
|
|
|
|
corner_cos = self.corner_cos
|
|
|
|
graph = self.low_f_graph
|
|
|
|
graph_y_axis = self.graph_axes.y_axis
|
|
|
|
|
|
|
|
A = TexMobject("A_x")
|
|
|
|
A.highlight(self.A_color)
|
|
|
|
A.move_to(x.get_left())
|
|
|
|
corner_A = A.copy()
|
|
|
|
corner_A.scale(0.8)
|
|
|
|
corner_A.move_to(corner_cos, LEFT)
|
|
|
|
|
|
|
|
h_brace = Brace(Line(ORIGIN, 2*RIGHT), UP)
|
|
|
|
v_brace = Brace(Line(
|
|
|
|
graph_y_axis.number_to_point(0),
|
|
|
|
graph_y_axis.number_to_point(1),
|
|
|
|
), LEFT, buff = SMALL_BUFF)
|
|
|
|
for brace in h_brace, v_brace:
|
|
|
|
brace.A = brace.get_tex("A_x")
|
|
|
|
brace.A.highlight(self.A_color)
|
|
|
|
v_brace.A.scale(0.5, about_point = v_brace.get_center())
|
|
|
|
all_As = VGroup(A, corner_A, h_brace.A, v_brace.A)
|
|
|
|
|
|
|
|
def update_vect(vect):
|
|
|
|
self.oscillating_vector.A_vect[0] = h_brace.get_width()
|
|
|
|
return vect
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
GrowFromCenter(h_brace),
|
|
|
|
GrowFromCenter(v_brace),
|
|
|
|
)
|
|
|
|
self.dither(2)
|
|
|
|
self.play(
|
|
|
|
x.next_to, A, RIGHT, SMALL_BUFF,
|
|
|
|
corner_cos.next_to, corner_A, RIGHT, SMALL_BUFF,
|
|
|
|
FadeIn(all_As)
|
|
|
|
)
|
2017-09-01 10:41:27 -07:00
|
|
|
x.add(A)
|
|
|
|
corner_cos.add(corner_A)
|
2017-08-31 23:20:16 -07:00
|
|
|
self.dither()
|
|
|
|
factor = 0.5
|
|
|
|
self.play(
|
|
|
|
v_brace.stretch_in_place, factor, 1,
|
|
|
|
v_brace.move_to, v_brace.copy(), DOWN,
|
|
|
|
MaintainPositionRelativeTo(v_brace.A, v_brace),
|
|
|
|
h_brace.stretch_in_place, factor, 0,
|
|
|
|
h_brace.move_to, h_brace.copy(), LEFT,
|
|
|
|
MaintainPositionRelativeTo(h_brace.A, h_brace),
|
|
|
|
UpdateFromFunc(self.vector, update_vect),
|
|
|
|
graph.stretch_in_place, factor, 1,
|
|
|
|
)
|
|
|
|
self.dither(4)
|
|
|
|
|
2017-09-01 10:41:27 -07:00
|
|
|
self.h_brace = h_brace
|
|
|
|
self.v_brace = v_brace
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-08-30 18:33:55 -07:00
|
|
|
def add_kets(self):
|
2017-09-01 10:41:27 -07:00
|
|
|
x, y = self.components
|
|
|
|
E_equals = self.E_equals
|
|
|
|
for mob in x, y, E_equals:
|
|
|
|
mob.add_background_rectangle()
|
|
|
|
mob.generate_target()
|
|
|
|
|
|
|
|
right_ket = TexMobject("|\\rightarrow\\rangle")
|
|
|
|
up_ket = TexMobject("|\\uparrow\\rangle")
|
|
|
|
kets = VGroup(right_ket, up_ket)
|
|
|
|
kets.highlight(YELLOW)
|
|
|
|
for ket in kets:
|
|
|
|
ket.add_background_rectangle()
|
|
|
|
plus = TextMobject("+")
|
|
|
|
group = VGroup(
|
|
|
|
E_equals.target,
|
|
|
|
x.target, right_ket, plus,
|
|
|
|
y.target, up_ket,
|
|
|
|
)
|
|
|
|
group.arrange_submobjects(RIGHT)
|
|
|
|
E_equals.target.shift(SMALL_BUFF*UP)
|
|
|
|
group.scale(0.8)
|
|
|
|
group.move_to(self.brackets, DOWN)
|
|
|
|
group.to_edge(LEFT, buff = MED_SMALL_BUFF)
|
|
|
|
|
|
|
|
kets_word = TextMobject("``kets''")
|
|
|
|
kets_word.next_to(kets, DOWN, buff = 0.8)
|
|
|
|
arrows = VGroup(*[
|
|
|
|
Arrow(kets_word.get_top(), ket, color = ket.get_color())
|
|
|
|
for ket in kets
|
|
|
|
])
|
|
|
|
ket_rects = VGroup(*map(SurroundingRectangle, kets))
|
|
|
|
ket_rects.highlight(WHITE)
|
|
|
|
unit_vectors = VGroup(*[Vector(2*vect) for vect in RIGHT, UP])
|
|
|
|
unit_vectors.set_fill(YELLOW)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
FadeOut(self.brackets),
|
|
|
|
*map(MoveToTarget, [E_equals, x, y])
|
|
|
|
)
|
|
|
|
self.play(*map(Write, [right_ket, plus, up_ket]), run_time = 1)
|
|
|
|
self.play(
|
|
|
|
Write(kets_word),
|
|
|
|
LaggedStart(ShowCreation, arrows, lag_ratio = 0.7),
|
|
|
|
run_time = 2,
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
for ket, ket_rect, unit_vect in zip(kets, ket_rects, unit_vectors):
|
|
|
|
self.play(ShowCreation(ket_rect))
|
|
|
|
self.play(FadeOut(ket_rect))
|
|
|
|
self.play(ReplacementTransform(ket[1][1].copy(), unit_vect))
|
|
|
|
self.dither()
|
|
|
|
self.play(FadeOut(unit_vectors))
|
|
|
|
self.play(*map(FadeOut, [kets_word, arrows]))
|
|
|
|
|
|
|
|
self.kets = kets
|
|
|
|
self.plus = plus
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-08-30 18:33:55 -07:00
|
|
|
def switch_to_vertically_polarized_light(self):
|
2017-09-01 10:41:27 -07:00
|
|
|
x, y = self.components
|
|
|
|
x_ket, y_ket = self.kets
|
|
|
|
plus = self.plus
|
|
|
|
|
|
|
|
x.target = TexMobject("0", "").add_background_rectangle()
|
|
|
|
y.target = TexMobject(
|
|
|
|
"A_y", "\\cos(", "2\\pi", "f_y", "t", "+", "\\phi_y", ")"
|
|
|
|
)
|
|
|
|
y.target.highlight_by_tex_to_color_map({
|
|
|
|
"A" : self.A_color,
|
|
|
|
"f" : self.f_color,
|
|
|
|
"phi" : self.phi_color,
|
|
|
|
})
|
|
|
|
y.target.add_background_rectangle()
|
|
|
|
VGroup(x.target, y.target).scale(0.8)
|
|
|
|
for mob in [plus] + list(self.kets):
|
|
|
|
mob.generate_target()
|
|
|
|
|
|
|
|
movers = x, x_ket, plus, y, y_ket
|
|
|
|
group = VGroup(*[m.target for m in movers])
|
|
|
|
group.arrange_submobjects(RIGHT)
|
|
|
|
group.move_to(x, LEFT)
|
|
|
|
|
|
|
|
vector_A_vect = np.array(self.oscillating_vector.A_vect)
|
|
|
|
def update_vect(vect, alpha):
|
|
|
|
self.oscillating_vector.A_vect = rotate_vector(
|
|
|
|
vector_A_vect, alpha*np.pi/2
|
|
|
|
)
|
|
|
|
return vect
|
|
|
|
|
|
|
|
new_h_brace = Brace(Line(ORIGIN, UP), RIGHT)
|
|
|
|
|
|
|
|
words = TextMobject(
|
|
|
|
"``", "Vertically", " polarized", "''",
|
|
|
|
arg_separator = "",
|
|
|
|
)
|
|
|
|
words.add_background_rectangle()
|
|
|
|
words.move_to(self.horizontally_polarized_words)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
UpdateFromAlphaFunc(self.vector, update_vect),
|
|
|
|
Transform(self.h_brace, new_h_brace),
|
|
|
|
self.h_brace.A.next_to, new_h_brace, RIGHT, SMALL_BUFF,
|
|
|
|
Transform(self.horizontally_polarized_words, words),
|
|
|
|
*map(FadeOut, [
|
|
|
|
self.corner_group, self.v_brace,
|
|
|
|
self.v_brace.A, self.low_f_graph,
|
|
|
|
])
|
|
|
|
)
|
|
|
|
self.play(*map(MoveToTarget, movers))
|
|
|
|
self.dither(5)
|
|
|
|
|
2017-09-01 18:57:38 -07:00
|
|
|
class ChangeFromHorizontalToVerticallyPolarized(DirectionOfPolarizationScene):
|
|
|
|
CONFIG = {
|
|
|
|
"filter_x_coordinates" : [],
|
|
|
|
"EMWave_config" : {
|
|
|
|
"start_point" : SPACE_WIDTH*LEFT,
|
|
|
|
"A_vect" : [0, 2, 0],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
def setup(self):
|
|
|
|
DirectionOfPolarizationScene.setup(self)
|
|
|
|
self.axes.z_axis.rotate(np.pi/2, OUT)
|
|
|
|
self.axes.y_axis.rotate(np.pi/2, UP)
|
|
|
|
self.remove(self.pol_filter)
|
|
|
|
self.em_wave.M_vects.set_fill(opacity = 0)
|
|
|
|
for vect in self.em_wave.E_vects:
|
|
|
|
vect.normal_vector = RIGHT
|
|
|
|
vect.set_fill(opacity = 0.5)
|
|
|
|
self.em_wave.E_vects[-1].set_fill(opacity = 1)
|
|
|
|
|
|
|
|
self.set_camera_position(0.9*np.pi/2, -0.05*np.pi)
|
|
|
|
|
|
|
|
def construct(self):
|
|
|
|
self.dither(3)
|
|
|
|
self.change_polarization_direction(np.pi/2)
|
|
|
|
self.dither(10)
|
|
|
|
|
|
|
|
class SumOfTwoWaves(ChangeFromHorizontalToVerticallyPolarized):
|
|
|
|
CONFIG = {
|
|
|
|
"axes_config" : {
|
|
|
|
"y_max" : 1.5,
|
|
|
|
"y_min" : -1.5,
|
|
|
|
"z_max" : 1.5,
|
|
|
|
"z_min" : -1.5,
|
|
|
|
},
|
|
|
|
"EMWave_config" : {
|
|
|
|
"A_vect" : [0, 0, 1],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
def setup(self):
|
|
|
|
ChangeFromHorizontalToVerticallyPolarized.setup(self)
|
|
|
|
for vect in self.em_wave.E_vects[:-1]:
|
|
|
|
vect.set_fill(opacity = 0.3)
|
|
|
|
self.side_em_waves = []
|
|
|
|
for shift_vect, A_vect in (5*DOWN, [0, 1, 0]), (5*UP, [0, 1, 1]):
|
|
|
|
axes = self.axes.copy()
|
|
|
|
em_wave = copy.deepcopy(self.em_wave)
|
|
|
|
axes.shift(shift_vect)
|
|
|
|
em_wave.mobject.shift(shift_vect)
|
|
|
|
em_wave.start_point += shift_vect
|
|
|
|
for ov in em_wave.continual_animations:
|
|
|
|
ov.A_vect = np.array(A_vect)
|
|
|
|
self.add(axes, em_wave)
|
|
|
|
self.side_em_waves.append(em_wave)
|
|
|
|
|
|
|
|
self.set_camera_position(0.95*np.pi/2, -0.03*np.pi)
|
|
|
|
|
|
|
|
def construct(self):
|
|
|
|
plus, equals = pe = VGroup(*map(TexMobject, "+="))
|
|
|
|
pe.scale(2)
|
|
|
|
pe.rotate(np.pi/2, RIGHT)
|
|
|
|
pe.rotate(np.pi/2, OUT)
|
|
|
|
plus.shift(2.5*DOWN)
|
|
|
|
equals.shift(2.5*UP)
|
|
|
|
self.add(pe)
|
|
|
|
|
|
|
|
self.dither(32)
|
|
|
|
|
|
|
|
class ShowTipToTailSum(ShowVectorEquation):
|
2017-09-01 10:41:27 -07:00
|
|
|
def construct(self):
|
2017-09-01 18:57:38 -07:00
|
|
|
self.force_skipping()
|
|
|
|
self.add_vector()
|
|
|
|
self.add_plane()
|
|
|
|
self.add_vertial_vector()
|
|
|
|
self.revert_to_original_skipping_status()
|
|
|
|
|
|
|
|
self.add_kets()
|
|
|
|
self.show_vector_sum()
|
|
|
|
self.write_superposition()
|
|
|
|
self.add_amplitudes()
|
|
|
|
self.add_phase_shift()
|
|
|
|
|
|
|
|
def add_vertial_vector(self):
|
|
|
|
self.h_vector = self.vector
|
|
|
|
self.h_oscillating_vector = self.oscillating_vector
|
|
|
|
self.h_oscillating_vector.start_up_time = 0
|
|
|
|
|
|
|
|
self.v_oscillating_vector = self.h_oscillating_vector.copy()
|
|
|
|
self.v_vector = self.v_oscillating_vector.vector
|
|
|
|
self.v_oscillating_vector.A_vect = [0, 2, 0]
|
|
|
|
self.v_oscillating_vector.update(0)
|
|
|
|
|
|
|
|
self.d_oscillating_vector = ContinualUpdateFromFunc(
|
|
|
|
Vector(UP+RIGHT, color = E_COLOR),
|
|
|
|
lambda v : v.put_start_and_end_on(
|
|
|
|
ORIGIN,
|
|
|
|
self.v_vector.get_end()+ self.h_vector.get_end(),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
self.d_vector = self.d_oscillating_vector.mobject
|
|
|
|
self.d_oscillating_vector.update(0)
|
|
|
|
|
|
|
|
self.add(self.v_oscillating_vector)
|
|
|
|
self.add_foreground_mobject(self.v_vector)
|
|
|
|
|
|
|
|
def add_kets(self):
|
|
|
|
h_ket, v_ket = kets = VGroup(*[
|
|
|
|
TexMobject(
|
|
|
|
"\\cos(", "2\\pi", "f", "t", ")",
|
|
|
|
"|\\!\\%sarrow\\rangle"%s
|
|
|
|
)
|
|
|
|
for s in "right", "up"
|
|
|
|
])
|
|
|
|
for ket in kets:
|
|
|
|
ket.highlight_by_tex_to_color_map({
|
|
|
|
"f" : self.f_color,
|
|
|
|
"rangle" : YELLOW,
|
|
|
|
})
|
|
|
|
ket.add_background_rectangle(opacity = 1)
|
|
|
|
ket.scale(0.8)
|
|
|
|
|
|
|
|
h_ket.next_to(2*RIGHT, UP, SMALL_BUFF)
|
|
|
|
v_ket.next_to(2*UP, UP, SMALL_BUFF)
|
|
|
|
self.add_foreground_mobject(kets)
|
|
|
|
|
|
|
|
self.kets = kets
|
|
|
|
|
|
|
|
def show_vector_sum(self):
|
|
|
|
h_line = DashedLine(ORIGIN, 2*RIGHT)
|
|
|
|
v_line = DashedLine(ORIGIN, 2*UP)
|
|
|
|
|
2017-09-06 20:18:19 -07:00
|
|
|
h_line.update = self.generate_dashed_line_update(
|
|
|
|
self.h_vector, self.v_vector
|
|
|
|
)
|
|
|
|
v_line.update = self.generate_dashed_line_update(
|
|
|
|
self.v_vector, self.h_vector
|
|
|
|
)
|
2017-09-01 18:57:38 -07:00
|
|
|
|
|
|
|
h_ket, v_ket = self.kets
|
|
|
|
for ket in self.kets:
|
|
|
|
ket.generate_target()
|
|
|
|
plus = TexMobject("+")
|
|
|
|
ket_sum = VGroup(h_ket.target, plus, v_ket.target)
|
|
|
|
ket_sum.arrange_submobjects(RIGHT)
|
|
|
|
ket_sum.next_to(3*RIGHT + 2*UP, UP, SMALL_BUFF)
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-09-01 18:57:38 -07:00
|
|
|
self.dither(4)
|
|
|
|
self.remove(self.h_oscillating_vector, self.v_oscillating_vector)
|
|
|
|
self.add(self.h_vector, self.v_vector)
|
|
|
|
h_line.update(h_line)
|
|
|
|
v_line.update(v_line)
|
|
|
|
self.play(*it.chain(
|
|
|
|
map(MoveToTarget, self.kets),
|
|
|
|
[Write(plus)],
|
|
|
|
map(ShowCreation, [h_line, v_line]),
|
|
|
|
))
|
|
|
|
blue_black = average_color(BLUE, BLACK)
|
|
|
|
self.play(
|
|
|
|
GrowFromPoint(self.d_vector, ORIGIN),
|
|
|
|
self.h_vector.set_fill, blue_black,
|
|
|
|
self.v_vector.set_fill, blue_black,
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.add(
|
|
|
|
self.h_oscillating_vector,
|
|
|
|
self.v_oscillating_vector,
|
|
|
|
self.d_oscillating_vector,
|
|
|
|
ContinualUpdateFromFunc(h_line, h_line.update),
|
|
|
|
ContinualUpdateFromFunc(v_line, v_line.update),
|
|
|
|
)
|
|
|
|
self.dither(4)
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-09-01 18:57:38 -07:00
|
|
|
self.ket_sum = VGroup(h_ket, plus, v_ket)
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-09-01 18:57:38 -07:00
|
|
|
def write_superposition(self):
|
|
|
|
superposition_words = TextMobject(
|
|
|
|
"``Superposition''", "of",
|
|
|
|
"$|\\!\\rightarrow\\rangle$", "and",
|
|
|
|
"$|\\!\\uparrow\\rangle$",
|
|
|
|
)
|
|
|
|
superposition_words.scale(0.8)
|
|
|
|
superposition_words.highlight_by_tex("rangle", YELLOW)
|
|
|
|
superposition_words.add_background_rectangle()
|
|
|
|
superposition_words.to_corner(UP+LEFT)
|
|
|
|
ket_sum = self.ket_sum
|
|
|
|
ket_sum.generate_target()
|
|
|
|
ket_sum.target.move_to(superposition_words)
|
|
|
|
ket_sum.target.align_to(ket_sum, UP)
|
|
|
|
|
|
|
|
sum_word = TextMobject("", "Sum")
|
|
|
|
weighted_sum_word = TextMobject("Weighted", "sum")
|
|
|
|
for word in sum_word, weighted_sum_word:
|
|
|
|
word.scale(0.8)
|
|
|
|
word.highlight(GREEN)
|
|
|
|
word.add_background_rectangle()
|
|
|
|
word.move_to(superposition_words.get_part_by_tex("Super"))
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-09-01 18:57:38 -07:00
|
|
|
self.play(
|
|
|
|
Write(superposition_words, run_time = 2),
|
|
|
|
MoveToTarget(ket_sum)
|
|
|
|
)
|
|
|
|
self.dither(2)
|
|
|
|
self.play(
|
|
|
|
FadeIn(sum_word),
|
|
|
|
superposition_words.shift, MED_LARGE_BUFF*DOWN,
|
|
|
|
ket_sum.shift, MED_LARGE_BUFF*DOWN,
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.play(ReplacementTransform(
|
|
|
|
sum_word, weighted_sum_word
|
|
|
|
))
|
|
|
|
self.dither(2)
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-09-01 18:57:38 -07:00
|
|
|
def add_amplitudes(self):
|
|
|
|
h_ket, plus, r_ket = self.ket_sum
|
|
|
|
for mob in self.ket_sum:
|
|
|
|
mob.generate_target()
|
|
|
|
h_A, v_A = 2, 0.5
|
|
|
|
h_A_mob, v_A_mob = A_mobs = VGroup(*[
|
|
|
|
TexMobject(str(A)).add_background_rectangle()
|
|
|
|
for A in [h_A, v_A]
|
|
|
|
])
|
|
|
|
A_mobs.scale(0.8)
|
|
|
|
A_mobs.highlight(GREEN)
|
|
|
|
h_A_mob.move_to(h_ket, LEFT)
|
|
|
|
VGroup(h_ket.target, plus.target).next_to(
|
|
|
|
h_A_mob, RIGHT, SMALL_BUFF
|
|
|
|
)
|
|
|
|
v_A_mob.next_to(plus.target, RIGHT, SMALL_BUFF)
|
|
|
|
r_ket.target.next_to(v_A_mob, RIGHT, SMALL_BUFF)
|
|
|
|
A_mobs.shift(0.4*SMALL_BUFF*UP)
|
|
|
|
|
|
|
|
h_ov = self.h_oscillating_vector
|
|
|
|
v_ov = self.v_oscillating_vector
|
|
|
|
|
|
|
|
|
|
|
|
self.play(*it.chain(
|
|
|
|
map(MoveToTarget, self.ket_sum),
|
|
|
|
map(Write, A_mobs),
|
|
|
|
[
|
|
|
|
UpdateFromAlphaFunc(
|
|
|
|
ov.vector,
|
2017-09-06 20:18:19 -07:00
|
|
|
self.generate_A_update(
|
|
|
|
ov,
|
|
|
|
A*np.array(ov.A_vect),
|
|
|
|
np.array(ov.A_vect)
|
|
|
|
)
|
2017-09-01 18:57:38 -07:00
|
|
|
)
|
|
|
|
for ov, A in (h_ov, h_A), (v_ov, v_A)
|
|
|
|
]
|
|
|
|
))
|
|
|
|
self.dither(4)
|
|
|
|
|
|
|
|
self.A_mobs = A_mobs
|
|
|
|
|
|
|
|
def add_phase_shift(self):
|
|
|
|
h_ket, plus, v_ket = self.ket_sum
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-09-01 18:57:38 -07:00
|
|
|
plus_phi = TexMobject("+", "\\pi/2")
|
|
|
|
plus_phi.highlight_by_tex("pi", self.phi_color)
|
|
|
|
plus_phi.scale(0.8)
|
|
|
|
plus_phi.next_to(v_ket.get_part_by_tex("t"), RIGHT, SMALL_BUFF)
|
|
|
|
v_ket.generate_target()
|
|
|
|
VGroup(*v_ket.target[1][-2:]).next_to(plus_phi, RIGHT, SMALL_BUFF)
|
|
|
|
v_ket.target[0].replace(v_ket.target[1])
|
2017-08-24 11:44:06 -07:00
|
|
|
|
|
|
|
|
2017-09-01 18:57:38 -07:00
|
|
|
h_ov = self.h_oscillating_vector
|
|
|
|
v_ov = self.v_oscillating_vector
|
|
|
|
|
|
|
|
ellipse = Circle()
|
|
|
|
ellipse.stretch_to_fit_height(2)
|
|
|
|
ellipse.stretch_to_fit_width(8)
|
|
|
|
ellipse.highlight(self.phi_color)
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-09-06 20:18:19 -07:00
|
|
|
h_A_mob, v_A_mob = self.A_mobs
|
|
|
|
new_h_A_mob = v_A_mob.copy()
|
|
|
|
new_h_A_mob.move_to(h_A_mob, RIGHT)
|
|
|
|
|
2017-09-01 18:57:38 -07:00
|
|
|
self.add_foreground_mobject(plus_phi)
|
|
|
|
self.play(
|
|
|
|
MoveToTarget(v_ket),
|
|
|
|
Write(plus_phi),
|
|
|
|
UpdateFromAlphaFunc(
|
|
|
|
v_ov.vector,
|
2017-09-06 20:18:19 -07:00
|
|
|
self.generate_phi_update(
|
2017-09-01 18:57:38 -07:00
|
|
|
v_ov,
|
|
|
|
np.array([0, np.pi/2, 0]),
|
|
|
|
np.array(v_ov.phi_vect)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
self.play(FadeIn(ellipse))
|
|
|
|
self.dither(5)
|
|
|
|
self.play(
|
|
|
|
UpdateFromAlphaFunc(
|
|
|
|
h_ov.vector,
|
|
|
|
self.generate_A_update(
|
2017-09-06 20:18:19 -07:00
|
|
|
h_ov,
|
|
|
|
0.25*np.array(h_ov.A_vect),
|
|
|
|
np.array(h_ov.A_vect),
|
2017-09-01 18:57:38 -07:00
|
|
|
)
|
|
|
|
),
|
2017-09-06 20:18:19 -07:00
|
|
|
ellipse.stretch, 0.25, 0,
|
|
|
|
Transform(h_A_mob, new_h_A_mob)
|
2017-09-01 18:57:38 -07:00
|
|
|
)
|
|
|
|
self.dither(8)
|
|
|
|
|
2017-09-06 20:18:19 -07:00
|
|
|
#####
|
|
|
|
|
|
|
|
def generate_A_update(self, ov, A_vect, prev_A_vect):
|
|
|
|
def update(vect, alpha):
|
|
|
|
ov.A_vect = interpolate(
|
|
|
|
np.array(prev_A_vect),
|
|
|
|
A_vect,
|
|
|
|
alpha
|
|
|
|
)
|
|
|
|
return vect
|
|
|
|
return update
|
|
|
|
|
|
|
|
def generate_phi_update(self, ov, phi_vect, prev_phi_vect):
|
|
|
|
def update(vect, alpha):
|
|
|
|
ov.phi_vect = interpolate(
|
|
|
|
prev_phi_vect, phi_vect, alpha
|
|
|
|
)
|
|
|
|
return vect
|
|
|
|
return update
|
|
|
|
|
|
|
|
def generate_dashed_line_update(self, v1, v2):
|
|
|
|
def update_line(line):
|
|
|
|
line.put_start_and_end_on_with_projection(
|
|
|
|
*v1.get_start_and_end()
|
|
|
|
)
|
|
|
|
line.shift(v2.get_end() - line.get_start())
|
|
|
|
return update_line
|
|
|
|
|
2017-09-01 18:57:38 -07:00
|
|
|
class CircularlyPolarizedLight(SumOfTwoWaves):
|
|
|
|
CONFIG = {
|
|
|
|
"EMWave_config" : {
|
|
|
|
"phi_vect" : [0, np.pi/2, 0],
|
2017-09-01 19:52:12 -07:00
|
|
|
},
|
2017-09-01 18:57:38 -07:00
|
|
|
}
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-09-01 19:52:12 -07:00
|
|
|
class AlternateBasis(ShowTipToTailSum):
|
|
|
|
def construct(self):
|
|
|
|
self.force_skipping()
|
|
|
|
self.add_vector()
|
|
|
|
self.add_plane()
|
|
|
|
self.add_vertial_vector()
|
|
|
|
self.add_kets()
|
|
|
|
self.show_vector_sum()
|
2017-09-06 20:18:19 -07:00
|
|
|
self.remove(self.ket_sum, self.kets)
|
2017-09-01 19:52:12 -07:00
|
|
|
self.reset_amplitude()
|
|
|
|
self.revert_to_original_skipping_status()
|
|
|
|
|
2017-09-06 20:18:19 -07:00
|
|
|
self.add_superposition_text()
|
2017-09-01 19:52:12 -07:00
|
|
|
self.rotate_plane()
|
2017-09-06 20:18:19 -07:00
|
|
|
self.show_vertically_polarized()
|
2017-09-01 19:52:12 -07:00
|
|
|
|
|
|
|
def reset_amplitude(self):
|
|
|
|
self.h_oscillating_vector.A_vect = np.array([1, 0, 0])
|
|
|
|
|
2017-09-06 20:18:19 -07:00
|
|
|
def add_superposition_text(self):
|
|
|
|
self.hv_superposition, self.da_superposition = superpositions = [
|
|
|
|
TexMobject(
|
|
|
|
"\\vec{\\textbf{E}}", "=",
|
|
|
|
"(\\dots)",
|
|
|
|
"|\\!\\%sarrow\\rangle"%s1,
|
|
|
|
"+",
|
|
|
|
"(\\dots)",
|
|
|
|
"|\\!\\%sarrow\\rangle"%s2,
|
|
|
|
)
|
|
|
|
for s1, s2 in ("right", "up"), ("ne", "nw")
|
|
|
|
]
|
|
|
|
for superposition in superpositions:
|
|
|
|
superposition.highlight_by_tex("rangle", YELLOW)
|
|
|
|
superposition.highlight_by_tex("E", E_COLOR)
|
|
|
|
superposition.add_background_rectangle(opacity = 1)
|
|
|
|
superposition.to_edge(UP)
|
|
|
|
self.add(self.hv_superposition)
|
|
|
|
|
2017-09-01 19:52:12 -07:00
|
|
|
def rotate_plane(self):
|
2017-09-06 20:18:19 -07:00
|
|
|
new_plane = NumberPlane(
|
|
|
|
x_unit_size = 2,
|
|
|
|
y_unit_size = 2,
|
|
|
|
y_radius = SPACE_WIDTH,
|
|
|
|
secondary_line_ratio = 0,
|
|
|
|
)
|
|
|
|
new_plane.add_coordinates()
|
|
|
|
new_plane.save_state()
|
|
|
|
new_plane.fade(1)
|
|
|
|
|
|
|
|
d = (RIGHT + UP)/np.sqrt(2)
|
|
|
|
a = (LEFT + UP)/np.sqrt(2)
|
|
|
|
|
|
|
|
self.dither(4)
|
|
|
|
self.play(
|
|
|
|
self.xy_plane.fade, 0.5,
|
|
|
|
self.xy_plane.coordinate_labels.fade, 1,
|
|
|
|
new_plane.restore,
|
|
|
|
new_plane.rotate, np.pi/4,
|
|
|
|
UpdateFromAlphaFunc(
|
|
|
|
self.h_vector,
|
|
|
|
self.generate_A_update(
|
|
|
|
self.h_oscillating_vector,
|
|
|
|
2*d*np.dot(0.5*RIGHT + UP, d),
|
|
|
|
np.array(self.h_oscillating_vector.A_vect)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
UpdateFromAlphaFunc(
|
|
|
|
self.v_vector,
|
|
|
|
self.generate_A_update(
|
|
|
|
self.v_oscillating_vector,
|
|
|
|
2*a*np.dot(0.5*RIGHT + UP, a),
|
|
|
|
np.array(self.v_oscillating_vector.A_vect)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
Transform(self.hv_superposition, self.da_superposition),
|
|
|
|
run_time = 2,
|
|
|
|
)
|
|
|
|
self.dither(4)
|
|
|
|
|
|
|
|
def show_vertically_polarized(self):
|
|
|
|
self.play(
|
|
|
|
UpdateFromAlphaFunc(
|
|
|
|
self.h_vector,
|
|
|
|
self.generate_A_update(
|
|
|
|
self.h_oscillating_vector,
|
|
|
|
np.array([0.7, 0.7, 0]),
|
|
|
|
np.array(self.h_oscillating_vector.A_vect)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
UpdateFromAlphaFunc(
|
|
|
|
self.v_vector,
|
|
|
|
self.generate_A_update(
|
|
|
|
self.v_oscillating_vector,
|
|
|
|
np.array([-0.7, 0.7, 0]),
|
|
|
|
np.array(self.v_oscillating_vector.A_vect)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
)
|
|
|
|
self.dither(8)
|
|
|
|
|
|
|
|
class WriteBasis(Scene):
|
|
|
|
def construct(self):
|
|
|
|
words = TextMobject("Choice of ``basis''")
|
|
|
|
words.scale_to_fit_width(2*SPACE_WIDTH-1)
|
|
|
|
words.to_edge(DOWN)
|
|
|
|
self.play(Write(words))
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
class ShowPolarizingFilter(DirectionOfPolarizationScene):
|
|
|
|
CONFIG = {
|
|
|
|
"EMWave_config" : {
|
|
|
|
"start_point" : SPACE_WIDTH*LEFT,
|
|
|
|
},
|
|
|
|
"apply_filter" : True,
|
|
|
|
}
|
|
|
|
def construct(self):
|
|
|
|
self.setup_rectangles()
|
|
|
|
self.fade_M_vects()
|
|
|
|
self.axes.fade(0.5)
|
|
|
|
|
|
|
|
self.initial_rotation()
|
|
|
|
self.mention_energy_absorption()
|
|
|
|
self.write_as_superposition()
|
|
|
|
self.diagonal_filter()
|
|
|
|
|
|
|
|
def setup_rectangles(self):
|
|
|
|
DirectionOfPolarizationScene.setup_rectangles(self)
|
|
|
|
self.rectangles[-1].fade(1)
|
|
|
|
|
|
|
|
def fade_M_vects(self):
|
|
|
|
self.em_wave.M_vects.set_fill(opacity = 0)
|
|
|
|
|
|
|
|
def initial_rotation(self):
|
|
|
|
self.dither()
|
|
|
|
self.play(FadeIn(self.rectangles))
|
|
|
|
self.dither()
|
|
|
|
self.change_polarization_direction(np.pi/2, run_time = 3)
|
|
|
|
self.move_camera(phi = 0.9*np.pi/2, theta = -0.05*np.pi)
|
|
|
|
|
|
|
|
def mention_energy_absorption(self):
|
|
|
|
words = TextMobject("Absorbs horizontal \\\\ energy")
|
|
|
|
words.highlight(RED)
|
|
|
|
words.next_to(ORIGIN, UP+RIGHT, MED_LARGE_BUFF)
|
|
|
|
words.rotate(np.pi/2, RIGHT)
|
|
|
|
words.rotate(np.pi/2, OUT)
|
|
|
|
|
|
|
|
lines = VGroup(*[
|
|
|
|
Line(
|
|
|
|
np.sin(a)*RIGHT + np.cos(a)*UP,
|
|
|
|
np.sin(a)*LEFT + np.cos(a)*UP,
|
|
|
|
color = RED,
|
|
|
|
stroke_width = 2,
|
|
|
|
)
|
|
|
|
for a in np.linspace(0, np.pi, 15)
|
|
|
|
])
|
|
|
|
lines.rotate(np.pi/2, RIGHT)
|
|
|
|
lines.rotate(np.pi/2, OUT)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
Write(words, run_time = 2),
|
|
|
|
*map(GrowFromCenter, lines)
|
|
|
|
)
|
|
|
|
self.play(FadeOut(lines))
|
|
|
|
self.play(FadeOut(words))
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
def write_as_superposition(self):
|
|
|
|
superposition, continual_updates = self.get_superposition_tex(0, "right", "up")
|
|
|
|
rect = superposition.rect
|
|
|
|
|
|
|
|
self.play(Write(superposition, run_time = 2))
|
|
|
|
self.add(*continual_updates)
|
|
|
|
for angle in np.pi/4, -np.pi/6:
|
|
|
|
self.change_polarization_direction(angle)
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
self.move_camera(
|
|
|
|
theta = -0.6*np.pi,
|
|
|
|
added_anims = [
|
|
|
|
Rotate(superposition, -0.6*np.pi, axis = OUT)
|
|
|
|
]
|
|
|
|
)
|
|
|
|
rect.set_stroke(YELLOW, 3)
|
|
|
|
self.play(ShowCreation(rect))
|
|
|
|
arrow = Arrow(
|
|
|
|
rect.get_nadir(), 3*RIGHT + 0.5*OUT,
|
|
|
|
normal_vector = DOWN
|
|
|
|
)
|
|
|
|
self.play(ShowCreation(arrow))
|
|
|
|
|
|
|
|
for angle in np.pi/3, -np.pi/3, np.pi/6:
|
|
|
|
self.change_polarization_direction(angle)
|
|
|
|
self.dither(2)
|
|
|
|
self.play(
|
|
|
|
FadeOut(superposition),
|
|
|
|
FadeOut(arrow),
|
|
|
|
)
|
|
|
|
self.move_camera(theta = -0.1*np.pi)
|
|
|
|
|
|
|
|
def diagonal_filter(self):
|
|
|
|
superposition, continual_updates = self.get_superposition_tex(-np.pi/4, "nw", "ne")
|
|
|
|
|
|
|
|
def update_filter_angle(pf, alpha):
|
|
|
|
pf.filter_angle = interpolate(0, -np.pi/4, alpha)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
Rotate(self.pol_filter, np.pi/4, axis = LEFT),
|
|
|
|
UpdateFromAlphaFunc(self.pol_filter, update_filter_angle),
|
|
|
|
Animation(self.em_wave.mobject)
|
|
|
|
)
|
|
|
|
superposition.rect.set_stroke(YELLOW, 2)
|
|
|
|
self.play(Write(superposition, run_time = 2))
|
|
|
|
self.add(*continual_updates)
|
|
|
|
for angle in np.pi/4, -np.pi/3, -np.pi/6:
|
|
|
|
self.change_polarization_direction(np.pi/4)
|
|
|
|
self.dither(2)
|
|
|
|
|
|
|
|
#######
|
|
|
|
|
|
|
|
def get_superposition_tex(self, angle, s1, s2):
|
|
|
|
superposition = TexMobject(
|
|
|
|
"0.00", "\\cos(", "2\\pi", "f", ")",
|
|
|
|
"|\\! \\%sarrow \\rangle"%s1,
|
|
|
|
"+",
|
|
|
|
"1.00", "\\cos(", "2\\pi", "f", ")",
|
|
|
|
"|\\! \\%sarrow \\rangle"%s2,
|
|
|
|
)
|
|
|
|
|
|
|
|
A_x = DecimalNumber(0)
|
|
|
|
A_y = DecimalNumber(1)
|
|
|
|
A_x.move_to(superposition[0])
|
|
|
|
A_y.move_to(superposition[7])
|
|
|
|
superposition.submobjects[0] = A_x
|
|
|
|
superposition.submobjects[7] = A_y
|
|
|
|
VGroup(A_x, A_y).highlight(GREEN)
|
|
|
|
superposition.highlight_by_tex("f", RED)
|
|
|
|
superposition.highlight_by_tex("rangle", YELLOW)
|
|
|
|
plus = superposition.get_part_by_tex("+")
|
|
|
|
plus.add_to_back(BackgroundRectangle(plus))
|
|
|
|
|
|
|
|
v_part = VGroup(*superposition[7:])
|
|
|
|
rect = SurroundingRectangle(v_part)
|
|
|
|
rect.fade(1)
|
|
|
|
superposition.rect = rect
|
|
|
|
superposition.add(rect)
|
|
|
|
|
|
|
|
superposition.shift(3*UP + SMALL_BUFF*LEFT)
|
|
|
|
superposition.rotate(np.pi/2, RIGHT)
|
|
|
|
superposition.rotate(np.pi/2, OUT)
|
|
|
|
|
|
|
|
def generate_decimal_update(trig_func):
|
|
|
|
def update_decimal(decimal):
|
|
|
|
new_decimal = DecimalNumber(abs(trig_func(
|
|
|
|
self.reference_line.get_angle() - angle
|
|
|
|
)))
|
|
|
|
new_decimal.rotate(np.pi/2, RIGHT)
|
|
|
|
new_decimal.rotate(np.pi/2, OUT)
|
|
|
|
new_decimal.rotate(self.camera.get_theta(), OUT)
|
|
|
|
new_decimal.scale_to_fit_depth(decimal.get_depth())
|
|
|
|
new_decimal.move_to(decimal, UP)
|
|
|
|
new_decimal.highlight(decimal.get_color())
|
|
|
|
decimal.align_data(new_decimal)
|
|
|
|
families = [
|
|
|
|
mob.family_members_with_points()
|
|
|
|
for mob in decimal, new_decimal
|
|
|
|
]
|
|
|
|
for sm1, sm2 in zip(*families):
|
|
|
|
sm1.interpolate(sm1, sm2, 1)
|
|
|
|
return decimal
|
|
|
|
return update_decimal
|
|
|
|
|
|
|
|
continual_updates = [
|
|
|
|
ContinualUpdateFromFunc(
|
|
|
|
A_x, generate_decimal_update(np.sin),
|
|
|
|
),
|
|
|
|
ContinualUpdateFromFunc(
|
|
|
|
A_y, generate_decimal_update(np.cos),
|
|
|
|
),
|
|
|
|
]
|
|
|
|
|
|
|
|
return superposition, continual_updates
|
|
|
|
|
|
|
|
class EnergyOfWavesWavePortion(DirectWaveOutOfScreen):
|
|
|
|
CONFIG = {
|
|
|
|
"EMWave_config" : {
|
|
|
|
"A_vect" : [0, 1, 1],
|
|
|
|
"amplitude" : 4,
|
|
|
|
"start_point" : SPACE_WIDTH*LEFT + 2*DOWN,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
def construct(self):
|
|
|
|
self.grow_arrows()
|
|
|
|
self.move_into_position()
|
|
|
|
self.fade_M_vects()
|
|
|
|
self.label_A()
|
|
|
|
self.add_components()
|
|
|
|
self.scale_up_and_down()
|
|
|
|
|
|
|
|
def grow_arrows(self):
|
|
|
|
for ov in self.em_wave.continual_animations:
|
|
|
|
ov.vector.rectangular_stem_width = 0.1
|
|
|
|
ov.vector.tip_length = 0.5
|
|
|
|
|
|
|
|
def label_A(self):
|
|
|
|
brace = Brace(Line(ORIGIN, 4*RIGHT))
|
|
|
|
brace.rotate(np.pi/4, OUT)
|
|
|
|
brace.A = brace.get_tex("A", buff = MED_SMALL_BUFF)
|
|
|
|
brace.A.scale_in_place(2)
|
|
|
|
brace.A.highlight(GREEN)
|
|
|
|
brace_group = VGroup(brace, brace.A)
|
|
|
|
self.position_brace_group(brace_group)
|
|
|
|
self.play(Write(brace_group, run_time = 1))
|
|
|
|
self.dither(4)
|
|
|
|
|
|
|
|
self.brace = brace
|
|
|
|
|
|
|
|
def add_components(self):
|
|
|
|
h_wave = self.em_wave.copy()
|
|
|
|
h_wave.A_vect = [0, 1, 0]
|
|
|
|
v_wave = self.em_wave.copy()
|
|
|
|
v_wave.A_vect = [0, 0, 1]
|
|
|
|
length = 4/np.sqrt(2)
|
|
|
|
for wave in h_wave, v_wave:
|
|
|
|
for ov in wave.continual_animations:
|
|
|
|
ov.A_vect = length*np.array(wave.A_vect)
|
|
|
|
|
|
|
|
h_brace = Brace(Line(ORIGIN, length*RIGHT))
|
|
|
|
v_brace = Brace(Line(ORIGIN, length*UP), LEFT)
|
|
|
|
for brace, c in (h_brace, "x"), (v_brace, "y"):
|
|
|
|
brace.A = brace.get_tex("A_%s"%c, buff = MED_LARGE_BUFF)
|
|
|
|
brace.A.scale_in_place(2)
|
|
|
|
brace.A.highlight(GREEN)
|
|
|
|
brace_group = VGroup(h_brace, h_brace.A, v_brace, v_brace.A)
|
|
|
|
self.position_brace_group(brace_group)
|
|
|
|
|
|
|
|
rhs = TexMobject("= \\sqrt{A_x^2 + A_y^2}")
|
|
|
|
rhs.scale(2)
|
|
|
|
for i in 3, 5, 7, 9:
|
|
|
|
rhs[i].highlight(GREEN)
|
|
|
|
rhs.rotate(np.pi/2, RIGHT)
|
|
|
|
rhs.rotate(np.pi/2, OUT)
|
|
|
|
|
|
|
|
period = 1./self.em_wave.frequency
|
|
|
|
self.add(h_wave, v_wave)
|
|
|
|
self.play(
|
|
|
|
FadeIn(h_wave.mobject),
|
|
|
|
FadeIn(v_wave.mobject),
|
|
|
|
self.brace.A.move_to, self.brace,
|
|
|
|
self.brace.A.shift, SMALL_BUFF*(2*UP+IN),
|
|
|
|
ReplacementTransform(self.brace, h_brace),
|
|
|
|
Write(h_brace.A)
|
|
|
|
)
|
|
|
|
self.dither(2)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
ReplacementTransform(h_brace.copy(), v_brace),
|
|
|
|
Write(v_brace.A)
|
|
|
|
)
|
|
|
|
self.dither(period - 1)
|
|
|
|
rhs.next_to(self.brace.A, UP, SMALL_BUFF)
|
|
|
|
self.play(Write(rhs))
|
|
|
|
self.dither(period)
|
|
|
|
|
|
|
|
self.h_brace = h_brace
|
|
|
|
self.v_brace = v_brace
|
|
|
|
self.h_wave = h_wave
|
|
|
|
self.v_wave = v_wave
|
|
|
|
|
|
|
|
def scale_up_and_down(self):
|
|
|
|
for scale_factor in 1.25, 0.4, 1.5, 0.5:
|
|
|
|
self.scale_wave(scale_factor)
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
######
|
|
|
|
|
|
|
|
def position_brace_group(self, brace_group):
|
|
|
|
brace_group.rotate(np.pi/2, RIGHT)
|
|
|
|
brace_group.rotate(np.pi/2, OUT)
|
|
|
|
brace_group.shift(2*DOWN)
|
|
|
|
|
|
|
|
def scale_wave(self, factor):
|
|
|
|
def generate_vect_update(ov):
|
|
|
|
prev_A = np.array(ov.A_vect)
|
|
|
|
new_A = factor*prev_A
|
|
|
|
def update(vect, alpha):
|
|
|
|
ov.A_vect = interpolate(
|
|
|
|
prev_A, new_A, alpha
|
|
|
|
)
|
|
|
|
return vect
|
|
|
|
return update
|
|
|
|
h_brace = self.h_brace
|
|
|
|
v_brace = self.v_brace
|
|
|
|
|
|
|
|
h_brace.generate_target()
|
|
|
|
h_brace.target.stretch_about_point(
|
|
|
|
factor, 1, h_brace.get_bottom()
|
|
|
|
)
|
|
|
|
v_brace.generate_target()
|
|
|
|
v_brace.target.stretch_about_point(
|
|
|
|
factor, 2, v_brace.get_nadir()
|
|
|
|
)
|
|
|
|
self.play(
|
|
|
|
MoveToTarget(h_brace),
|
|
|
|
MoveToTarget(v_brace),
|
|
|
|
*[
|
|
|
|
UpdateFromAlphaFunc(ov.vector, generate_vect_update(ov))
|
|
|
|
for ov in it.chain(
|
|
|
|
self.em_wave.continual_animations,
|
|
|
|
self.h_wave.continual_animations,
|
|
|
|
self.v_wave.continual_animations,
|
|
|
|
)
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
class EnergyOfWavesTeacherPortion(TeacherStudentsScene):
|
|
|
|
def construct(self):
|
|
|
|
self.show_energy_equation()
|
|
|
|
self.show_both_ways_of_thinking_about_it()
|
|
|
|
|
|
|
|
def show_energy_equation(self):
|
|
|
|
dot = Dot(self.teacher.get_top() + 2*(UP+LEFT))
|
|
|
|
dot.fade(1)
|
|
|
|
self.dot = dot
|
|
|
|
|
|
|
|
energy = TexMobject(
|
|
|
|
"\\frac{\\text{Energy}}{\\text{Volume}}",
|
|
|
|
"=",
|
|
|
|
"\\epsilon_0", "A", "^2"
|
|
|
|
)
|
|
|
|
energy.highlight_by_tex("A", GREEN)
|
|
|
|
energy.to_corner(UP+LEFT)
|
|
|
|
|
|
|
|
component_energy = TexMobject(
|
|
|
|
"=", "\\epsilon_0", "A_x", "^2",
|
|
|
|
"+", "\\epsilon_0", "A_y", "^2",
|
|
|
|
)
|
|
|
|
for i in 2, 6:
|
|
|
|
component_energy[i][0].highlight(GREEN)
|
|
|
|
component_energy[i+1].highlight(GREEN)
|
|
|
|
component_energy.next_to(energy[1], DOWN, MED_LARGE_BUFF, LEFT)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
Animation(dot),
|
|
|
|
self.teacher.change, "raise_right_hand", dot,
|
|
|
|
)
|
|
|
|
self.change_student_modes(
|
|
|
|
*["pondering"]*3,
|
|
|
|
look_at_arg = dot
|
|
|
|
)
|
|
|
|
self.dither(2)
|
|
|
|
self.play(Write(energy))
|
|
|
|
self.play(self.teacher.change, "happy")
|
|
|
|
self.dither(3)
|
|
|
|
self.play(
|
|
|
|
ReplacementTransform(
|
|
|
|
VGroup(*energy[-4:]).copy(),
|
|
|
|
VGroup(*component_energy[:4])
|
|
|
|
),
|
|
|
|
ReplacementTransform(
|
|
|
|
VGroup(*energy[-4:]).copy(),
|
|
|
|
VGroup(*component_energy[4:])
|
|
|
|
)
|
|
|
|
)
|
|
|
|
self.change_student_modes(*["happy"]*3, look_at_arg = energy)
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
def show_both_ways_of_thinking_about_it(self):
|
|
|
|
s1, s2 = self.get_students()[:2]
|
|
|
|
b1, b2 = [
|
|
|
|
ThoughtBubble(direction = v).scale(0.5)
|
|
|
|
for v in LEFT, RIGHT
|
|
|
|
]
|
|
|
|
b1.pin_to(s1)
|
|
|
|
b2.pin_to(s2)
|
|
|
|
|
|
|
|
b1.write("Add \\\\ components")
|
|
|
|
b2.write("Pythagorean \\\\ theorem")
|
|
|
|
|
|
|
|
for b, s in (b1, s1), (b2, s2):
|
|
|
|
self.play(
|
|
|
|
ShowCreation(b),
|
|
|
|
Write(b.content, run_time = 2),
|
|
|
|
s.change, "thinking"
|
|
|
|
)
|
|
|
|
self.dither(2)
|
|
|
|
self.change_student_modes(
|
|
|
|
*["plain"]*3,
|
|
|
|
look_at_arg = self.dot,
|
|
|
|
added_anims = [
|
|
|
|
self.teacher.change, "raise_right_hand", self.dot
|
|
|
|
]
|
|
|
|
|
|
|
|
)
|
|
|
|
self.play(self.teacher.look_at, self.dot)
|
|
|
|
self.dither(5)
|
|
|
|
|
|
|
|
class DescribePhoton(ThreeDScene):
|
|
|
|
def setup(self):
|
|
|
|
self.axes = ThreeDAxes()
|
|
|
|
self.add(self.axes)
|
|
|
|
|
|
|
|
self.set_camera_position(phi = 0.8*np.pi/2, theta = -np.pi/4)
|
|
|
|
em_wave = EMWave(
|
|
|
|
start_point = SPACE_WIDTH*LEFT,
|
|
|
|
A_vect = [0, 1, 1],
|
|
|
|
wave_number = 0,
|
|
|
|
amplitude = 3,
|
|
|
|
)
|
|
|
|
for ov in em_wave.continual_animations:
|
|
|
|
ov.vector.normal_vector = RIGHT
|
|
|
|
ov.vector.set_fill(opacity = 0.7)
|
|
|
|
for M_vect in em_wave.M_vects:
|
|
|
|
M_vect.set_fill(opacity = 0)
|
|
|
|
em_wave.update(0)
|
|
|
|
photon = WavePacket(
|
|
|
|
em_wave = em_wave,
|
|
|
|
run_time = 2,
|
|
|
|
)
|
|
|
|
|
|
|
|
self.photon = photon
|
|
|
|
self.em_wave = em_wave
|
|
|
|
|
|
|
|
def construct(self):
|
|
|
|
self.force_skipping()
|
|
|
|
|
|
|
|
self.add_ket_equation()
|
|
|
|
self.shoot_a_few_photons()
|
|
|
|
self.freeze_photon()
|
|
|
|
self.reposition_to_face_photon_head_on()
|
|
|
|
self.show_components()
|
|
|
|
self.change_basis()
|
|
|
|
self.show_amplitude_and_phase()
|
|
|
|
self.write_different_meaning()
|
|
|
|
self.write_components()
|
|
|
|
self.describe_via_energy()
|
|
|
|
self.components_not_possible_in_isolation()
|
|
|
|
self.ask_what_they_mean()
|
|
|
|
|
|
|
|
def add_ket_equation(self):
|
|
|
|
equation = TexMobject(
|
|
|
|
"|\\!\\psi\\rangle",
|
|
|
|
"=",
|
|
|
|
"\\alpha", "|\\!\\rightarrow \\rangle", "+",
|
|
|
|
"\\beta", "|\\!\\uparrow \\rangle",
|
|
|
|
)
|
|
|
|
equation.to_edge(UP).shift(MED_SMALL_BUFF*RIGHT)
|
|
|
|
equation.highlight_by_tex("psi", E_COLOR)
|
|
|
|
equation.highlight_by_tex("alpha", GREEN)
|
|
|
|
equation.highlight_by_tex("beta", RED)
|
|
|
|
rect = SurroundingRectangle(equation.get_part_by_tex("psi"))
|
|
|
|
rect.highlight(E_COLOR)
|
|
|
|
words = TextMobject("Polarization\\\\", "state")
|
|
|
|
words.next_to(rect, DOWN)
|
|
|
|
for part in words:
|
|
|
|
bg_rect = BackgroundRectangle(part)
|
|
|
|
bg_rect.stretch_in_place(2, 1)
|
|
|
|
part.add_to_back(bg_rect)
|
|
|
|
equation.rect = rect
|
|
|
|
equation.words = words
|
|
|
|
equation.add_background_rectangle()
|
|
|
|
equation.add(rect, words)
|
|
|
|
VGroup(rect, words).fade(1)
|
|
|
|
|
|
|
|
equation.rotate(np.pi/2, RIGHT)
|
|
|
|
equation.rotate(np.pi/2 + self.camera.get_theta(), OUT)
|
|
|
|
|
|
|
|
self.add(equation)
|
|
|
|
self.equation = equation
|
|
|
|
|
|
|
|
def shoot_a_few_photons(self):
|
|
|
|
for x in range(2):
|
|
|
|
self.play(self.photon)
|
|
|
|
|
|
|
|
def freeze_photon(self):
|
|
|
|
self.play(
|
|
|
|
self.photon,
|
|
|
|
rate_func = lambda x : 0.5*x,
|
|
|
|
run_time = 1
|
|
|
|
)
|
|
|
|
self.add(self.photon.mobject)
|
|
|
|
self.photon.rate_func = lambda x : x
|
|
|
|
self.photon.run_time = 2
|
|
|
|
|
|
|
|
def reposition_to_face_photon_head_on(self):
|
|
|
|
plane = NumberPlane(
|
|
|
|
color = LIGHT_GREY,
|
|
|
|
secondary_color = DARK_GREY,
|
|
|
|
x_unit_size = 2,
|
|
|
|
y_unit_size = 2,
|
|
|
|
y_radius = SPACE_WIDTH,
|
|
|
|
)
|
|
|
|
plane.add_coordinates(x_vals = range(-3, 4), y_vals = [])
|
|
|
|
plane.rotate(np.pi/2, RIGHT)
|
|
|
|
plane.rotate(np.pi/2, OUT)
|
|
|
|
|
|
|
|
self.play(self.em_wave.M_vects.set_fill, None, 0)
|
|
|
|
self.move_camera(
|
|
|
|
phi = np.pi/2, theta = 0,
|
|
|
|
added_anims = [
|
|
|
|
Rotate(self.equation, -self.camera.get_theta())
|
|
|
|
]
|
|
|
|
)
|
|
|
|
self.play(
|
|
|
|
Write(plane, run_time = 1),
|
|
|
|
Animation(self.equation)
|
|
|
|
)
|
|
|
|
|
|
|
|
self.xy_plane = plane
|
|
|
|
|
|
|
|
def show_components(self):
|
|
|
|
h_arrow, v_arrow = [
|
|
|
|
Vector(
|
|
|
|
1.38*direction,
|
|
|
|
color = color,
|
|
|
|
normal_vector = RIGHT,
|
|
|
|
)
|
|
|
|
for color, direction in (GREEN, UP), (RED, OUT)
|
|
|
|
]
|
|
|
|
v_arrow.move_to(h_arrow.get_end(), IN)
|
|
|
|
h_part = VGroup(*self.equation[1][2:4]).copy()
|
|
|
|
v_part = VGroup(*self.equation[1][5:7]).copy()
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
self.equation.rect.set_stroke, BLUE, 4,
|
|
|
|
self.equation.words.set_fill, WHITE, 1,
|
|
|
|
)
|
|
|
|
for part, arrow, d in (h_part, h_arrow, IN), (v_part, v_arrow, UP):
|
|
|
|
self.play(
|
|
|
|
part.next_to, arrow.get_center(), d,
|
|
|
|
ShowCreation(arrow)
|
|
|
|
)
|
|
|
|
part.rotate(np.pi/2, DOWN)
|
|
|
|
bg_rect = BackgroundRectangle(part)
|
|
|
|
bg_rect.stretch_in_place(1.3, 0)
|
|
|
|
part.add_to_back(bg_rect)
|
|
|
|
part.rotate(np.pi/2, UP)
|
|
|
|
self.add(part)
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
self.h_part_tex = h_part
|
|
|
|
self.h_arrow = h_arrow
|
|
|
|
self.v_part_tex = v_part
|
|
|
|
self.v_arrow = v_arrow
|
|
|
|
|
|
|
|
def show_amplitude_and_phase(self):
|
|
|
|
alpha = self.h_part_tex[1]
|
|
|
|
new_alpha = alpha.copy().shift(IN)
|
|
|
|
rhs = TexMobject(
|
|
|
|
"=", "A_x", "e",
|
|
|
|
"^{2\\pi", "f", "t", "+", "\\phi_x }"
|
|
|
|
)
|
|
|
|
A_rect = SurroundingRectangle(rhs.get_part_by_tex("A_x"), buff = 0.5*SMALL_BUFF)
|
|
|
|
A_word = TextMobject("Amplitude")
|
|
|
|
A_word.add_background_rectangle()
|
|
|
|
A_word.next_to(A_rect, DOWN, aligned_edge = LEFT)
|
|
|
|
A_group = VGroup(A_rect, A_word)
|
|
|
|
A_group.highlight(YELLOW)
|
|
|
|
phase_rect = SurroundingRectangle(VGroup(*rhs[3:]), buff = 0.5*SMALL_BUFF)
|
|
|
|
phase_word = TextMobject("Phase")
|
|
|
|
phase_word.add_background_rectangle()
|
|
|
|
phase_word.next_to(phase_rect, UP)
|
|
|
|
phase_group = VGroup(phase_word, phase_rect)
|
|
|
|
phase_group.highlight(MAROON_B)
|
|
|
|
rhs.add_background_rectangle()
|
|
|
|
|
|
|
|
group = VGroup(rhs, A_group, phase_group)
|
|
|
|
group.rotate(np.pi/2, RIGHT)
|
|
|
|
group.rotate(np.pi/2, OUT)
|
|
|
|
group.next_to(new_alpha, UP, SMALL_BUFF)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
ReplacementTransform(alpha.copy(), new_alpha),
|
|
|
|
FadeIn(rhs)
|
|
|
|
)
|
|
|
|
for word, rect in A_group, phase_group:
|
|
|
|
self.play(
|
|
|
|
ShowCreation(rect),
|
|
|
|
Write(word, run_time = 1)
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.play(*map(FadeOut, [new_alpha, group]))
|
|
|
|
|
|
|
|
def change_basis(self):
|
|
|
|
superposition = VGroup(*self.equation[1][2:])
|
|
|
|
plane = self.xy_plane
|
|
|
|
h_arrow = self.h_arrow
|
|
|
|
v_arrow = self.v_arrow
|
|
|
|
h_part = self.h_part_tex
|
|
|
|
v_part = self.v_part_tex
|
|
|
|
axes = self.axes
|
|
|
|
movers = [
|
|
|
|
plane, axes,
|
|
|
|
h_arrow, v_arrow,
|
|
|
|
h_part, v_part,
|
|
|
|
self.equation,
|
|
|
|
superposition,
|
|
|
|
]
|
|
|
|
for mob in movers:
|
|
|
|
mob.save_state()
|
|
|
|
|
|
|
|
superposition.target = TexMobject(
|
|
|
|
"\\gamma", "|\\! \\nearrow \\rangle", "+",
|
|
|
|
"\\delta", "|\\! \\nwarrow \\rangle",
|
|
|
|
)
|
|
|
|
superposition.target.highlight_by_tex("gamma", TEAL_D)
|
|
|
|
superposition.target.highlight_by_tex("delta", MAROON)
|
|
|
|
for part in superposition.target.get_parts_by_tex("rangle"):
|
|
|
|
part[1].rotate_in_place(-np.pi/12)
|
|
|
|
superposition.target.rotate(np.pi/2, RIGHT)
|
|
|
|
superposition.target.rotate(np.pi/2, OUT)
|
|
|
|
superposition.target.move_to(superposition)
|
|
|
|
|
|
|
|
for mob in plane, axes:
|
|
|
|
mob.generate_target()
|
|
|
|
mob.target.rotate(np.pi/6, RIGHT)
|
|
|
|
|
|
|
|
A = 1.9
|
|
|
|
h_arrow.target = Vector(
|
|
|
|
A*np.cos(np.pi/12)*rotate_vector(UP, np.pi/6, RIGHT),
|
|
|
|
normal_vector = RIGHT,
|
|
|
|
color = TEAL
|
|
|
|
)
|
|
|
|
v_arrow.target = Vector(
|
|
|
|
A*np.sin(np.pi/12)*rotate_vector(OUT, np.pi/6, RIGHT),
|
|
|
|
normal_vector = RIGHT,
|
|
|
|
color = MAROON
|
|
|
|
)
|
|
|
|
v_arrow.target.shift(h_arrow.target.get_vector())
|
|
|
|
|
|
|
|
h_part.target = VGroup(*superposition.target[:2]).copy()
|
|
|
|
v_part.target = VGroup(*superposition.target[3:]).copy()
|
|
|
|
h_part.target.next_to(
|
|
|
|
h_arrow.target.get_center(), IN+UP, SMALL_BUFF
|
|
|
|
)
|
|
|
|
v_part.target.next_to(
|
|
|
|
v_arrow.target.get_center(), UP, SMALL_BUFF
|
|
|
|
)
|
|
|
|
for part in h_part.target, v_part.target:
|
|
|
|
part.rotate(np.pi/2, DOWN)
|
|
|
|
part.add_to_back(BackgroundRectangle(part))
|
|
|
|
part.rotate(np.pi/2, UP)
|
|
|
|
|
|
|
|
self.equation.generate_target()
|
|
|
|
|
|
|
|
self.revert_to_original_skipping_status()
|
|
|
|
self.play(*map(MoveToTarget, movers))
|
|
|
|
self.dither(2)
|
|
|
|
self.play(*[mob.restore for mob in movers])
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
def write_different_meaning(self):
|
2017-09-01 19:52:12 -07:00
|
|
|
pass
|
2017-08-24 11:44:06 -07:00
|
|
|
|
2017-09-06 20:18:19 -07:00
|
|
|
def write_components(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def describe_via_energy(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def components_not_possible_in_isolation(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def ask_what_they_mean(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class SuperpositionHasDifferentInterpretation(TeacherStudentsScene):
|
|
|
|
def construct(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-08-24 11:44:06 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-01 10:41:27 -07:00
|
|
|
|
|
|
|
|
2017-08-24 11:44:06 -07:00
|
|
|
|
|
|
|
|
|
|
|
|