-
-
Notifications
You must be signed in to change notification settings - Fork 69
Open
Labels
bugSomething isn't workingSomething isn't workinglibRelated to the library (a.k.a. module)Related to the library (a.k.a. module)
Description
Terms
- Checked the existing issues and discussions to see if my issue had not already been reported;
- Checked the frequently asked questions;
- Read the installation instructions;
- Created a virtual environment in which I can reproduce my bug;
Describe the issue
Apparently, the rendering can stall when the animations are sufficiently large to be automatically cut into smaller pieces.
Command
manim-slides render main.py Main
Issue Type
Other
Python version
Python 3.11.12
Python environment
Manim Slides version: 5.5.2
Python executable: /export/home/eertmans/repositories/jeertmans.github.io/_slides/2023-07-17-siegen-presentation/.venv/bin/python3
Manim bindings:
manim (version: 0.19.0)
manimgl not found
Qt API: pyside6 (version: 6.9.2)What is your platform?
Linux
Other platform
No response
Manim Slides Python code
import numpy as np
import sympy as sy
from manim import *
from manim_slides import Slide
from shapely.geometry import LineString
"""
Some useful function required for the 'simple example'.
"""
def row(*args):
"""Create a symbol row (or col) vector from input arguments."""
return sy.Matrix(args)
def generate_c(as_gamma=False):
"""Return C(x) and it's derivative."""
# Unknowns
s1, s2 = sy.symbols("s_1 s_2", real=True) # s1, s2 are real values
# Geometry
# - Nodes
BS = row(2, -1)
UE = row(2, 4)
# - Interaction points
X1 = row(s1, s1)
X2 = row(5, s2)
# - Surface normals
n1 = row(1, -1).normalized()
n2 = row(-1, 0).normalized()
# - Aliases
V0 = X1 - BS
V1 = X2 - X1
V2 = UE - X2
if as_gamma:
g1 = sy.Function(r"\gamma_1", real=True)(s1, s2)
g2 = sy.Function(r"\gamma_2", real=True)(s1, s2)
else:
g1 = V0.norm() / V1.norm()
g2 = V1.norm() / V2.norm()
# Write different equations
eqs = [
g1 * V1 - (V0 - 2 * V0.dot(n1) * n1),
g2 * V2 - (V1 - 2 * V1.dot(n2) * n2),
]
F = sy.Matrix.vstack(*eqs)
f = F.norm() ** 2
_df = sy.lambdify((s1, s2), row(f.diff(s1), f.diff(s2)))
def df(x):
return _df(*x).reshape(-1)
return sy.lambdify((s1, s2), f), df
def generate_c_ris(phi=0):
"""Return C(x) and it's derivative for a RIS."""
# Unknowns
s1, s2 = sy.symbols("s_1 s_2", real=True) # s1, s2 are real values
# Geometry
# - Nodes
BS = row(2, -1)
UE = row(2, 4 - 0.5)
# - Interaction points
X1 = row(s1, s1)
X2 = row(5, s2)
# - Surface normals
n1 = row(1, -1).normalized()
n2 = row(-1, 0).normalized()
# Aliases
V0 = X1 - BS
V1 = X2 - X1
V2 = UE - X2
cross = n2[0] * V2[1] - n2[1] * V2[0]
g1 = V0.norm() / V1.norm()
# Write different equations
eqs = [
g1 * V1 - (V0 - 2 * V0.dot(n1) * n1),
row(cross - sy.sin(phi) * V2.norm()),
]
F = sy.Matrix.vstack(*eqs)
f = F.norm() ** 2
_df = sy.lambdify((s1, s2), row(f.diff(s1), f.diff(s2)))
def df(x):
return _df(*x).reshape(-1)
return sy.lambdify((s1, s2), f), df
def gradient_descent(x0, df, tol=1e-12, max_it=100, return_steps=False):
"""Perform a gradient descent using optimal alpha for linear systems."""
xa = x0
dfxa = df(xa)
xb = xa - 0.25 * dfxa # First step, alpha = .5
dfxb = df(xb)
dx = xb - xa
dfx = dfxb - dfxa
n_it = 1
steps = [dx]
while np.linalg.norm(dx) > tol and n_it < max_it:
alpha = np.dot(dx, dfx) / np.linalg.norm(dfx) ** 2
xa, xb = xb, xb - alpha * dfxb
dfxa, dfxb = dfxb, df(xb)
dx = xb - xa
dfx = dfxb - dfxa
n_it += 1
if return_steps:
steps.append(dx)
if return_steps:
return steps
return xb
"""
Here, because I switched the background from black to white,
so I have to make default color for most things to be black (instead of white).
"""
def black(func):
"""Sets default color to black"""
def wrapper(*args, color=BLACK, **kwargs):
return func(*args, color=color, **kwargs)
return wrapper
Tex = black(Tex)
Text = black(Text)
MathTex = black(MathTex)
Line = black(Line)
Dot = black(Dot)
Brace = black(Brace)
Arrow = black(Arrow)
Angle = black(Angle)
"""
Slides generation
"""
class Main(Slide):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.slide_no = None
self.slide_text = None
def write_slide_number(self, inital=1, text=Tex, animation=Write, position=ORIGIN):
self.slide_no = inital
self.slide_text = text(str(inital)).shift(position)
return animation(self.slide_text)
def update_slide_number(self, text=Tex, animation=Transform):
self.slide_no += 1
new_text = text(str(self.slide_no)).move_to(self.slide_text)
return animation(self.slide_text, new_text)
def construct(self):
self.camera.background_color = WHITE
WALL_COLOR = ORANGE
BS_COLOR = BLUE
UE_COLOR = MAROON_D
GOOD_COLOR = "#28C137"
BAD_COLOR = "#FF0000"
IMAGE_COLOR = "#636463"
X_COLOR = DARK_BROWN
NW = Dot().to_corner(UL)
NE = Dot().to_corner(UR)
SW = Dot().to_corner(DL)
SE = Dot().to_corner(DR)
NL = Line(NW.get_center(), NE.get_center()).set_color(WALL_COLOR)
SL = Line(SW.get_center(), SE.get_center()).set_color(WALL_COLOR)
WL = Line(NW.get_center(), SW.get_center()).set_color(WALL_COLOR)
EL = Line(NE.get_center(), SE.get_center()).set_color(WALL_COLOR)
slide_no_pos = SE.shift(0.15 * RIGHT + 0.2 * DOWN).get_center()
# TeX Preamble
tex_template = TexTemplate()
tex_template.add_to_preamble(
r"""
\usepackage{fontawesome5}
\usepackage{siunitx}
\DeclareSIQualifier\wattref{W}
\DeclareSIUnit\dbw{\decibel\wattref}
\usepackage{amsmath,amssymb,amsfonts,mathtools}
\newcommand{\bs}{\boldsymbol}
\newcommand{\scp}[3][]{#1\langle #2, #3 #1\rangle}
\newcommand{\bb}{\mathbb}
\newcommand{\cl}{\mathcal}
"""
)
# Slide: Title
title = VGroup(
Tex(
r"\textbf{Min-Path-Tracing}:\\A Diffraction Aware Alternative to \\Image Method in ",
r"Ray Tracing",
font_size=60,
),
Tex("Jérome Eertmans"),
).arrange(DOWN, buff=1)
self.play(FadeIn(title), self.write_slide_number(position=slide_no_pos))
self.next_slide()
# Slide: room
self.play(FadeOut(title), self.update_slide_number())
BS = Tex(r"\faWifi", tex_template=tex_template, color=BS_COLOR).shift(4 * LEFT)
UE = Tex(r"\faPhone", tex_template=tex_template, color=UE_COLOR).shift(
3 * RIGHT
)
self.play(
FadeIn(BS), FadeIn(UE), Create(NL), Create(SL), Create(WL), Create(EL)
)
self.next_slide()
A = BS.copy().shift(0.5 * RIGHT)
B = UE.copy().shift(0.5 * LEFT)
LOS = Arrow(
A.get_center(),
B.get_center(),
stroke_width=6,
buff=0.0,
)
self.play(Write(LOS))
self.next_slide()
# Slide: multiple paths in indoor environment
paths = VGroup()
x = LOS.get_center()[0]
for wall in [NL, SL]:
y = wall.get_center()[1]
middle = [x, y, 0]
path = VGroup(
Line(A.get_center(), middle, stroke_width=6),
Arrow(
middle,
Dot(UE.get_center()).shift(UP * 0.5 * np.sign(y) + 0.25 * LEFT),
stroke_width=6,
buff=0.0,
),
)
path.z_index = -1
paths.add(path)
for p in path:
self.play(Write(p))
self.wait(0.1)
self.next_slide()
channel = MathTex(r"P, \tau, \phi...")
channel.next_to(UE, UP + RIGHT)
self.play(Write(channel))
self.next_slide()
self.play(FadeOut(paths), FadeOut(channel))
self.next_slide()
# Slide: challenge
self.play(FadeOut(LOS))
how_to = Tex("How to find all paths?")
ray_tracing = Tex("Multiple methods exist!")
group = VGroup(how_to, ray_tracing).arrange(DOWN)
self.play(FadeIn(how_to))
self.next_slide()
self.play(FadeIn(ray_tracing, shift=UP))
self.next_slide()
# Slide: outline
_, sec1, sec2, sec3 = outline = VGroup(
Tex(r"\textbf{Outline:}"),
Tex("1. Image-based method"),
Tex("2. Our method"),
Tex(r"3. Future \& Applications"),
).arrange(DOWN)
for t in outline[2:]:
t.align_to(outline[1], LEFT)
self.play(FadeOut(group), self.update_slide_number())
self.play(FadeIn(outline[0]))
self.next_slide()
for t in outline[1:]:
self.play(FadeIn(t, shift=UP))
self.next_slide()
# Sec. 1
# Slide: simple example
outline -= sec1
self.play(FadeOut(outline), self.update_slide_number())
BS_dot, I1, I2, UE_dot, W1, W2, X1, X2 = locs = VGroup(
Dot([2, -1, 0], color=BS_COLOR),
Dot([-1, 2, 0], color=IMAGE_COLOR),
Dot([11, 2, 0], color=IMAGE_COLOR),
Dot([2, 4, 0], color=UE_COLOR),
Line([3.3, 3.3, 0], [0, 0, 0], color=WALL_COLOR),
Line([5, 4, 0], [5, 0.5, 0], color=WALL_COLOR),
Dot([20 / 7, 20 / 7, 0], color=X_COLOR, stroke_width=2, fill_color=WHITE),
Dot([5, 10 / 3, 0], color=X_COLOR, stroke_width=2, fill_color=WHITE),
)
locs.move_to(ORIGIN)
X_OFFSET, Y_OFFSET, _ = np.array([2, -1, 0]) - BS_dot.get_center()
self.play(
sec1.animate.to_corner(UL),
BS.animate.move_to(locs[0]),
UE.animate.move_to(locs[3]),
Transform(WL, W1),
Transform(EL, W2),
FadeOut(NL, shift=UP),
FadeOut(SL, shift=DOWN),
)
self.next_slide()
self.play(
Transform(BS, BS_dot),
Transform(UE, UE_dot),
)
self.next_slide()
LOS = Arrow(BS, UE)
self.play(Create(LOS))
self.next_slide()
self.play(LOS.animate.set_color(BAD_COLOR))
self.next_slide()
self.play(FadeOut(LOS))
self.next_slide()
arrow_1 = Arrow(BS, I1)
arrow_2 = Arrow(I1, I2)
right_angle_1 = RightAngle(arrow_1, W1, color=RED)
right_angle_2 = RightAngle(arrow_2, W2, color=RED)
self.play(Create(arrow_1), Create(right_angle_1))
self.play(FadeIn(I1))
self.next_slide()
self.play(FadeOut(arrow_1), FadeOut(right_angle_1))
self.play(Create(arrow_2), Create(right_angle_2))
self.play(FadeIn(I2))
self.play(FadeOut(arrow_2), FadeOut(right_angle_2))
self.next_slide()
line1 = Line(UE, I2)
line2 = Line(X2, I1)
self.play(Create(line1))
self.next_slide()
self.play(FadeIn(X2))
self.next_slide()
self.play(FadeOut(line1))
self.next_slide()
self.play(Create(line2))
self.play(FadeIn(X1))
self.play(FadeOut(line2))
self.next_slide()
path = VGroup(
Line(BS, X1),
Line(X1, X2),
Line(X2, UE),
)
for p in path:
self.play(Create(p))
self.play(path.animate.set_color(GOOD_COLOR))
self.next_slide()
# Slide: summary of image RT
old_objects = [
mob for mob in self.mobjects if mob not in [self.slide_text, sec1]
]
self.play(self.update_slide_number(), *[FadeOut(mob) for mob in old_objects])
path.set_color(BLACK)
pros = VGroup(
Tex(r"\textbf{Pros}"),
Tex(r"- Simple"),
Tex(r"- Fast - $\cl O (n)$", tex_template=tex_template),
).arrange(DOWN)
for pro in pros[1:]:
pro.align_to(pros[0], LEFT)
cons = VGroup(
Tex(r"\textbf{Cons}"),
Tex(r"- Limited to planar surfaces"),
Tex(r"- Specular reflection only"),
).arrange(DOWN)
for con in cons[1:]:
con.align_to(cons[0], LEFT)
summary = VGroup(
Tex("Summary:", font_size=60),
VGroup(pros, cons).arrange(RIGHT, buff=4),
).arrange(DOWN, buff=1)
self.play(FadeIn(summary[0]))
self.next_slide()
self.play(FadeIn(summary[1][0]))
self.next_slide()
self.play(FadeIn(summary[1][1]))
# Sec. 2
# Slide: MPT
self.next_slide()
sec2.to_corner(UL)
self.play(self.update_slide_number(), FadeOut(summary), Transform(sec1, sec2))
BS_ = BS.copy().move_to(ORIGIN)
UE_ = UE.copy().move_to(ORIGIN)
W1_ = Line([-1.5, 0, 0], [1.5, 0, 0], color=WALL_COLOR)
VGroup(VGroup(BS_, UE_).arrange(RIGHT, buff=5), W1_).arrange(DOWN, buff=3)
X1_ = X1.copy().move_to(W1_.get_center())
# Normal vector
NV_ = always_redraw(lambda: Line(X1_, X1_.get_center() + 3 * UP).add_tip())
VIN_ = always_redraw(lambda: Line(BS_, X1_))
VOUT_ = always_redraw(lambda: Line(X1_, UE_))
AIN_ = Angle(NV_, VIN_.copy().scale(-1), radius=1.01)
AIN_ = always_redraw(
lambda: Angle(NV_, VIN_.copy().scale(-1), radius=1.01, color=BS_COLOR)
)
AOUT_ = always_redraw(lambda: Angle(VOUT_, NV_, radius=1.01, color=UE_COLOR))
ain_ = DecimalNumber(AIN_.get_value(degrees=True), unit=r"^{\circ}")
ain_.next_to(AIN_, 2 * LEFT)
aout_ = DecimalNumber(AOUT_.get_value(degrees=True), unit=r"^{\circ}")
aout_.next_to(AOUT_, 2 * RIGHT)
angle_in_ = VGroup(AIN_, ain_)
angle_in_.set_color(BS_COLOR)
ain_.add_updater(
lambda m: m.set_value(
Angle(NV_, VIN_.copy().scale(-1)).get_value(degrees=True)
)
)
always(ain_.next_to, AIN_, 2 * LEFT)
angle_out_ = VGroup(AOUT_, aout_)
angle_out_.set_color(UE_COLOR)
aout_.add_updater(
lambda m: m.set_value(Angle(VOUT_, NV_).get_value(degrees=True))
)
always(aout_.next_to, AOUT_, 2 * RIGHT)
scene_ = VGroup(BS_, UE_, W1_, X1_, NV_, VIN_, VOUT_)
angles_ = VGroup(angle_in_, angle_out_)
self.play(FadeIn(scene_))
self.next_slide()
self.add(angles_)
self.wait(0.1)
self.next_slide()
def I_(BS, X1, UE):
vin = X1.get_center() - BS.get_center()
vout = UE.get_center() - X1.get_center()
n = np.array([0, 1, 0])
vin /= np.linalg.norm(vin)
vout /= np.linalg.norm(vout)
error = vout - (vin - 2 * np.dot(vin, n) * n)
return np.linalg.norm(error) ** 2
def C_(X1):
line_y = W1_.get_center()[1]
y = X1.get_center()[1]
return (y - line_y) ** 2
self.play(X1_.animate.move_to(W1_.get_start()))
self.play(X1_.animate.move_to(W1_.get_end()))
self.play(X1_.animate.move_to(W1_.get_center()))
self.wait(0.1)
self.next_slide()
cost, i_number, plus, c_number = cost_label = (
VGroup(
MathTex(r"\mathcal{C} =", tex_template=tex_template),
DecimalNumber(I_(BS_, X1_, UE_)),
MathTex("+"),
DecimalNumber(C_(X1_)),
)
.arrange(RIGHT)
.next_to(W1_, 2 * DOWN)
.set_color(BLUE)
)
def label_constructor(*args, **kwargs):
return MathTex(*args, tex_template=tex_template, **kwargs)
i_brace, c_brace = braces = VGroup(
BraceLabel(i_number, r"\cl I", label_constructor=label_constructor),
BraceLabel(c_number, r"\cl F", label_constructor=label_constructor),
).set_color(BLUE)
i_number.add_updater(lambda m: m.set_value(I_(BS_, X1_, UE_)))
c_number.add_updater(lambda m: m.set_value(C_(X1_)))
self.play(FadeIn(cost), FadeIn(i_number), FadeIn(i_brace))
self.next_slide()
self.play(X1_.animate.move_to(W1_.get_start()))
self.play(X1_.animate.move_to(W1_.get_end()))
self.play(X1_.animate.move_to(W1_.get_center()))
self.wait(0.1)
self.next_slide()
self.play(X1_.animate.shift(UP))
self.wait(0.1)
self.next_slide()
self.play(FadeIn(plus, c_number, c_brace))
self.next_slide()
self.play(X1_.animate.move_to(W1_.get_center()))
self.wait(0.1)
# Slide: any reflection
self.next_slide()
arc_ = Arc(
radius=1.5,
arc_center=X1_.copy().shift(1.5 * DOWN).get_center(),
color=WALL_COLOR,
start_angle=PI,
angle=-PI,
)
interaction = Tex("Reflection")
interaction.next_to(NV_, UP)
interaction_eq = MathTex(
r"\cl I \sim \hat{\bs r} = \hat{\bs \imath} - 2 \scp{\hat{\bs \imath}}{\hat{\bs n}}\hat{\bs n}",
tex_template=tex_template,
)
interaction_eq.to_corner(UR)
self.play(
FadeOut(cost_label),
FadeOut(braces),
FadeIn(interaction),
FadeIn(interaction_eq),
)
self.next_slide()
# Diffraction (setup)
DIFF_W1_A = Polygon(
W1_.get_start(),
W1_.get_end(),
W1_.get_end() + DOWN + 0.25 * LEFT,
W1_.get_start() + DOWN + 0.25 * LEFT,
stroke_opacity=0,
fill_color=WALL_COLOR,
fill_opacity=0.7,
)
DIFF_W1_B = Polygon(
W1_.get_start(),
W1_.get_end(),
W1_.get_end() + 0.8 * DOWN + 0.25 * RIGHT,
W1_.get_start() + 0.8 * DOWN + 0.25 * RIGHT,
stroke_opacity=0,
fill_color=WALL_COLOR,
fill_opacity=0.5,
)
D_NV_ = Line(X1_, X1_.get_center() + RIGHT * 3).add_tip()
D_AIN_ = Angle(
D_NV_.copy().scale(-1),
VIN_.copy().scale(-1),
radius=1.01,
other_angle=True,
color=BS_COLOR,
)
D_AOUT_ = Angle(VOUT_, D_NV_, radius=1.01, other_angle=True, color=UE_COLOR)
D_ain_ = DecimalNumber(
D_AIN_.get_value(degrees=True), unit=r"^{\circ}", color=BS_COLOR
)
D_ain_.next_to(D_AIN_, 2 * LEFT)
D_aout_ = DecimalNumber(
D_AOUT_.get_value(degrees=True), unit=r"^{\circ}", color=UE_COLOR
)
D_aout_.next_to(D_AOUT_, 2 * RIGHT)
# Slide: reflection on sphere
W1_.save_state()
self.play(Transform(W1_, arc_))
self.next_slide()
# Slide: reflection on metasurface
UE_.save_state()
phi = MathTex(r"\phi", color=UE_COLOR).move_to(aout_.get_center())
self.play(
Restore(W1_),
UE_.animate.shift(RIGHT),
FadeTransform(aout_, phi),
Transform(
interaction, Tex("Reflection on metasurfaces").move_to(interaction)
),
Transform(
interaction_eq,
MathTex(
r"\cl I \sim \bs r = f(\hat{\bs n}, \phi)",
tex_template=tex_template,
).to_corner(UR),
),
)
self.next_slide()
# Slide: diffraction
refl_config = VGroup(NV_, AIN_, AOUT_, ain_, aout_)
diff_config = VGroup(D_NV_, D_AIN_, D_AOUT_, D_ain_, D_aout_)
refl_config.save_state()
self.play(
*[
Transform(refl, diff)
if not isinstance(refl, DecimalNumber)
else FadeTransform(refl, diff)
for refl, diff in zip(refl_config, diff_config)
],
Restore(W1_),
Restore(UE_),
FadeOut(phi),
FadeIn(DIFF_W1_B),
FadeIn(DIFF_W1_A),
Transform(interaction, Tex("Diffraction").move_to(interaction)),
Transform(
interaction_eq,
MathTex(
r"\cl I \sim \frac{\scp{\bs i}{\hat{\bs e}}}{\| \bs i \|} = \frac{\scp{\bs d}{\hat{\bs e}}}{\|\bs d\|}",
tex_template=tex_template,
).to_corner(UR),
),
)
self.remove(*refl_config)
self.add(*diff_config)
self.next_slide()
# Slide: refraction
(UE_.shift(DOWN * 4),)
R_NV_ = Line(X1_, X1_.get_center() + UP * 3).add_tip()
R_AIN_ = Angle(
R_NV_,
VIN_.copy().scale(-1),
radius=1.01,
color=BS_COLOR,
)
R_AOUT_ = Angle(
R_NV_.copy().scale(-1), Line(X1_, UE_), radius=1.01, color=UE_COLOR
)
R_ain_ = DecimalNumber(
R_AIN_.get_value(degrees=True), unit=r"^{\circ}", color=BS_COLOR
)
R_ain_.next_to(R_AIN_, 2 * LEFT)
R_aout_ = DecimalNumber(
R_AOUT_.get_value(degrees=True), unit=r"^{\circ}", color=UE_COLOR
)
R_aout_.next_to(R_AOUT_, DR + RIGHT)
refr_config = VGroup(R_NV_, R_AIN_, R_AOUT_, R_ain_, R_aout_)
dashed = DashedLine(X1_, X1_.get_center() + 2 * DOWN, color=GRAY)
self.play(
Write(dashed),
FadeOut(DIFF_W1_A),
FadeOut(DIFF_W1_B),
*[
Transform(refl, diff)
if not isinstance(refl, DecimalNumber)
else FadeTransform(refl, diff)
for refl, diff in zip(diff_config, refr_config)
],
Transform(interaction, Tex("Refraction").move_to(interaction)),
Transform(
interaction_eq,
MathTex(
r"\cl I \sim v_1 \sin(\theta_2) = v_2 \sin(\theta_1)",
tex_template=tex_template,
).to_corner(UR),
),
)
self.remove(*diff_config)
self.add(*refr_config)
self.next_slide()
self.play(
FadeOut(dashed),
FadeOut(refr_config),
FadeOut(scene_),
FadeOut(interaction),
FadeOut(interaction_eq),
self.update_slide_number(),
)
self.next_slide()
minimize_eq = Tex(
r"\[\underset{\bs{\cl X} \in \bb R^{n_t}}{\text{minimize}}\ \cl C(\bs{\cl X}) := \|\cl I(\bs{\cl X})\|^2 + \|\cl F(\bs{\cl X})\|^2\]",
tex_template=tex_template,
)
nt_eq = Tex("where $n_t$ is the total number of unknowns").shift(DOWN)
constraint_eq = MathTex(
r"\cl C(\bs{\cl X})", r"= 0", tex_template=tex_template
).shift(2 * DOWN)
constraint_eq_relaxed = MathTex(
r"\cl C(\bs{\cl X})", r"\le \epsilon", tex_template=tex_template
).shift(2 * DOWN)
self.play(FadeIn(minimize_eq))
self.next_slide()
self.play(FadeIn(nt_eq, shift=DOWN))
self.next_slide()
self.play(FadeIn(constraint_eq))
self.next_slide()
self.play(Transform(constraint_eq, constraint_eq_relaxed))
self.next_slide()
if_we_know = Tex(
r"If we know a mapping s.t. $(x_k, y_k) \leftrightarrow t_k$"
).shift(UP)
self.play(
FadeIn(if_we_know),
)
self.next_slide()
self.play(
Transform(
minimize_eq,
Tex(
r"\[\underset{\bs{\cl T} \in \bb R^{n_r}}{\text{minimize}}\ \cl C(\bs{\cl X}(\bs{\cl T})) := \|\cl I(\bs{\cl X }(\bs{\cl T}))\|^2\]",
tex_template=tex_template,
).move_to(minimize_eq),
),
Transform(
nt_eq,
Tex("where $n_r$ is the total number of (2d) reflections").move_to(
nt_eq
),
),
Transform(
constraint_eq,
MathTex(
r"\cl C(\bs{\cl X(\cl T)})",
r"\le \epsilon",
tex_template=tex_template,
).move_to(constraint_eq),
),
)
self.next_slide()
# Slide: gradient descent on simple example using MPT method
self.play(
FadeOut(if_we_know),
FadeOut(minimize_eq),
FadeOut(nt_eq),
FadeOut(constraint_eq),
self.update_slide_number(),
)
X1.move_to(W1.get_center())
X2.move_to(W2.get_center())
def intersects(l1, l2):
l1 = LineString([l1.get_start()[:-1], l1.get_end()[:-1]])
l2 = LineString([l2.get_start()[:-1], l2.get_end()[:-1]])
return l1.intersects(l2)
old_objects.remove(I1)
old_objects.remove(I2)
path.remove(*path)
path.add(
always_redraw(lambda: Line(BS, X1)),
always_redraw(lambda: Line(X1, X2)),
always_redraw(
lambda: Line(
X2, UE, color=BAD_COLOR if intersects(Line(X2, UE), W1) else BLACK
)
),
)
self.play(*[FadeIn(mob) for mob in old_objects])
self.next_slide()
# Slide: animate actual gradient descent
f, df = generate_c()
def remap(X1, X2):
s1 = X1.get_center()[0]
s2 = X2.get_center()[1]
return s1 + X_OFFSET, s2 + Y_OFFSET
cost_label, f_number = f_label = VGroup(
MathTex(r"\mathcal{C} = ", tex_template=tex_template),
DecimalNumber(
f(*remap(X1, X2)), # f(s1, s2)
num_decimal_places=2,
include_sign=False,
),
)
f_label.set_color(BLUE)
f_label.arrange(RIGHT)
f_label.next_to(W2, RIGHT)
always(f_label.next_to, W2, RIGHT)
f_always(f_number.set_value, lambda: f(*remap(X1, X2)))
cost_eq = MathTex(
r"\|[\cl I_1(t_1, t_2); \cl I_2(t_1,t_2)] \|^2",
tex_template=tex_template,
color=BLUE,
font_size=40,
).next_to(cost_label, RIGHT)
cost_eq_full = MathTex(
r"&\left(- t_1 + t_2 + \frac{\left(t_2 - 4\right) \sqrt{\left(t_1 - 5\right)^{2} + \left(t_1 - t_2\right)^{2}}}{\sqrt{\left(t_2 - 4\right)^{2} + 9}}\right)^{2} \\+& \left(t_1 + \frac{3 \sqrt{\left(t_1 - 5\right)^{2} + \left(t_1 - t_2\right)^{2}}}{\sqrt{\left(t_2 - 4\right)^{2} + 9}} - 5\right)^{2} \\+& \Bigg|{t_1 + \frac{\left(t_1 - 5\right) \sqrt{\left(t_1 - 2\right)^{2} + \left(t_1 + 1\right)^{2}}}{\sqrt{\left(t_1 - 5\right)^{2} + \left(t_1 - t_2\right)^{2}}} - \frac{\sqrt{2} \left(\sqrt{2} \left(t_1 - 2\right) - \sqrt{2} \left(t_1 + 1\right)\right)}{2} - 2}\Bigg|^{2} \\+& \left|{t_1 + \frac{\left(t_1 - t_2\right) \sqrt{\left(t_1 - 2\right)^{2} + \left(t_1 + 1\right)^{2}}}{\sqrt{\left(t_1 - 5\right)^{2} + \left(t_1 - t_2\right)^{2}}} + \frac{\sqrt{2} \left(\sqrt{2} \left(t_1 - 2\right) - \sqrt{2} \left(t_1 + 1\right)\right)}{2} + 1}\right|^{2}",
color=BLUE,
font_size=16,
).next_to(cost_label, RIGHT)
self.play(FadeIn(cost_label), FadeIn(cost_eq))
self.next_slide()
self.play(Transform(cost_eq, cost_eq_full))
self.next_slide()
self.play(FadeTransform(cost_eq, f_number))
self.next_slide()
x0 = remap(X1, X2)
for ds1, ds2 in gradient_descent(x0, df, return_steps=True):
self.play(
X1.animate.shift([ds1, ds1, 0]),
X2.animate.shift([0, ds2, 0]),
run_time=1.3,
)
self.wait(0.1)
self.next_slide()
# Slide: what if METASURFACE?
what_if_ms_text = Tex("What if we had a metasurface?").to_corner(UR)
ms_text = Tex(r"$\phi=0$", color=GREEN).next_to(W2).shift(DOWN)
self.play(FadeIn(what_if_ms_text))
self.next_slide()
self.play(UE.animate.shift(np.array([0, -0.5, 0])))
self.play(EL.animate.set_color(GREEN)) # EL is W2
self.play(FadeIn(ms_text))
f, df = generate_c_ris()
_, f_number = f_label = VGroup(
MathTex(r"\mathcal{C} = ", tex_template=tex_template),
DecimalNumber(
f(*remap(X1, X2)), # f(s1, s2)
num_decimal_places=2,
include_sign=False,
),
)
f_label.set_color(BLUE)
f_label.arrange(RIGHT)
f_label.next_to(W2, RIGHT)
always(f_label.next_to, W2, RIGHT)
f_always(f_number.set_value, lambda: f(*remap(X1, X2)))
self.play(FadeIn(f_label, shift=UP))
self.next_slide()
x0 = remap(X1, X2)
for ds1, ds2 in gradient_descent(x0, df, return_steps=True):
self.play(
X1.animate.shift([ds1, ds1, 0]),
X2.animate.shift([0, ds2, 0]),
run_time=0.6,
)
self.next_slide()
# Sec. 3
sec3.to_corner(UL)
self.play(*[FadeOut(mob) for mob in self.mobjects])
self.play(self.update_slide_number(), Transform(sec1, sec3))
self.next_slide()
geom = SVGMobject("geometry.svg").scale(5)
tabl = Tex(
r"""
\begin{tabular}{l|r|r|r|r|r|r|r|r|r|r|r}
Number of interactions & \multicolumn{1}{r}{1} & \multicolumn{3}{r}{2} & \multicolumn{7}{r}{3} \\
\hline\\
Interactions list & D & RD & DR & DD & RRD & RDR & RDD & DRR & DRD & DDR & DDD \\
$E/E_\text{LOS}$ (\si{\decibel}) & \textbf{-32} & -236 & -242 & \textbf{-44} & -231 & -246 & \textbf{-69} & -212 & \textbf{-72} & -81 & \textbf{-60} \\
\end{tabular}
""",
tex_template=tex_template,
)
results = VGroup(geom, tabl).arrange(DOWN, buff=2).scale(0.4)
self.play(FadeIn(geom))
self.next_slide()
self.play(FadeIn(tabl))
self.next_slide()
# Slide: summary of MPT method
self.play(FadeOut(results), self.update_slide_number())
pros = (
VGroup(
Tex(r"\textbf{Pros}"),
Tex(r"- Any geometry (but requires more info.)"),
Tex(r"- Any \# of reflect., diff., and refract."),
Tex(r"- Allows for multiple solutions"),
Tex(r"- Optimizer can be chosen"),
)
.scale(0.5)
.arrange(DOWN)
)
for pro in pros[1:]:
pro.align_to(pros[0], LEFT)
cons = (
VGroup(
Tex(r"\textbf{Cons}"),
Tex(r"- In general, problem is not convex"),
Tex(r"- Slower - $\cl O (k \cdot n)$", tex_template=tex_template),
)
.scale(0.5)
.arrange(DOWN)
)
for con in cons[1:]:
con.align_to(cons[0], LEFT)
summary = VGroup(
Tex("Summary:", font_size=60),
VGroup(pros, cons).arrange(RIGHT, buff=2),
).arrange(DOWN, buff=1)
cons.align_to(pros, UP)
self.play(FadeIn(summary[0]))
self.next_slide()
self.play(FadeIn(summary[1][0]))
self.next_slide()
self.play(FadeIn(summary[1][1]))
future = VGroup(
Tex(r"\textbf{Future work:}"),
Tex(r"- Compare with Ray Launching"),
Tex(r"- Discuss different solvers / minimizers"),
).arrange(DOWN)
for t in future[2:]:
t.align_to(future[1], LEFT)
self.next_slide()
self.play(FadeOut(summary), self.update_slide_number())
self.play(FadeIn(future))
self.next_slide()
# Slide: fade out everything and thanks
self.play(*[FadeOut(mob) for mob in self.mobjects])
thanks = Tex("Thanks for listening!").scale(2)
self.play(FadeIn(thanks))
self.wait()
self.next_slide()Relevant log output
Screenshots
No response
Additional information
No response
Recommended fix or suggestions
A temporary fix is to add the following line to the class definition:
class Main(Slide):
max_duration_before_split_reverse = Noneas it will disable the split-reverse feature.
lucas0817 and seanhrichardson
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workinglibRelated to the library (a.k.a. module)Related to the library (a.k.a. module)