diff options
| author | Elvis Claros Castro <elvis@claros.ar> | 2026-09-26 20:21:47 -0300 |
|---|---|---|
| committer | Elvis Claros Castro <elvis@claros.ar> | 2026-09-26 20:21:47 -0300 |
| commit | 59355909f2de9236af8168a26c70bcf6caa3b285 (patch) | |
| tree | 686186e2086f81aa22ad25e78eb29fca3cbadc9a /scenes/v16_bayes.py | |
| download | 100cia-videos-59355909f2de9236af8168a26c70bcf6caa3b285.tar.gz 100cia-videos-59355909f2de9236af8168a26c70bcf6caa3b285.zip | |
Import video pipeline as it was
Diffstat (limited to 'scenes/v16_bayes.py')
| -rw-r--r-- | scenes/v16_bayes.py | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/scenes/v16_bayes.py b/scenes/v16_bayes.py new file mode 100644 index 0000000..311dd01 --- /dev/null +++ b/scenes/v16_bayes.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +import sys, os +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from manim import * +from tiktok import * + +COLS, ROWS = 25, 40 +PX, PY = 0.27, 0.175 +GY = 1.65 # centro vertical de la grilla +RAD = 0.062 +APAGADO = "#2B3A5C" +ENFERMA = 437 # fila 17, columna 12 (queda centrada) +FALSOS = [63, 147, 232, 318, 389, 476, 551, 668, 742, 861] + + +def pos(i): + r, c = divmod(i, COLS) + return np.array([(c - (COLS - 1) / 2) * PX, + GY + ((ROWS - 1) / 2 - r) * PY, 0.0]) + + +class Bayes(TikTok): + NAME = "bayes" + + def construct(self): + self.prepare() + chip = self.chip("Probabilidad", CELESTE) + + # --- la tarjeta del test --------------------------------------------- + marco = RoundedRectangle(corner_radius=0.32, width=6.4, height=3.4, stroke_width=5, + stroke_color=CELESTE, fill_color="#121C33", + fill_opacity=1).move_to(UP * 3.5) + et = Text("TEST", font=FONT, font_size=40, weight=BOLD, color=GRIS) + num = Text("99%", font=FONT, font_size=118, weight=BOLD, color=AMBAR) + pie = Text("de precisión", font=FONT, font_size=38, weight=BOLD, color=WHITE) + VGroup(et, num, pie).arrange(DOWN, buff=0.18).move_to(marco) + tarjeta = VGroup(marco, et, num, pie) + + with self.beat(0) as b: + b.play(FadeIn(chip, shift=DOWN * 0.3), run_time=0.4) + b.play(GrowFromCenter(tarjeta), run_time=0.8) + b.play(Flash(num, color=AMBAR, line_length=0.35, num_lines=14, + flash_radius=1.7), run_time=0.9) + + sello = VGroup( + RoundedRectangle(corner_radius=0.18, width=4.7, height=1.25, stroke_width=8, + stroke_color=ROSA, fill_color="#2A0E18", fill_opacity=0.94), + Text("POSITIVO", font=FONT, font_size=60, weight=BOLD, color=ROSA)) + sello.rotate(-0.09).move_to(marco.get_bottom() + DOWN * 0.05) + + with self.beat(1) as b: + b.play(FadeIn(sello, scale=2.4), run_time=0.55) + b.play(Wiggle(sello, scale_value=1.07), run_time=1.0) + + preg = Text("La mayoría contesta:", font=FONT, font_size=40, + weight=BOLD, color=GRIS).move_to(UP * 0.45) + mal = Text("99%", font=FONT, font_size=106, weight=BOLD, color=GRIS) + mal.next_to(preg, DOWN, buff=0.28) + + with self.beat(2) as b: + b.play(FadeIn(preg, shift=UP * 0.2), run_time=0.5) + b.play(FadeIn(mal, scale=0.7), run_time=0.7) + + tacha = Line(mal.get_left() + LEFT * 0.28, mal.get_right() + RIGHT * 0.28, + stroke_width=11, color=ROSA) + bien = Text("9%", font=FONT, font_size=150, weight=BOLD, + color=VERDE).move_to(DOWN * 2.05) + + with self.beat(3) as b: + b.play(Create(tacha), run_time=0.45) + b.play(FadeIn(bien, scale=0.6), run_time=0.7) + b.play(Flash(bien, color=VERDE, flash_radius=1.7, num_lines=16), run_time=0.9) + + # --- las mil personas ------------------------------------------------- + puntos = VGroup(*[Dot(radius=RAD, color=APAGADO, fill_opacity=1).move_to(pos(i)) + for i in range(COLS * ROWS)]) + rotulo = Text("1.000 personas", font=FONT, font_size=40, weight=BOLD, + color=WHITE).move_to(UP * 5.55) + + with self.beat(4) as b: + b.play(FadeOut(VGroup(tarjeta, sello, preg, mal, tacha, bien)), run_time=0.5) + b.play(FadeIn(puntos, lag_ratio=0), FadeIn(rotulo, shift=DOWN * 0.2), + run_time=1.1) + + enf = puntos[ENFERMA] + anillo = Circle(radius=0.30, stroke_width=6, color=ROSA).move_to(pos(ENFERMA)) + cajita = RoundedRectangle(corner_radius=0.14, width=2.45, height=0.7, stroke_width=0, + fill_color="#0B0F1A", fill_opacity=0.92) + txt = Text("1 enferma", font=FONT, font_size=34, weight=BOLD, color=ROSA) + etiq = VGroup(cajita, txt).move_to(pos(ENFERMA) + RIGHT * 1.95) + guia = Line(anillo.get_right(), etiq.get_left(), stroke_width=4, color=ROSA) + + with self.beat(5) as b: + b.play(enf.animate.set_color(ROSA).scale(2.2), run_time=0.5) + b.play(Create(anillo), run_time=0.4) + b.play(Create(guia), FadeIn(etiq), run_time=0.5) + + # --- el barrido del test ---------------------------------------------- + barrido = Line(LEFT * 3.6, RIGHT * 3.6, stroke_width=6, color=CELESTE) + barrido.move_to([0, pos(0)[1] + 0.22, 0]) + ley1 = VGroup(Dot(radius=0.12, color=ROSA), + Text("1 positivo verdadero", font=FONT, font_size=36, + weight=BOLD, color=WHITE)).arrange(RIGHT, buff=0.26) + ley1.move_to(DOWN * 2.15) + + with self.beat(6) as b: + b.play(FadeIn(barrido), run_time=0.25) + b.play(barrido.animate.move_to([0, pos(COLS * ROWS - 1)[1] - 0.22, 0]), + run_time=max(0.9, b.floor - 1.5), rate_func=linear) + b.play(FadeOut(barrido), + Flash(anillo, color=VERDE, flash_radius=0.65, num_lines=12), + run_time=0.5) + b.add(ley1) + + # --- los falsos positivos --------------------------------------------- + falsos = VGroup(*[puntos[i] for i in FALSOS]) + + with self.beat(7) as b: + b.play(LaggedStart(*[p.animate.set_color(AMBAR).scale(2.2) for p in falsos], + lag_ratio=0.2), run_time=max(1.3, b.floor - 0.7)) + + ley2 = VGroup(Dot(radius=0.12, color=AMBAR), + Text("10 falsos positivos", font=FONT, font_size=36, + weight=BOLD, color=WHITE)).arrange(RIGHT, buff=0.26) + ley2.move_to(DOWN * 2.78) + + with self.beat(8) as b: + b.play(FadeIn(ley2, shift=UP * 0.2), run_time=0.45) + b.play(*[Indicate(p, color=AMBAR, scale_factor=1.7) for p in falsos], + run_time=1.1) + + # --- los once positivos, en fila -------------------------------------- + marcados = set(FALSOS) | {ENFERMA} + resto = VGroup(*[p for j, p in enumerate(puntos) if j not in marcados]) + elegidos = [puntos[ENFERMA]] + [puntos[i] for i in FALSOS] + cuenta = Text("11 positivos", font=FONT, font_size=52, weight=BOLD, + color=WHITE).move_to(UP * 2.2) + frac = Text("1 de 11 = 9%", font=FONT, font_size=90, weight=BOLD, + color=VERDE).move_to(UP * 0.7) + + with self.beat(9) as b: + b.play(resto.animate.set_opacity(0.12), + FadeOut(VGroup(anillo, guia, etiq, rotulo, ley1, ley2)), run_time=0.5) + b.play(*[p.animate.move_to([(k - 5) * 0.62, 3.35, 0]).scale(2.4) + for k, p in enumerate(elegidos)], run_time=0.9) + b.play(FadeIn(cuenta, shift=UP * 0.2), run_time=0.4) + b.play(FadeIn(frac, scale=0.7), run_time=0.6) + + cierre = VGroup( + Text("Si la enfermedad es rara,", font=FONT, font_size=42, weight=BOLD, color=GRIS), + Text("un positivo suelto", font=FONT, font_size=50, weight=BOLD, color=WHITE), + Text("casi siempre es falso", font=FONT, font_size=50, weight=BOLD, color=AMBAR), + ).arrange(DOWN, buff=0.32).move_to(DOWN * 1.75) + + with self.beat(10) as b: + b.play(FadeOut(resto), run_time=0.4) + b.play(FadeIn(cierre, shift=UP * 0.25), run_time=0.8) + b.play(Flash(frac, color=VERDE, flash_radius=2.2, num_lines=18), run_time=0.9) + + self.finish() |