diff options
-rw-r--r-- | video/qam.py | 104 |
1 files changed, 96 insertions, 8 deletions
diff --git a/video/qam.py b/video/qam.py index 88096e9..711fb04 100644 --- a/video/qam.py +++ b/video/qam.py @@ -1,6 +1,18 @@ from manimlib import * from scipy import signal as sig +def square(t, slew_rate=.1): + t = t % 1 + + if t < .1: + return t * 1 / slew_rate + elif t < .5 - slew_rate / 2: + return 1 + elif t < .5 + slew_rate / 2: + return 1 - (t - (.5 - slew_rate / 2)) * 1 / slew_rate + else: + return 0 + class TimeDependentComplexPlane(ComplexPlane): CONFIG = { @@ -29,6 +41,9 @@ class TimeDependentComplexPlane(ComplexPlane): def number_to_point(self, number, time=0): return self.coords_to_point(number.real, number.imag, time) + def point_to_number(self, point, time=0): + return point[0] + 1j * point[1] + def n2p(self, number, time=0): return self.number_to_point(number, time) @@ -65,23 +80,96 @@ class QamModulation(Scene): CONFIG = {} def construct(self): - cplane = TimeDependentComplexPlane() + self.camera.frame.reorient(0, 0, 0) + # create a complex plane + cplane = TimeDependentComplexPlane() self.play(ShowCreation(cplane)) - self.play(self.camera.frame.animate.move_to(2 * OUT)) - graph_y = cplane.get_inphase_graph(lambda t: 2 * np.cos(2 * t), color=RED) - graph_x = cplane.get_quadrature_graph(lambda t: 1 * sig.square(4 * t), color=BLUE) + # a complex number + dot = Dot(cplane.n2p(1 + 2j), color=GREEN) + + number = DecimalNumber() + + number.add_updater(lambda m: m.next_to(dot, RIGHT)) + + def update_nums(m): + x, y, z = dot.get_center() + num = cplane.p2n((x,y)) + m.set_value(num) + + number.add_updater(update_nums) + + # create and move complex number around + self.play(ShowCreation(dot), ShowCreation(number)) + self.play(dot.animate.move_to(cplane.n2p(-5+3j)), run_time=2) + self.play(dot.animate.move_to(cplane.n2p(-4-3j)), run_time=2) + + # move the number according to a time dependend complex function + def signal_func(t): + real = -2 * np.cos(2 * t) + imag = 3 * (square(t / 2) - .5) + + return real + 1j * imag + + signal_func_at_zero = signal_func(0) - self.play(self.camera.frame.animate.reorient(90, 90, 90)) + self.play(dot.animate.move_to(cplane.n2p(signal_func_at_zero)), run_time=2) + + def dot_update_func(m, dt): + m.move_to(cplane.n2p(signal_func(m.time))) + m.time = m.time + dt / 2 + + dot.time = 0 + dot.add_updater(dot_update_func) + self.wait(5) + + # get out and show time dependence + self.play(self.camera.frame.animate.shift(2 * OUT)) + + # show functions + graph_y = cplane.get_inphase_graph(lambda t: signal_func(t).real, color=RED) + graph_x = cplane.get_quadrature_graph(lambda t: signal_func(t).imag, color=BLUE) + + self.play(self.camera.frame.animate.reorient(-90, 90, 90)) self.play(ShowCreation(graph_x)) self.play(self.camera.frame.animate.reorient(0, 90, 90)) self.play(ShowCreation(graph_y)) - self.play(self.camera.frame.animate.reorient(80, 90, 90)) + self.play(self.camera.frame.animate.reorient(-100, 90, 90)) + self.play(self.camera.frame.animate.rotate(40 * DEGREES, axis = UP)) + + # create arrow for complex value + dot.remove_updater(dot_update_func) + self.play(dot.animate.move_to(cplane.n2p(signal_func_at_zero)), run_time=2) + + arr = Arrow(cplane.n2p(0), cplane.n2p(signal_func_at_zero)) + self.play(ShowCreation(arr)) + + def arr_update_func(m, dt): + m.set_points_by_ends( + cplane.n2p(0, time=m.time), + cplane.n2p(signal_func(m.time), time=m.time) + ) + m.time = m.time + dt / 2 + + dot.time = 0 + arr.time = 0 + + dot.add_updater(dot_update_func) + arr.add_updater(arr_update_func) + self.wait(10) + + self.play(*map(FadeOut, (arr, graph_x, graph_y))) + self.play( + self.camera.frame.animate.rotate(50 * DEGREES, axis = UP), + dot.animate.move_to(cplane.n2p(1+1j)) + ) + self.play(self.camera.frame.animate.shift(-2 * OUT)) - # arrow = Arrow( + dot.remove_updater(dot_update_func) + arr.remove_updater(arr_update_func) # open an interactive IPython shell here - self.embed() + # self.embed() |