├── 2021 ├── Car.svg ├── Car_Oben.svg ├── Left_Hand_Rule_Up.svg ├── Opening-Book.svg ├── Pin.svg ├── Right_Hand_Rule_Down.svg ├── Right_Hand_Rule_Up.svg ├── Right_Hand_Rule_Winding.svg ├── TrigFunc-Parameter-a.py ├── TrigFunc-Parameter-b.py ├── Vektoren-RMV-Addition.py ├── Vektoren-RMV-Intros.py ├── Vektoren-RMV-Linearkombination.py ├── Vektoren-RMV-SkalareMultiplikation.py ├── Vektoren-RMV-Skalarprodukt.py ├── Vektoren-RMV-Subtraktion.py ├── Vektoren-RMV-Trailer.py ├── Vektoren-RMV-Vektorprodukt.py └── video_icon.svg ├── 2022 ├── Binomial Distribution │ ├── Binom-00-Trailer.py │ ├── Binom-01-BExp.py │ ├── Binom-02-BTrail.py │ ├── Binom-03-BFormula.py │ ├── Binom-04-Hist.py │ ├── Binom-05-ExpValue.py │ ├── Binom-06-HistProp.py │ ├── Binom-07-Kum.py │ ├── Binom-08-KumTables.py │ ├── Binom-09-Mindestens-Hoechstens.py │ ├── BinomHelper.py │ └── SVGs and IMGs │ │ ├── Blood_Donation.svg │ │ ├── BrainBulb.svg │ │ ├── GummyBear.svg │ │ ├── Jakob_Bernoulli.jpg │ │ ├── Rabbit.svg │ │ ├── biathlon-shoot.svg │ │ ├── biathlon-skiing.svg │ │ ├── clubs.svg │ │ ├── diamonds.svg │ │ ├── emoji_couple_holding_hands.svg │ │ ├── emoji_couple_holding_hands_ww.svg │ │ ├── emoji_heart_eyes.svg │ │ ├── emoji_middle_finger.svg │ │ ├── emoji_sunglas.svg │ │ ├── hearts.svg │ │ ├── human_body_back.svg │ │ ├── open-tafelwerk-tables.png │ │ ├── rose_illustration.svg │ │ ├── smartphone.svg │ │ ├── smartwatch.svg │ │ ├── spades.svg │ │ ├── table_binom_cdf_100.png │ │ ├── table_binom_cdf_10_20_25.png │ │ └── table_binom_cdf_50.png ├── Hypotests-01-Links.py ├── Hypotests-02-Links-Alpha.py ├── TrigFunc-All-Parameters.py ├── TrigFunc-Parameter-c.py └── TrigFunc-Parameter-d.py └── README.md /2021/Car.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 16 | 22 | 24 | 58 | 63 | 65 | 67 | 68 | -------------------------------------------------------------------------------- /2021/Car_Oben.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 15 | 16 | 22 | 23 | 26 | 30 | 32 | 34 | 37 | 40 | 42 | 44 | 46 | 48 | 50 | 51 | 52 | 53 | 54 | 63 | 66 | 72 | 74 | 77 | 79 | 82 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /2021/Left_Hand_Rule_Up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /2021/Pin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 15 | 22 | 24 | 26 | 30 | 31 | -------------------------------------------------------------------------------- /2021/Right_Hand_Rule_Down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 8 | 25 | 32 | 39 | 41 | 43 | 45 | 49 | 53 | 55 | 57 | 58 | -------------------------------------------------------------------------------- /2021/Right_Hand_Rule_Up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 23 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /2021/Right_Hand_Rule_Winding.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 15 | 24 | 28 | 31 | 35 | 41 | 42 | -------------------------------------------------------------------------------- /2021/Vektoren-RMV-Intros.py: -------------------------------------------------------------------------------- 1 | from manim import * 2 | 3 | vec_a_color = RED 4 | vec_b_color = YELLOW 5 | vec_c_color = BLUE 6 | 7 | x_color = PINK 8 | y_color = ORANGE 9 | 10 | 11 | # Video Icon 12 | class Intro_Addition(Scene): 13 | def construct(self): 14 | 15 | self.video_nums = 5 16 | self.this_video_index = 0 17 | self.video_path_arc = -90*DEGREES 18 | self.target_point = 4.5*LEFT + DOWN 19 | 20 | self.arrow_kwargs = {"buff": 0, "stroke_width": 3, "max_tip_length_to_length_ratio": 0.2} 21 | 22 | self.title_series = Text("Rechnen mit \nVektoren", font = "Bahnschrift")\ 23 | .scale(2)\ 24 | .shift(RIGHT + DOWN)\ 25 | .set_color(GREEN_E) 26 | 27 | self.video_rect = ScreenRectangle(height = 4)\ 28 | .set_color(GREY)\ 29 | .move_to(1.5*RIGHT + 1.5*DOWN) 30 | 31 | self.title_episode = Text("Addition von Vektoren")\ 32 | .set_color_by_gradient(vec_a_color, vec_b_color, vec_c_color)\ 33 | .set_fill(color = GREY, opacity = 0.5)\ 34 | .set_stroke(width = 1.5)\ 35 | .next_to(self.video_rect.get_top(), UP) 36 | 37 | self.setup_scene() 38 | self.pop_out_this_series() 39 | self.show_scenes_from_episode() 40 | 41 | 42 | def setup_scene(self): 43 | 44 | series = self.series = self.get_series_filmrolls() 45 | # calcs = self.calcs = self.get_calc_symbols() 46 | addition = self.get_add_pic() 47 | scalar = self.get_scalar_pic() 48 | lin_comp = self.get_lincomb_pic() 49 | dot_prod = self.get_dotprod_pic() 50 | cross_prod = self.get_crossprod_pic() 51 | 52 | self.calc_pics = VGroup(addition, scalar, lin_comp, dot_prod, cross_prod) 53 | 54 | 55 | self.play( 56 | AnimationGroup( 57 | *[DrawBorderThenFill(episode, run_time = 3) for episode in series], lag_ratio = 0.1, 58 | ), 59 | AnimationGroup( 60 | *[Create(pic, run_time = 3) for pic in self.calc_pics], lag_ratio = 0.1 61 | ), 62 | # Create(calcs, lag_ratio = 0.1, run_time = 3), 63 | Write(self.title_series, run_time = 1.5) 64 | ) 65 | self.wait() 66 | 67 | def pop_out_this_series(self): 68 | target_point = self.target_point 69 | 70 | icon_and_pic = VGroup(self.series[self.this_video_index], self.calc_pics[self.this_video_index]) 71 | icon_and_pic.save_state() 72 | 73 | icon_and_pic.generate_target() 74 | icon_and_pic.target.move_to(target_point) 75 | 76 | self.this_video = self.series[self.this_video_index] 77 | 78 | self.play( 79 | MoveToTarget(icon_and_pic, path_arc = self.video_path_arc), 80 | FadeOut(self.title_series, shift = 4*RIGHT), 81 | run_time = 2 82 | ) 83 | self.wait() 84 | 85 | self.icon_and_pic = icon_and_pic 86 | 87 | def show_scenes_from_episode(self): 88 | this_video = self.this_video 89 | 90 | rotation_point = this_video[0:5].get_left() 91 | 92 | self.play( 93 | Rotating(this_video[0:5], radians = 30*DEGREES, about_point = rotation_point, rate_func = smooth, run_time = 1.5), 94 | Create(self.video_rect, run_time = 2), 95 | Write(self.title_episode, run_time = 2) 96 | ) 97 | self.wait() 98 | 99 | self.play(Rotating(this_video[0:5], radians = -30*DEGREES, about_point = rotation_point, rate_func = smooth, run_time = 0.5)) 100 | self.play( 101 | ShrinkToCenter(self.video_rect), 102 | FadeOut(self.title_episode, target_position = self.video_rect.get_center()) 103 | ) 104 | self.wait() 105 | 106 | 107 | self.play( 108 | Restore(self.icon_and_pic, path_arc = -self.video_path_arc), 109 | run_time = 2 110 | ) 111 | self.wait() 112 | 113 | 114 | self.play( 115 | LaggedStartMap(FadeOut, self.series, shift = 2*UP, lag_ratio = 0.15), 116 | LaggedStartMap(FadeOut, self.calc_pics, shift = 2*UP, lag_ratio = 0.15), 117 | run_time = 3 118 | ) 119 | self.wait() 120 | 121 | # functions 122 | 123 | def get_series_filmrolls(self): 124 | icon = SVGMobject(file_name = "video_icon") 125 | 126 | series = VGroup(*[icon.copy() for x in range(self.video_nums)]) 127 | series.arrange_submobjects(RIGHT, buff = 0.75) 128 | series.set(width = config["frame_width"] - MED_LARGE_BUFF) 129 | series.set_color(GREY)#(LIGHTER_GREY, LIGHT_GREY, GREY, DARK_GREY, DARKER_GREY)#RED_A, RED_B, RED_C, RED_D, RED_E 130 | series.to_edge(UP) 131 | 132 | return series 133 | 134 | def get_calc_symbols(self): 135 | calcs = VGroup(*[ 136 | MathTex(*tex)\ 137 | .move_to(icon[-1])\ 138 | .set_color_by_tex_to_color_map({"\\vec{a}": vec_a_color, "\\vec{b}": vec_b_color, "r": vec_c_color, "\\bullet": GREEN, "\\times": GREEN}) 139 | for tex, icon in zip( 140 | [["\\vec{a}", "+", "\\vec{b}"], ["r", "\\cdot", "\\vec{a}"], ["r", "\\cdot", "\\vec{a}", "+", "s", "\\cdot", "\\vec{b}"], ["\\vec{a}", "\\bullet", "\\vec{b}"], ["\\vec{a}", "\\times", "\\vec{b}"]], 141 | self.series 142 | ) 143 | ]) 144 | 145 | def get_add_pic(self): 146 | vec_a_num = [1.5, 0, 0] 147 | vec_b_num = [0.5, 1, 0] 148 | vec_c_num = [a+b for a,b in zip(vec_a_num, vec_b_num)] 149 | 150 | vec_a = Arrow(ORIGIN, vec_a_num[0]*RIGHT + vec_a_num[1]*UP, color = vec_a_color, **self.arrow_kwargs) 151 | vec_b = Arrow(ORIGIN, vec_b_num[0]*RIGHT + vec_b_num[1]*UP, color = vec_b_color, **self.arrow_kwargs) 152 | vec_c = Arrow(ORIGIN, vec_c_num[0]*RIGHT + vec_c_num[1]*UP, color = vec_c_color, **self.arrow_kwargs) 153 | 154 | vec_a2 = vec_a.copy().shift(vec_b_num[0]*RIGHT + vec_b_num[1]*UP) 155 | vec_b2 = vec_b.copy().shift(vec_a_num[0]*RIGHT + vec_a_num[1]*UP) 156 | 157 | for vec in vec_a2, vec_b2: 158 | vec.set_stroke(opacity = 0.4) 159 | vec.set_fill(opacity = 0.4) 160 | 161 | pic = VGroup(vec_a, vec_b, vec_a2, vec_b2, vec_c) 162 | pic.move_to(self.series[0][-1]) 163 | pic.set(height = self.series[0][-1].get_height() - 0.2) 164 | 165 | return pic 166 | 167 | def get_scalar_pic(self): 168 | vec_a_num = [0.7, 0.2, 0] 169 | vec_c_num = [3*x for x in vec_a_num] 170 | 171 | vec_a = Arrow(ORIGIN, vec_a_num[0]*RIGHT + vec_a_num[1]*UP, color = vec_a_color, **self.arrow_kwargs) 172 | vec_a2 = vec_a.copy().shift(vec_a_num[0]*RIGHT + vec_a_num[1]*UP) 173 | vec_a3 = vec_a2.copy().shift(vec_a_num[0]*RIGHT + vec_a_num[1]*UP) 174 | 175 | vec_c = Arrow(ORIGIN, vec_c_num[0]*RIGHT + vec_c_num[1]*UP, color = vec_c_color, **self.arrow_kwargs) 176 | 177 | for vec in vec_a, vec_a2, vec_a3: 178 | vec.shift(0.5*UP) 179 | 180 | pic = VGroup(vec_a, vec_a2, vec_a3, vec_c) 181 | pic.move_to(self.series[1][-1]) 182 | pic.set(height = self.series[1][-1].get_height() - 0.2) 183 | 184 | return pic 185 | 186 | def get_lincomb_pic(self): 187 | scalar_a = 0.5 188 | scalar_b = 2/3 189 | 190 | vec_a_num = [1.5, 0, 0] 191 | vec_b_num = [0.5, 1, 0] 192 | vec_c_num = [scalar_a * a + scalar_b * b for a,b in zip(vec_a_num, vec_b_num)] 193 | 194 | vec_a2_num = [scalar_a * x for x in vec_a_num] 195 | vec_b2_num = [scalar_b * x for x in vec_b_num] 196 | 197 | vec_a = Arrow(ORIGIN, vec_a_num[0]*RIGHT + vec_a_num[1]*UP, color = vec_a_color, **self.arrow_kwargs) 198 | vec_b = Arrow(ORIGIN, vec_b_num[0]*RIGHT + vec_b_num[1]*UP, color = vec_b_color, **self.arrow_kwargs) 199 | vec_c = Arrow(ORIGIN, vec_c_num[0]*RIGHT + vec_c_num[1]*UP, color = vec_c_color, **self.arrow_kwargs) 200 | 201 | vec_a2 = Arrow(ORIGIN, vec_a2_num[0]*RIGHT + vec_a2_num[1]*UP, color = vec_a_color, **self.arrow_kwargs) 202 | vec_b2 = Arrow(ORIGIN, vec_b2_num[0]*RIGHT + vec_b2_num[1]*UP, color = vec_b_color, **self.arrow_kwargs) 203 | 204 | line_a = DashedLine(vec_a2.get_end(), vec_c.get_end(), color = GREY) 205 | line_b = DashedLine(vec_b2.get_end(), vec_c.get_end(), color = GREY) 206 | 207 | for vec in vec_a, vec_b: 208 | vec.set_stroke(opacity = 0.4) 209 | vec.set_fill(opacity = 0.4) 210 | 211 | pic = VGroup(line_a, line_b, vec_a, vec_b, vec_a2, vec_b2, vec_c) 212 | pic.move_to(self.series[2][-1]) 213 | pic.set(height = self.series[2][-1].get_height() - 0.2) 214 | 215 | return pic 216 | 217 | def get_dotprod_pic(self): 218 | vec_a_num = [1.5, 0, 0] 219 | vec_b_num = [0.8, 1, 0] 220 | vec_c_num = [0.8, 0, 0] 221 | 222 | vec_a = Arrow(ORIGIN, vec_a_num[0]*RIGHT + vec_a_num[1]*UP, color = vec_a_color, **self.arrow_kwargs) 223 | vec_b = Arrow(ORIGIN, vec_b_num[0]*RIGHT + vec_b_num[1]*UP, color = vec_b_color, **self.arrow_kwargs) 224 | vec_c = Arrow(ORIGIN, vec_c_num[0]*RIGHT + vec_c_num[1]*UP, color = vec_c_color, **self.arrow_kwargs) 225 | 226 | line = DashedLine(vec_b.get_end(), vec_c.get_end(), color = GREY) 227 | 228 | pic = VGroup(line, vec_a, vec_b, vec_c) 229 | pic.move_to(self.series[3][-1]) 230 | pic.set(height = self.series[3][-1].get_height() - 0.2) 231 | 232 | return pic 233 | 234 | def get_crossprod_pic(self): 235 | vec_a_num = [1.25, 0.0, 0] 236 | vec_b_num = [0.75, 0.5, 0] 237 | vec_c_num = [0.00, 1, 0] 238 | 239 | vec_s_num = [a+b for a,b in zip(vec_a_num, vec_b_num)] 240 | 241 | vec_a = Arrow(ORIGIN, vec_a_num[0]*RIGHT + vec_a_num[1]*UP, color = vec_a_color, **self.arrow_kwargs) 242 | vec_b = Arrow(ORIGIN, vec_b_num[0]*RIGHT + vec_b_num[1]*UP, color = vec_b_color, **self.arrow_kwargs) 243 | vec_c = Arrow(ORIGIN, vec_c_num[0]*RIGHT + vec_c_num[1]*UP, color = vec_c_color, **self.arrow_kwargs) 244 | 245 | vec_s = Arrow(ORIGIN, vec_s_num[0]*RIGHT + vec_s_num[1]*UP, color = vec_c_color, **self.arrow_kwargs) 246 | 247 | rect = VMobject() 248 | rect.set_points_as_corners([ 249 | vec_a.get_start(), 250 | vec_a.get_end(), 251 | vec_s.get_end(), 252 | vec_b.get_end(), 253 | vec_b.get_start() 254 | ]) 255 | rect.set_fill(color = vec_c_color, opacity = 0.3) 256 | rect.set_stroke(width = 0) 257 | 258 | 259 | pic = VGroup(rect, vec_a, vec_b, vec_c) 260 | pic.move_to(self.series[4][-1]) 261 | pic.set(height = self.series[4][-1].get_height() - 0.2) 262 | 263 | return pic 264 | 265 | 266 | class Intro_Scalar(Intro_Addition): 267 | def construct(self): 268 | 269 | self.video_nums = 5 270 | self.this_video_index = 1 271 | self.video_path_arc = -120*DEGREES 272 | self.target_point = 4.5*LEFT + DOWN 273 | 274 | self.arrow_kwargs = {"buff": 0, "stroke_width": 3, "max_tip_length_to_length_ratio": 0.2} 275 | 276 | self.title_series = Text("Rechnen mit \nVektoren", font = "Bahnschrift")\ 277 | .scale(2)\ 278 | .shift(RIGHT + DOWN)\ 279 | .set_color(GREEN_E) 280 | 281 | self.video_rect = ScreenRectangle(height = 4)\ 282 | .set_color(GREY)\ 283 | .move_to(1.5*RIGHT + 1.5*DOWN) 284 | 285 | self.title_episode = Text("Skalare Multiplikation")\ 286 | .set_color_by_gradient(vec_a_color, vec_b_color, vec_c_color)\ 287 | .set_fill(color = GREY, opacity = 0.5)\ 288 | .set_stroke(width = 1.5)\ 289 | .next_to(self.video_rect.get_top(), UP) 290 | 291 | self.setup_scene() 292 | self.pop_out_this_series() 293 | self.show_scenes_from_episode() 294 | 295 | 296 | class Intro_Linear_Combination(Intro_Addition): 297 | def construct(self): 298 | 299 | self.video_nums = 5 300 | self.this_video_index = 2 301 | self.video_path_arc = -90*DEGREES 302 | self.target_point = 4.5*LEFT + DOWN 303 | 304 | self.arrow_kwargs = {"buff": 0, "stroke_width": 3, "max_tip_length_to_length_ratio": 0.2} 305 | 306 | self.title_series = Text("Rechnen mit \nVektoren", font = "Bahnschrift")\ 307 | .scale(2)\ 308 | .shift(RIGHT + DOWN)\ 309 | .set_color(GREEN_E) 310 | 311 | self.video_rect = ScreenRectangle(height = 4)\ 312 | .set_color(GREY)\ 313 | .move_to(1.5*RIGHT + 1.5*DOWN) 314 | 315 | self.title_episode = Text("Linearkombinationen")\ 316 | .set_color_by_gradient(vec_a_color, vec_b_color, vec_c_color)\ 317 | .set_fill(color = GREY, opacity = 0.5)\ 318 | .set_stroke(width = 1.5)\ 319 | .next_to(self.video_rect.get_top(), UP) 320 | 321 | self.setup_scene() 322 | self.pop_out_this_series() 323 | self.show_scenes_from_episode() 324 | 325 | 326 | class Intro_DotProduct(Intro_Addition): 327 | def construct(self): 328 | 329 | self.video_nums = 5 330 | self.this_video_index = 3 331 | self.video_path_arc = -90*DEGREES 332 | self.target_point = 4.5*LEFT + DOWN 333 | 334 | self.arrow_kwargs = {"buff": 0, "stroke_width": 3, "max_tip_length_to_length_ratio": 0.2} 335 | 336 | self.title_series = Text("Rechnen mit \nVektoren", font = "Bahnschrift")\ 337 | .scale(2)\ 338 | .shift(RIGHT + DOWN)\ 339 | .set_color(GREEN_E) 340 | 341 | self.video_rect = ScreenRectangle(height = 4)\ 342 | .set_color(GREY)\ 343 | .move_to(1.5*RIGHT + 1.5*DOWN) 344 | 345 | self.title_episode = Text("Skalarprodukt")\ 346 | .set_color_by_gradient(vec_a_color, vec_b_color, vec_c_color)\ 347 | .set_fill(color = GREY, opacity = 0.5)\ 348 | .set_stroke(width = 1.5)\ 349 | .next_to(self.video_rect.get_top(), UP) 350 | 351 | self.setup_scene() 352 | self.point_at_coming_episodes() 353 | self.new_pop_out_this_series() 354 | self.show_scenes_from_episode() 355 | 356 | 357 | 358 | def point_at_coming_episodes(self): 359 | self.play( 360 | AnimationGroup( 361 | VGroup(self.series[-2], self.calc_pics[-2]).animate(rate_func = there_and_back).shift(0.75*DOWN), 362 | VGroup(self.series[-1], self.calc_pics[-1]).animate(rate_func = there_and_back).shift(0.75*DOWN), 363 | FadeOut(self.title_series, shift = 14*LEFT), 364 | lag_ratio = 0.1 365 | ), 366 | run_time = 4 367 | ) 368 | self.wait() 369 | 370 | def new_pop_out_this_series(self): 371 | target_point = self.target_point 372 | 373 | icon_and_pic = VGroup(self.series[self.this_video_index], self.calc_pics[self.this_video_index]) 374 | icon_and_pic.save_state() 375 | 376 | icon_and_pic.generate_target() 377 | icon_and_pic.target.move_to(target_point) 378 | 379 | self.this_video = self.series[self.this_video_index] 380 | 381 | self.play( 382 | MoveToTarget(icon_and_pic, path_arc = self.video_path_arc), 383 | run_time = 4 384 | ) 385 | self.wait() 386 | 387 | self.icon_and_pic = icon_and_pic 388 | 389 | 390 | class Intro_CrossProduct(Intro_Addition): 391 | def construct(self): 392 | 393 | self.video_nums = 5 394 | self.this_video_index = 4 395 | self.video_path_arc = -90*DEGREES 396 | self.target_point = 4.5*LEFT + DOWN 397 | 398 | self.arrow_kwargs = {"buff": 0, "stroke_width": 3, "max_tip_length_to_length_ratio": 0.2} 399 | 400 | self.title_series = Text("Rechnen mit \nVektoren", font = "Bahnschrift")\ 401 | .scale(2)\ 402 | .shift(RIGHT + DOWN)\ 403 | .set_color(GREEN_E) 404 | 405 | self.video_rect = ScreenRectangle(height = 4)\ 406 | .set_color(GREY)\ 407 | .move_to(1.5*RIGHT + 1.5*DOWN) 408 | 409 | self.title_episode = Text("Kreuzprodukt")\ 410 | .set_color_by_gradient(vec_a_color, vec_b_color, vec_c_color)\ 411 | .set_fill(color = GREY, opacity = 0.5)\ 412 | .set_stroke(width = 1.5)\ 413 | .next_to(self.video_rect.get_top(), UP) 414 | 415 | self.setup_scene() 416 | self.pop_out_this_series() 417 | self.show_scenes_from_episode() 418 | 419 | 420 | 421 | 422 | 423 | class Intro_Trailer(Intro_Addition): 424 | def construct(self): 425 | self.video_nums = 5 426 | self.this_video_index = 1 427 | self.video_path_arc = -120*DEGREES 428 | self.target_point = 4.5*LEFT + DOWN 429 | 430 | self.arrow_kwargs = {"buff": 0, "stroke_width": 3, "max_tip_length_to_length_ratio": 0.2} 431 | 432 | self.title_series = Text("Rechnen mit \nVektoren", font = "Bahnschrift")\ 433 | .scale(2)\ 434 | .shift(RIGHT + DOWN)\ 435 | .set_color(GREEN_E) 436 | 437 | self.video_rect = ScreenRectangle(height = 4)\ 438 | .set_color(GREY)\ 439 | .move_to(1.5*RIGHT + 1.5*DOWN) 440 | 441 | 442 | self.setup_scene() 443 | self.arrange_vertically() 444 | self.go_through_episodes() 445 | self.pop_out_window() 446 | 447 | 448 | def arrange_vertically(self): 449 | for mob in self.series, self.calc_pics: 450 | mob.save_state() 451 | 452 | self.calc_pics.generate_target() 453 | self.calc_pics.target.arrange_submobjects(DOWN).to_edge(LEFT).shift(2*RIGHT) 454 | 455 | self.play( 456 | AnimationGroup( 457 | ApplyMethod(self.series.shift, 3*UP, lag_ratio = 0.2), 458 | FadeOut(self.title_series), 459 | MoveToTarget(self.calc_pics), 460 | lag_ratio = 0.2 461 | ), 462 | run_time = 4 463 | ) 464 | self.wait() 465 | 466 | 467 | self.epi_numbers = VGroup(*[ 468 | MathTex(tex).next_to(pic.get_center(), LEFT, buff = 1.5) 469 | for tex, pic in zip( 470 | ["01", "02", "03", "04", "05"], 471 | self.calc_pics 472 | ) 473 | ]) 474 | 475 | self.epi_titles = VGroup(*[ 476 | Tex(tex).next_to(pic.get_center(), RIGHT, buff = 1.5) 477 | for tex, pic in zip( 478 | ["Addition", "Skalare Multiplikation", "Linearkombinationen", "Skalarprodukt", "Kreuzprodukt"], 479 | self.calc_pics 480 | ) 481 | ]) 482 | self.play( 483 | FadeIn(self.epi_numbers, shift = RIGHT, lag_ratio = 0.15), 484 | FadeIn(self.epi_titles, shift = LEFT, lag_ratio = 0.15), 485 | run_time = 2 486 | ) 487 | self.wait() 488 | 489 | def go_through_episodes(self): 490 | self.play( 491 | *[mob[1:].animate.set_color(DARK_GREY) for mob in [self.epi_numbers, self.epi_titles]] 492 | ) 493 | self.wait(1.75) 494 | 495 | for index in range(1, len(self.calc_pics)): 496 | self.play( 497 | *[mob[index - 1].animate.set_color(DARK_GREY) for mob in [self.epi_numbers, self.epi_titles]], 498 | *[mob[index].animate.set_color(WHITE) for mob in [self.epi_numbers, self.epi_titles]], 499 | ) 500 | self.wait(1.75) 501 | 502 | self.play(*[mob[:-1].animate.set_color(WHITE) for mob in [self.epi_numbers, self.epi_titles]]) 503 | self.wait() 504 | 505 | 506 | self.play( 507 | Restore(self.calc_pics), 508 | Restore(self.series), 509 | FadeOut(self.epi_numbers, shift = RIGHT), 510 | FadeOut(self.epi_titles, shift = LEFT), 511 | run_time = 3 512 | ) 513 | self.wait() 514 | 515 | def pop_out_window(self): 516 | rect = ScreenRectangle(height = 5, stroke_width = 3) 517 | rect.next_to(self.series, DOWN) 518 | 519 | self.play(Create(rect), run_time = 2) 520 | self.wait() 521 | 522 | 523 | -------------------------------------------------------------------------------- /2021/Vektoren-RMV-Trailer.py: -------------------------------------------------------------------------------- 1 | from manim import * 2 | 3 | vec_a_color = RED 4 | vec_b_color = YELLOW 5 | vec_c_color = BLUE 6 | 7 | x_color = PINK 8 | y_color = ORANGE 9 | 10 | 11 | 12 | 13 | 14 | class Intro_Trailer(Scene): 15 | def construct(self): 16 | self.video_nums = 5 17 | self.this_video_index = 1 18 | self.video_path_arc = -120*DEGREES 19 | self.target_point = 4.5*LEFT + DOWN 20 | 21 | self.arrow_kwargs = {"buff": 0, "stroke_width": 3, "max_tip_length_to_length_ratio": 0.2} 22 | 23 | self.title_series = Text("Rechnen mit \nVektoren", font = "Bahnschrift")\ 24 | .scale(2)\ 25 | .shift(RIGHT + DOWN)\ 26 | .set_color(GREEN_E) 27 | 28 | self.video_rect = ScreenRectangle(height = 4)\ 29 | .set_color(GREY)\ 30 | .move_to(1.5*RIGHT + 1.5*DOWN) 31 | 32 | 33 | self.setup_scene() 34 | self.arrange_vertically() 35 | self.show_episodes() 36 | self.pop_out_window() 37 | self.go_through_episodes() 38 | 39 | def setup_scene(self): 40 | 41 | series = self.series = self.get_series_filmrolls() 42 | # calcs = self.calcs = self.get_calc_symbols() 43 | addition = self.get_add_pic() 44 | scalar = self.get_scalar_pic() 45 | lin_comp = self.get_lincomb_pic() 46 | dot_prod = self.get_dotprod_pic() 47 | cross_prod = self.get_crossprod_pic() 48 | 49 | self.calc_pics = VGroup(addition, scalar, lin_comp, dot_prod, cross_prod) 50 | 51 | 52 | self.play( 53 | AnimationGroup( 54 | *[DrawBorderThenFill(episode, run_time = 3) for episode in series], lag_ratio = 0.1, 55 | ), 56 | AnimationGroup( 57 | *[Create(pic, run_time = 3) for pic in self.calc_pics], lag_ratio = 0.1 58 | ), 59 | # Create(calcs, lag_ratio = 0.1, run_time = 3), 60 | Write(self.title_series, run_time = 1.5) 61 | ) 62 | self.wait() 63 | 64 | def arrange_vertically(self): 65 | for mob in self.series, self.calc_pics: 66 | mob.save_state() 67 | 68 | self.calc_pics.generate_target() 69 | self.calc_pics.target.arrange_submobjects(DOWN).to_edge(LEFT).shift(2*RIGHT) 70 | 71 | self.play( 72 | AnimationGroup( 73 | ApplyMethod(self.series.shift, 3*UP, lag_ratio = 0.2), 74 | FadeOut(self.title_series), 75 | MoveToTarget(self.calc_pics), 76 | lag_ratio = 0.2 77 | ), 78 | run_time = 4 79 | ) 80 | self.wait() 81 | 82 | 83 | self.epi_numbers = VGroup(*[ 84 | MathTex(tex).next_to(pic.get_center(), LEFT, buff = 1.5) 85 | for tex, pic in zip( 86 | ["01", "02", "03", "04", "05"], 87 | self.calc_pics 88 | ) 89 | ]) 90 | 91 | self.epi_titles = VGroup(*[ 92 | Tex(tex).next_to(pic.get_center(), RIGHT, buff = 1.5) 93 | for tex, pic in zip( 94 | ["Addition", "Skalare Multiplikation", "Linearkombinationen", "Skalarprodukt", "Kreuzprodukt"], 95 | self.calc_pics 96 | ) 97 | ]) 98 | self.play( 99 | FadeIn(self.epi_numbers, shift = RIGHT, lag_ratio = 0.15), 100 | FadeIn(self.epi_titles, shift = LEFT, lag_ratio = 0.15), 101 | run_time = 2 102 | ) 103 | self.wait() 104 | 105 | def show_episodes(self): 106 | self.play( 107 | *[mob[1:].animate.set_color(DARK_GREY) for mob in [self.epi_numbers, self.epi_titles]] 108 | ) 109 | self.wait(1.75) 110 | 111 | for index in range(1, len(self.calc_pics)): 112 | self.play( 113 | *[mob[index - 1].animate.set_color(DARK_GREY) for mob in [self.epi_numbers, self.epi_titles]], 114 | *[mob[index].animate.set_color(WHITE) for mob in [self.epi_numbers, self.epi_titles]], 115 | ) 116 | self.wait(1.75) 117 | 118 | self.play(*[mob[:-1].animate.set_color(WHITE) for mob in [self.epi_numbers, self.epi_titles]]) 119 | self.wait() 120 | 121 | 122 | self.play( 123 | Restore(self.calc_pics), 124 | Restore(self.series), 125 | FadeOut(self.epi_numbers, shift = RIGHT), 126 | self.epi_titles.animate.scale(0.7).to_edge(LEFT).shift(1*DOWN + 0.5*RIGHT), 127 | run_time = 3 128 | ) 129 | self.wait() 130 | 131 | def pop_out_window(self): 132 | rect = ScreenRectangle(height = 5, stroke_width = 3) 133 | rect.next_to(self.series, DOWN) 134 | rect.to_edge(RIGHT) 135 | 136 | self.play(Create(rect), run_time = 2) 137 | self.wait(2) 138 | 139 | def go_through_episodes(self): 140 | pass 141 | 142 | # functions 143 | 144 | def get_series_filmrolls(self): 145 | icon = SVGMobject(file_name = "video_icon") 146 | 147 | series = VGroup(*[icon.copy() for x in range(self.video_nums)]) 148 | series.arrange_submobjects(RIGHT, buff = 0.75) 149 | series.set(width = config["frame_width"] - MED_LARGE_BUFF) 150 | series.set_color(GREY)#(LIGHTER_GREY, LIGHT_GREY, GREY, DARK_GREY, DARKER_GREY)#RED_A, RED_B, RED_C, RED_D, RED_E 151 | series.to_edge(UP) 152 | 153 | return series 154 | 155 | def get_calc_symbols(self): 156 | calcs = VGroup(*[ 157 | MathTex(*tex)\ 158 | .move_to(icon[-1])\ 159 | .set_color_by_tex_to_color_map({"\\vec{a}": vec_a_color, "\\vec{b}": vec_b_color, "r": vec_c_color, "\\bullet": GREEN, "\\times": GREEN}) 160 | for tex, icon in zip( 161 | [["\\vec{a}", "+", "\\vec{b}"], ["r", "\\cdot", "\\vec{a}"], ["r", "\\cdot", "\\vec{a}", "+", "s", "\\cdot", "\\vec{b}"], ["\\vec{a}", "\\bullet", "\\vec{b}"], ["\\vec{a}", "\\times", "\\vec{b}"]], 162 | self.series 163 | ) 164 | ]) 165 | 166 | def get_add_pic(self): 167 | vec_a_num = [1.5, 0, 0] 168 | vec_b_num = [0.5, 1, 0] 169 | vec_c_num = [a+b for a,b in zip(vec_a_num, vec_b_num)] 170 | 171 | vec_a = Arrow(ORIGIN, vec_a_num[0]*RIGHT + vec_a_num[1]*UP, color = vec_a_color, **self.arrow_kwargs) 172 | vec_b = Arrow(ORIGIN, vec_b_num[0]*RIGHT + vec_b_num[1]*UP, color = vec_b_color, **self.arrow_kwargs) 173 | vec_c = Arrow(ORIGIN, vec_c_num[0]*RIGHT + vec_c_num[1]*UP, color = vec_c_color, **self.arrow_kwargs) 174 | 175 | vec_a2 = vec_a.copy().shift(vec_b_num[0]*RIGHT + vec_b_num[1]*UP) 176 | vec_b2 = vec_b.copy().shift(vec_a_num[0]*RIGHT + vec_a_num[1]*UP) 177 | 178 | for vec in vec_a2, vec_b2: 179 | vec.set_stroke(opacity = 0.4) 180 | vec.set_fill(opacity = 0.4) 181 | 182 | pic = VGroup(vec_a, vec_b, vec_a2, vec_b2, vec_c) 183 | pic.move_to(self.series[0][-1]) 184 | pic.set(height = self.series[0][-1].get_height() - 0.2) 185 | 186 | return pic 187 | 188 | def get_scalar_pic(self): 189 | vec_a_num = [0.7, 0.2, 0] 190 | vec_c_num = [3*x for x in vec_a_num] 191 | 192 | vec_a = Arrow(ORIGIN, vec_a_num[0]*RIGHT + vec_a_num[1]*UP, color = vec_a_color, **self.arrow_kwargs) 193 | vec_a2 = vec_a.copy().shift(vec_a_num[0]*RIGHT + vec_a_num[1]*UP) 194 | vec_a3 = vec_a2.copy().shift(vec_a_num[0]*RIGHT + vec_a_num[1]*UP) 195 | 196 | vec_c = Arrow(ORIGIN, vec_c_num[0]*RIGHT + vec_c_num[1]*UP, color = vec_c_color, **self.arrow_kwargs) 197 | 198 | for vec in vec_a, vec_a2, vec_a3: 199 | vec.shift(0.5*UP) 200 | 201 | pic = VGroup(vec_a, vec_a2, vec_a3, vec_c) 202 | pic.move_to(self.series[1][-1]) 203 | pic.set(height = self.series[1][-1].get_height() - 0.2) 204 | 205 | return pic 206 | 207 | def get_lincomb_pic(self): 208 | scalar_a = 0.5 209 | scalar_b = 2/3 210 | 211 | vec_a_num = [1.5, 0, 0] 212 | vec_b_num = [0.5, 1, 0] 213 | vec_c_num = [scalar_a * a + scalar_b * b for a,b in zip(vec_a_num, vec_b_num)] 214 | 215 | vec_a2_num = [scalar_a * x for x in vec_a_num] 216 | vec_b2_num = [scalar_b * x for x in vec_b_num] 217 | 218 | vec_a = Arrow(ORIGIN, vec_a_num[0]*RIGHT + vec_a_num[1]*UP, color = vec_a_color, **self.arrow_kwargs) 219 | vec_b = Arrow(ORIGIN, vec_b_num[0]*RIGHT + vec_b_num[1]*UP, color = vec_b_color, **self.arrow_kwargs) 220 | vec_c = Arrow(ORIGIN, vec_c_num[0]*RIGHT + vec_c_num[1]*UP, color = vec_c_color, **self.arrow_kwargs) 221 | 222 | vec_a2 = Arrow(ORIGIN, vec_a2_num[0]*RIGHT + vec_a2_num[1]*UP, color = vec_a_color, **self.arrow_kwargs) 223 | vec_b2 = Arrow(ORIGIN, vec_b2_num[0]*RIGHT + vec_b2_num[1]*UP, color = vec_b_color, **self.arrow_kwargs) 224 | 225 | line_a = DashedLine(vec_a2.get_end(), vec_c.get_end(), color = GREY) 226 | line_b = DashedLine(vec_b2.get_end(), vec_c.get_end(), color = GREY) 227 | 228 | for vec in vec_a, vec_b: 229 | vec.set_stroke(opacity = 0.4) 230 | vec.set_fill(opacity = 0.4) 231 | 232 | pic = VGroup(line_a, line_b, vec_a, vec_b, vec_a2, vec_b2, vec_c) 233 | pic.move_to(self.series[2][-1]) 234 | pic.set(height = self.series[2][-1].get_height() - 0.2) 235 | 236 | return pic 237 | 238 | def get_dotprod_pic(self): 239 | vec_a_num = [1.5, 0, 0] 240 | vec_b_num = [0.8, 1, 0] 241 | vec_c_num = [0.8, 0, 0] 242 | 243 | vec_a = Arrow(ORIGIN, vec_a_num[0]*RIGHT + vec_a_num[1]*UP, color = vec_a_color, **self.arrow_kwargs) 244 | vec_b = Arrow(ORIGIN, vec_b_num[0]*RIGHT + vec_b_num[1]*UP, color = vec_b_color, **self.arrow_kwargs) 245 | vec_c = Arrow(ORIGIN, vec_c_num[0]*RIGHT + vec_c_num[1]*UP, color = vec_c_color, **self.arrow_kwargs) 246 | 247 | line = DashedLine(vec_b.get_end(), vec_c.get_end(), color = GREY) 248 | 249 | pic = VGroup(line, vec_a, vec_b, vec_c) 250 | pic.move_to(self.series[3][-1]) 251 | pic.set(height = self.series[3][-1].get_height() - 0.2) 252 | 253 | return pic 254 | 255 | def get_crossprod_pic(self): 256 | vec_a_num = [1.25, 0.0, 0] 257 | vec_b_num = [0.75, 0.5, 0] 258 | vec_c_num = [0.00, 1, 0] 259 | 260 | vec_s_num = [a+b for a,b in zip(vec_a_num, vec_b_num)] 261 | 262 | vec_a = Arrow(ORIGIN, vec_a_num[0]*RIGHT + vec_a_num[1]*UP, color = vec_a_color, **self.arrow_kwargs) 263 | vec_b = Arrow(ORIGIN, vec_b_num[0]*RIGHT + vec_b_num[1]*UP, color = vec_b_color, **self.arrow_kwargs) 264 | vec_c = Arrow(ORIGIN, vec_c_num[0]*RIGHT + vec_c_num[1]*UP, color = vec_c_color, **self.arrow_kwargs) 265 | 266 | vec_s = Arrow(ORIGIN, vec_s_num[0]*RIGHT + vec_s_num[1]*UP, color = vec_c_color, **self.arrow_kwargs) 267 | 268 | rect = VMobject() 269 | rect.set_points_as_corners([ 270 | vec_a.get_start(), 271 | vec_a.get_end(), 272 | vec_s.get_end(), 273 | vec_b.get_end(), 274 | vec_b.get_start() 275 | ]) 276 | rect.set_fill(color = vec_c_color, opacity = 0.3) 277 | rect.set_stroke(width = 0) 278 | 279 | 280 | pic = VGroup(rect, vec_a, vec_b, vec_c) 281 | pic.move_to(self.series[4][-1]) 282 | pic.set(height = self.series[4][-1].get_height() - 0.2) 283 | 284 | return pic 285 | 286 | 287 | class ThreeVsTwoDimensions(Scene): 288 | def construct(self): 289 | pass 290 | 291 | 292 | 293 | -------------------------------------------------------------------------------- /2021/video_icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 9 | 11 | 13 | 37 | 40 | 41 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/Binom-00-Trailer.py: -------------------------------------------------------------------------------- 1 | from manim import * 2 | from BinomHelpers import * 3 | 4 | 5 | class OpinionPoll(Scene): 6 | def construct(self): 7 | map = self.get_german_map() 8 | 9 | pins = VGroup(*[SVGMobject(SVG_DIR + "pin", height = 0.25) for _ in range(6)]) 10 | pins.arrange(RIGHT) 11 | pins[0].move_to(3.4*LEFT + 2.5*UP) 12 | pins[1].move_to(4*LEFT + 1.85*UP) 13 | pins[2].move_to(3*LEFT + 1*UP) 14 | pins[3].move_to(5.5*LEFT + 0.25*UP) 15 | pins[4].move_to(3.75*LEFT + 1.25*DOWN) 16 | pins[5].move_to(5*LEFT + 2*DOWN) 17 | 18 | 19 | self.play(Write(map), run_time = 3) 20 | self.play(LaggedStartMap(FadeIn, pins, shift = DOWN, lag_ratio = 0.1), run_time = 2) 21 | self.wait() 22 | 23 | data0 = np.zeros(6) 24 | data = np.array([0.4, 0.28, 0.13, 0.09, 0.06, 0.04]) 25 | histo0 = Histogram(data0, width = 5, height = 4, bar_colors = [PURPLE, MAROON, ORANGE], include_x_labels = False) 26 | histo = Histogram(data, width = 5, height = 4, bar_colors = [PURPLE, MAROON, ORANGE], include_x_labels = False) 27 | 28 | for h in histo0, histo: 29 | h.shift(2.5*RIGHT) 30 | 31 | title = Tex("Hate it or love it", font_size = 64) 32 | title.scale(1.25) 33 | title.next_to(histo, UP, aligned_edge=RIGHT) 34 | title.set_color_by_gradient(PURPLE, MAROON, ORANGE) 35 | 36 | self.play( 37 | FadeIn(histo.axes), 38 | ReplacementTransform(histo0.bars, histo.bars, lag_ratio = 0.1), 39 | run_time = 3 40 | ) 41 | self.play(Write(title)) 42 | 43 | subject = Tex("Stochastik", color = YELLOW_E) 44 | subject.rotate(90*DEGREES) 45 | subject.set(width = histo.bars[0].width - 0.3) 46 | subject.next_to(histo.bars[0].get_bottom(), UP, buff = 0.2) 47 | 48 | self.play(FadeIn(subject, shift = 3*UP), run_time = 1) 49 | self.wait() 50 | 51 | 52 | # Bruchrechnung --> Baumdiagramm --> Pfadregeln 53 | 54 | histo_group = VGroup(title, histo, subject) 55 | tree = BinomTree(width = 5, height = 6, num_events = 3, cx_font_size = 16) 56 | tree.to_edge(LEFT) 57 | 58 | pfad = [1,5,12] # [[1,5,13], [1,5,12], [1,4,11], [1,4,10], [0,3,9], [0,3,8], [0,2,7], [0,2,6]] 59 | prob_all = tree.get_pfad_prob(texp = "0.75", texq = "0.25", use_prob_values=True) 60 | 61 | prob_pfad = VGroup(*[prob_all[x] for x in pfad]) 62 | 63 | mult = MathTex("0.75", "\\cdot", "0.75", "\\cdot", "0.25") 64 | mult.move_to(tree) 65 | 66 | self.play( 67 | histo_group.animate.to_edge(RIGHT), 68 | Unwrite(map), 69 | LaggedStartMap(ShrinkToCenter, pins, lag_ratio = 0.1), 70 | FadeIn(mult, shift = 5*RIGHT, rate_func = squish_rate_func(smooth, 0.5, 1)), 71 | run_time = 2.5 72 | ) 73 | self.wait(0.5) 74 | self.play( 75 | ReplacementTransform(mult, prob_pfad), 76 | FadeIn(tree.cx_marks, lag_ratio = 0.1), 77 | run_time = 2 78 | ) 79 | self.wait(0.5) 80 | 81 | 82 | pfad_list = [[1,5,13], [1,5,12], [1,4,11], [1,4,10], [0,3,9], [0,3,8], [0,2,7], [0,2,6]] 83 | pfade = VGroup(*[tree.get_pfad(numbers) for numbers in pfad_list]) 84 | moving_dots = VGroup(*[Dot(point = tree.lines[0].get_start()).set_fill(opacity = 0) for _ in range(8)]) 85 | traces = VGroup(*[ 86 | TracedPath(dot.get_center, dissipating_time=0.75, stroke_opacity=[0, 1, 0], 87 | stroke_color = YELLOW_D, stroke_width = 6) 88 | for dot in moving_dots 89 | ]) 90 | self.add(traces) 91 | self.play( 92 | AnimationGroup( 93 | *[MoveAlongPath(dot, pfad, run_time = 2.5) for dot, pfad in zip(moving_dots, pfade)], 94 | lag_ratio = 0.1 95 | ), 96 | ) 97 | for trace in traces: 98 | trace.clear_updaters() 99 | self.bring_to_back(tree) 100 | self.play(FadeOut(traces)) 101 | self.wait() 102 | 103 | # functions 104 | def get_german_map(self): 105 | map = SVGMobject(SVG_DIR + "germany_map", height = config["frame_height"] - 2) 106 | map.to_edge(LEFT) 107 | map.set_fill(BLUE, 0.75) 108 | map.set_stroke(width = 2, color = YELLOW) 109 | 110 | return map 111 | 112 | 113 | class CodingScene(Scene): 114 | def construct(self): 115 | 116 | question = Tex("Wie programmiert \\\\man den Zufall?") 117 | question.scale(2) 118 | self.play(Write(question)) 119 | self.wait() 120 | 121 | self.play(FadeOut(question, shift = 2*DOWN)) 122 | 123 | 124 | code = ''' 125 | self.play( 126 | AnimationGroup(*[ 127 | MoveAlongPath(dot, pfad, run_time = 5) 128 | for dot, pfad in zip(moving_dots, pfade) 129 | ], lag_ratio = 0.1), 130 | run_time = 5 131 | ) 132 | self.wait() 133 | ''' 134 | rendered_code = Code(code=code, tab_width=4, background="window", language="Python", font="Monospace") 135 | self.play(Write(rendered_code)) 136 | self.wait(3) 137 | 138 | 139 | self.play( 140 | rendered_code.animate.scale(0.8).to_edge(UP, buff = 0.2), 141 | run_time = 2 142 | ) 143 | self.wait(3) 144 | 145 | 146 | class CodingScene2(Scene): 147 | def construct(self): 148 | code = ''' 149 | choices = get_die_faces() 150 | 151 | def shuffle_die(mob): 152 | new_mob = random.choice(choices) 153 | new_mob.match_height(mob) 154 | mob.become(new_mob) 155 | 156 | for k in range(len(dices)): 157 | self.play(UpdateFromFunc(first_die, shuffle_die)) 158 | first_die.become(choices[dice_values[k] - 1]) 159 | self.play(TransformFromCopy(first_die, dices[k])) 160 | counter += 1 161 | num.set_value(counter) 162 | ''' 163 | 164 | rendered_code = Code(code=code, tab_width=4, background="window", language="Python", font="Monospace") 165 | self.play(Write(rendered_code), run_time = 1.5) 166 | self.wait(3) 167 | 168 | 169 | class RiseHistoFromGround(HistoScene): 170 | def construct(self): 171 | n = 10 172 | p = 0.7 173 | histo_kwargs = { 174 | "width": config["frame_width"] - 2, "height": config["frame_height"] - 3.25, 175 | "x_tick_freq": 1, "x_label_freq": 1, "y_max_value": 0.3, "y_tick_num": 3, 176 | "bar_colors": [RED, GREEN, BLUE, YELLOW] 177 | } 178 | histo_0 = self.get_histogram(n, p, zeros = True, **histo_kwargs) 179 | histo = self.get_histogram(n, p, zeros = False, **histo_kwargs) 180 | 181 | for mob in histo_0, histo: 182 | mob.center().to_edge(UP) 183 | 184 | title = Tex("Binomialverteilung")\ 185 | .set_color_by_gradient(*histo_kwargs["bar_colors"])\ 186 | .set_fill(color = WHITE, opacity = 0.3)\ 187 | .set_stroke(width = 1.5)\ 188 | .set(width = config["frame_width"] - 3)\ 189 | .to_edge(DOWN) 190 | 191 | self.play( 192 | DrawBorderThenFill(title, rate_func = squish_rate_func(smooth, 0.6, 1)), 193 | FadeIn(histo.axes), 194 | ReplacementTransform(histo_0.bars, histo.bars, lag_ratio = 0.2), 195 | run_time = 5 196 | ) 197 | self.wait() 198 | self.remove(histo_0) 199 | 200 | 201 | p_val = ValueTracker(0.7) 202 | histo.p_val = p_val 203 | histo.n = n 204 | self.play( 205 | p_val.animate.set_value(0.25), 206 | UpdateFromFunc(histo, self.update_histogram), 207 | run_time = 4 208 | ) 209 | self.wait() 210 | 211 | # functions 212 | def update_histogram(self, hist): 213 | new_dist = scipy.stats.binom(hist.n, hist.p_val.get_value()) 214 | new_data = np.array([new_dist.pmf(x) for x in range(0, hist.n + 1)]) 215 | 216 | new_bars = hist.get_bars(new_data) 217 | new_bars.match_style(hist.bars) 218 | hist.bars.become(new_bars) 219 | 220 | 221 | class AskForAbo(Scene): 222 | def construct(self): 223 | title = Tex("Wie wäre es denn mit einem...", " Abo", "???") 224 | title.set(width = 12) 225 | title.to_edge(UL) 226 | 227 | wheel = self.wheel = self.get_wheel() 228 | wheel.scale(1.25) 229 | wheel.shift(4*RIGHT) 230 | 231 | self.play( 232 | AnimationGroup( 233 | Write(title[0]), 234 | DrawBorderThenFill(wheel), 235 | lag_ratio = 0.4 236 | ), 237 | run_time = 3 238 | ) 239 | self.wait() 240 | 241 | 242 | succ = wheel.succ[0].copy().scale(0.5) 243 | fail = wheel.fail[0].copy().scale(0.5) 244 | sf = VGroup(succ, fail) 245 | sf.arrange(DOWN, buff = 1) 246 | sf.move_to(5*LEFT) 247 | 248 | yes = Tex("Ja, warum nicht!").scale(1.25).next_to(succ, RIGHT) 249 | no = Tex("Ähm nope, Danke!").scale(1.25).next_to(fail, RIGHT) 250 | 251 | self.play( 252 | FadeIn(title[1:], shift = UP, scale = 0.1), 253 | LaggedStartMap(GrowFromCenter, sf, lag_ratio = 0.25), 254 | LaggedStartMap(FadeIn, VGroup(yes, no), shift = 2*LEFT, lag_ratio = 0.25), 255 | run_time = 1.5 256 | ) 257 | self.wait() 258 | 259 | self.rotate_arrow(deg_angle = -(7*360 - 110), run_time = 8) 260 | self.wait() 261 | 262 | # functions 263 | def get_wheel(self): 264 | colors = [BLUE, ORANGE, BLUE, BLUE, BLUE] 265 | sectors = VGroup() 266 | for i in range(5): 267 | sector = Sector( 268 | outer_radius = 1.8, angle = 72*DEGREES, start_angle = i * 72*DEGREES - 36*DEGREES, 269 | color = colors[i], fill_opacity = 0.75 270 | ) 271 | sector.set_stroke(width = 1, color = WHITE) 272 | sectors.add(sector) 273 | 274 | dot = Dot(color = WHITE).set_stroke(width = 1, color = BLACK) 275 | arrow = Arrow(1.35*DOWN, 1.35*UP, stroke_width = 8, color = BLACK).move_to(dot) 276 | arrow.rotate(-10*DEGREES) 277 | arrow.set_stroke(width = 10) 278 | 279 | wheel = VGroup(sectors, arrow, dot) 280 | wheel.arrow = arrow 281 | wheel.succ = VGroup(sectors[0], sectors[2], sectors[3], sectors[4]) 282 | wheel.fail = VGroup(sectors[1]) 283 | 284 | return wheel 285 | 286 | def rotate_arrow(self, deg_angle, added_anims = None, **kwargs): 287 | wheel = self.wheel 288 | 289 | if added_anims is None: 290 | added_anims = [] 291 | 292 | self.play( 293 | Rotate( 294 | wheel.arrow, 295 | angle = deg_angle*DEGREES, 296 | about_point = wheel.get_center(), 297 | rate_func = slow_into, 298 | **kwargs 299 | ), 300 | *added_anims 301 | ) 302 | 303 | 304 | class Thumbnail(HistoScene): 305 | def construct(self): 306 | n = 10 307 | p = 0.7 308 | p_val = ValueTracker(p) 309 | histo_kwargs = { 310 | "width": config["frame_width"] - 2, "height": config["frame_height"] - 3.25, 311 | "x_tick_freq": 1, "x_label_freq": 1, "y_max_value": 0.3, "y_tick_num": 3, 312 | "bar_colors": [RED, GREEN, BLUE, YELLOW] 313 | } 314 | histo = self.get_histogram(n, p, zeros = False, **histo_kwargs) 315 | histo.center() 316 | histo.to_edge(DOWN) 317 | 318 | title = Tex("Binomialverteilung") 319 | title.set(width = histo.width) 320 | title.set_color_by_gradient(RED, GREEN, BLUE, YELLOW) 321 | title.to_corner(UL) 322 | 323 | trailer = Tex("Trailer") 324 | trailer.to_edge(UP).shift(0.65*RIGHT) 325 | 326 | # for x in [0,1,2,3,4,6]: 327 | # histo.bars[x].set_fill(opacity = 0.2) 328 | 329 | p6 = MathTex("P", "(", "X", "=", "6", ")") 330 | p6[-2].set_color(C_COLOR) 331 | p6.rotate(90*DEGREES) 332 | p6.set(height = histo.bars[6].height - 0.25) 333 | p6.next_to(histo.bars[6].get_bottom(), UP, buff = 0.1) 334 | 335 | binom5 = get_binom_formula(10, 0.7, 6)[7:] 336 | binom5.next_to(histo.bars[6].get_corner(UL), UL) 337 | 338 | 339 | carrow = CurvedArrow(binom5.get_bottom() + 0.1*DOWN, histo.bars[6].get_left() + 0.5*UP, angle = TAU / 8, stroke_width = 3) 340 | 341 | 342 | self.add(histo, title, trailer) 343 | self.add(p6, binom5) 344 | self.add(carrow) 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | class CasNoCas(Scene): 358 | def construct(self): 359 | title = Tex("Wir schreiben den Test ... ") 360 | title.scale(2.5) 361 | title.shift(UP) 362 | 363 | origin = Tex("mit Cas", color = RED) 364 | origin.scale(2.5) 365 | 366 | def update_tex(mob): 367 | value = random.uniform(0,1) 368 | if value < 0.5: 369 | tex = Tex("mit CAS", font_size = 72, color = RED) 370 | else: 371 | tex = Tex("ohne CAS", font_size = 72, color = GREEN) 372 | tex.scale(2.5) 373 | mob.become(tex) 374 | 375 | self.play( 376 | Write(title), 377 | FadeIn(origin, shift = 2*UP), 378 | ) 379 | self.wait() 380 | 381 | self.play( 382 | UpdateFromFunc(origin, update_tex), 383 | run_time = 5 384 | ) 385 | self.wait() 386 | 387 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/Binom-04-Hist.py: -------------------------------------------------------------------------------- 1 | from manim import * 2 | from BinomHelpers import * 3 | import random 4 | 5 | import scipy.stats 6 | 7 | 8 | class Intro(HistoScene): 9 | def construct(self): 10 | n = 10 11 | p = 0.7 12 | histo_kwargs = { 13 | "width": config["frame_width"] - 2, "height": config["frame_height"] - 3.25, 14 | "x_tick_freq": 1, "x_label_freq": 1, "y_max_value": 0.3, "y_tick_num": 3, 15 | "bar_colors": [RED, GREEN, BLUE, YELLOW] 16 | } 17 | histo_0 = self.get_histogram(n, p, zeros = True, **histo_kwargs) 18 | histo = self.get_histogram(n, p, zeros = False, **histo_kwargs) 19 | 20 | for mob in histo_0, histo: 21 | mob.center().to_edge(DOWN) 22 | 23 | title = Tex("Histogramm")\ 24 | .set_color_by_gradient(*histo_kwargs["bar_colors"])\ 25 | .set_fill(color = WHITE, opacity = 0.3)\ 26 | .set_stroke(width = 1.5)\ 27 | .set(width = config["frame_width"] - 6)\ 28 | .to_corner(UR) 29 | 30 | 31 | self.add(histo_0) 32 | self.play( 33 | DrawBorderThenFill(title, rate_func = squish_rate_func(smooth, 0.6, 1)), 34 | ReplacementTransform(histo_0.bars, histo.bars, lag_ratio = 0.2), 35 | run_time = 5 36 | ) 37 | self.wait() 38 | self.remove(histo_0) 39 | 40 | 41 | prop_val = ValueTracker(p) 42 | histo.p_val = prop_val 43 | histo.n = n 44 | def update_histogram(hist): 45 | new_dist = scipy.stats.binom(hist.n, hist.p_val.get_value()) 46 | new_data = np.array([new_dist.pmf(x) for x in range(0, hist.n + 1)]) 47 | new_bars = hist.get_bars(new_data) 48 | new_bars.match_style(hist.bars) 49 | hist.bars.become(new_bars) 50 | 51 | for prop in [0.1, 0.5, p]: 52 | self.play( 53 | prop_val.animate.set_value(prop), 54 | UpdateFromFunc(histo, update_histogram, suspend_mobject_updating=False), 55 | run_time = 4.5 56 | ) 57 | self.wait(0.5) 58 | self.wait(0.5) 59 | 60 | remember = Tex("Merke dir das...", font_size = 72).shift(2*LEFT + 0.4*DOWN) 61 | self.play(Write(remember)) 62 | self.wait(3) 63 | 64 | 65 | class WhatsTheModell(HistoScene): 66 | def construct(self): 67 | self.n = 10 68 | self.p = 0.7 69 | 70 | self.both_result() 71 | self.probability() 72 | self.trail_of_length_10() 73 | 74 | def both_result(self): 75 | coin_scale = 1.5 76 | results = VGroup(*[get_coin(symbol).scale(coin_scale) for symbol in ["Z", "K"]]) 77 | results.arrange(RIGHT, buff = 2) 78 | for result in results: 79 | result.save_state() 80 | result.center() 81 | 82 | init_heads = get_coin("K").scale(1.5) 83 | 84 | def random_update_result(mob): 85 | p = random.uniform(0,1) 86 | if p > 0.5: 87 | choice = get_coin("K") 88 | else: 89 | choice = get_coin("Z") 90 | choice.scale(coin_scale) 91 | mob.become(choice) 92 | 93 | self.play( 94 | UpdateFromFunc(init_heads, random_update_result, run_time = 6) 95 | ) 96 | self.add(results) 97 | self.remove(init_heads) 98 | self.play(*[Restore(result) for result in results], run_time = 2) 99 | 100 | 101 | myTemplate = TexTemplate() 102 | myTemplate.add_to_preamble(r"\usepackage{pifont}") 103 | 104 | sf_marks = VGroup(*[ 105 | Tex(mark, color = tex_color, tex_template = myTemplate, font_size = 120) 106 | for mark, tex_color in zip([CMARK_TEX, XMARK_TEX], [C_COLOR, X_COLOR]) 107 | ]) 108 | for mark, result in zip(sf_marks, results): 109 | mark.next_to(result, UP, buff = 1) 110 | 111 | self.play(DrawBorderThenFill(sf_marks, lag_ratio = 0.1), run_time = 1.5) 112 | self.play(Swap(*results), run_time = 1.5) 113 | self.wait() 114 | 115 | succ_group = VGroup(sf_marks[0], results[1]) 116 | succ_group.generate_target() 117 | succ_group.target.arrange(RIGHT, buff = 0.5).to_edge(UP).shift(4*RIGHT) 118 | 119 | fail_group = VGroup(results[0], sf_marks[1]) 120 | fail_group.generate_target() 121 | fail_group.target.arrange(RIGHT, buff = 0.5).to_edge(UP).shift(4*LEFT) 122 | 123 | self.play( 124 | *[MoveToTarget(group) for group in [succ_group, fail_group]], 125 | run_time = 1.5 126 | ) 127 | 128 | self.succ_group, self.fail_group = succ_group, fail_group 129 | 130 | def probability(self): 131 | prob = ValueTracker(0.5) 132 | succ = DecimalNumber(prob.get_value())\ 133 | .scale(1.5)\ 134 | .set_color(C_COLOR)\ 135 | .next_to(self.succ_group, DOWN, buff = 0.5)\ 136 | .add_updater(lambda dec: dec.set_value(prob.get_value())) 137 | fail = DecimalNumber(1 - prob.get_value())\ 138 | .scale(1.5)\ 139 | .set_color(X_COLOR)\ 140 | .next_to(self.fail_group, DOWN, buff = 0.5)\ 141 | .add_updater(lambda dec: dec.set_value(1 - prob.get_value())) 142 | 143 | self.play(*[FadeIn(sf, shift = DOWN) for sf in [succ, fail]]) 144 | self.wait() 145 | self.play(prob.animate.set_value(self.p), run_time = 3) 146 | self.play(Circumscribe(succ, color = C_COLOR, stroke_width = 6, run_time = 2)) 147 | self.wait() 148 | 149 | bools = 7 * [True] + 3 * [False] 150 | grid = get_coin_grid(bools, height=6) 151 | grid.arrange(RIGHT).set(height = 1).shift(DOWN) 152 | 153 | random.shuffle(bools) 154 | grid_shuffle = get_coin_grid(bools, height=6) 155 | grid_shuffle.arrange(RIGHT).set(height = 1).shift(DOWN) 156 | self.play(LaggedStartMap(FadeIn, grid_shuffle, shift = 0.5*UP, lag_ratio = 0.1), run_time = 1.5) 157 | self.wait() 158 | 159 | self.play(ReplacementTransform(grid_shuffle, grid)) 160 | self.wait() 161 | 162 | 163 | bools = 70 * [True] + 30 * [False] 164 | new_grid = get_coin_grid(bools, height = 5) 165 | new_grid.to_edge(DOWN) 166 | 167 | random.shuffle(bools) 168 | new_grid_shuffle = get_coin_grid(bools, height = 5) 169 | new_grid_shuffle.to_edge(DOWN) 170 | 171 | self.play(ReplacementTransform(grid, new_grid_shuffle)) 172 | self.wait() 173 | 174 | self.play(TransformMatchingShapes(new_grid_shuffle, new_grid)) 175 | self.wait(2) 176 | 177 | self.play( 178 | AnimationGroup( 179 | FadeOut(new_grid[:70], shift = 5*UP), 180 | FadeOut(new_grid[70:], shift = 3*DOWN), 181 | lag_ratio = 0.1 182 | ), 183 | run_time = 2 184 | ) 185 | self.wait() 186 | 187 | self.play( 188 | AnimationGroup( 189 | *[dec.animate.next_to(group, direction, buff = 0.35) for dec, group, direction 190 | in zip([succ, fail],[self.succ_group, self.fail_group],[LEFT, RIGHT])], 191 | lag_ratio = 0.1 192 | ), 193 | run_time = 2.5 194 | ) 195 | self.wait() 196 | 197 | def trail_of_length_10(self): 198 | # Create 20 DecimalNumbers 199 | numbers = VGroup() 200 | for i in range(self.n): 201 | num = DecimalNumber() 202 | numbers.add(num) 203 | 204 | # set their value 205 | def randomize_numbers(numbers): 206 | for num in numbers: 207 | value = random.uniform(0,1) 208 | num.set_value(value) 209 | if value < 0.3: 210 | num.set_color(RED) 211 | else: 212 | num.set_color(GREEN) 213 | 214 | numbers.set(height = 0.2) 215 | numbers.arrange(RIGHT, buff = 0.35) 216 | numbers.to_edge(UP, buff = 2.75) 217 | 218 | # get results (K or Z) depending on that number 219 | def get_results(numbers): 220 | results = VGroup() 221 | for num in numbers: 222 | if num.get_value() < 0.3: 223 | result = Tex("Z").set_color(RED) 224 | else: 225 | result = Tex("K").set_color(BLUE) 226 | 227 | result.set(height = 0.4) 228 | result.next_to(num, UP) 229 | results.add(result) 230 | return results 231 | 232 | succ_nums = VGroup() 233 | grid = VGroup() 234 | for x in range(10): 235 | succ_var = 0 236 | self.play( 237 | numbers.animate.shift(0.5*DOWN), 238 | UpdateFromFunc(numbers, randomize_numbers) 239 | ) 240 | 241 | for num in numbers: 242 | if num.get_value() > 0.3: 243 | succ_var += 1 244 | 245 | results = get_results(numbers) 246 | grid.add(*results) 247 | self.play(LaggedStartMap(FadeIn, results, shift = 0.2*DOWN)) 248 | 249 | succ_num = Integer()\ 250 | .set_value(succ_var)\ 251 | .next_to(results, RIGHT, buff = 0.5)\ 252 | .align_to(self.succ_group, RIGHT)\ 253 | .shift(0.6*LEFT)\ 254 | .set_color(YELLOW_E) 255 | succ_num.value = succ_var 256 | 257 | succ_nums.add(succ_num) 258 | 259 | self.play(Write(succ_num)) 260 | 261 | self.wait(2) 262 | 263 | # FadeOut numbers, results & arrange succ_nums 264 | succ_nums.generate_target() 265 | succ_nums.target.scale(1.75).arrange(RIGHT, buff = 0.75).center() 266 | self.play( 267 | LaggedStartMap(ShrinkToCenter, grid, lag_ratio = 0.01, run_time = 2), 268 | LaggedStartMap(ShrinkToCenter, numbers, lag_ratio = 0.1, run_time = 2), 269 | MoveToTarget(succ_nums, lag_ratio = 0.05, rate_func = squish_rate_func(smooth, 0.3, 1), run_time = 3) 270 | ) 271 | self.wait() 272 | 273 | # clarify meaning again 274 | def get_arrows_from_value(value): 275 | value_group = VGroup(*[number for number in succ_nums if number.value == value]) 276 | arrows = VGroup() 277 | for mob in value_group: 278 | arrow = Arrow(ORIGIN, 1.5*UP) 279 | arrow.next_to(mob, DOWN) 280 | arrows.add(arrow) 281 | 282 | return arrows 283 | 284 | arrows_6 = get_arrows_from_value(6) 285 | arrows_7 = get_arrows_from_value(7) 286 | self.play(FadeIn(arrows_6, shift = UP, lag_ratio = 0.1)) 287 | self.wait() 288 | self.play( 289 | FadeOut(arrows_6, shift = DOWN, lag_ratio = 0.1), 290 | FadeIn(arrows_7, shift = UP, lag_ratio = 0.1) 291 | ) 292 | self.wait() 293 | self.play(FadeOut(arrows_7)) 294 | self.wait() 295 | 296 | # prepare for histogram 297 | histo_kwargs = { 298 | "width": config["frame_width"] - 2, "height": config["frame_height"] - 3.25, 299 | "x_tick_freq": 1, "x_label_freq": 1, "y_max_value": 0.3, "y_tick_num": 3, 300 | "include_h_lines": True, "bar_colors": [RED, GREEN, BLUE, YELLOW] 301 | } 302 | histo = self.get_histogram(self.n, self.p, **histo_kwargs) 303 | histo.center().to_edge(DOWN) 304 | 305 | for num in succ_nums: 306 | value = num.value 307 | num.generate_target() 308 | target_mob = histo.axes.x_labels[value] 309 | num.target.match_height(target_mob).match_color(target_mob).move_to(target_mob) 310 | self.play( 311 | LaggedStartMap(MoveToTarget, succ_nums, lag_ratio = 0.1), run_time = 5 312 | ) 313 | self.wait() 314 | self.play( 315 | Create(histo.axes.x_axis), 316 | ShowIncreasingSubsets(histo.axes.x_labels), 317 | run_time = 5 318 | ) 319 | self.remove(succ_nums) 320 | self.wait(2) 321 | 322 | self.play( 323 | Create(histo.axes.y_axis), 324 | Create(histo.axes.h_lines), 325 | run_time = 3 326 | ) 327 | self.wait(3) 328 | 329 | 330 | # Brian Links: 331 | # https://github.com/brianamedee/3B1B-Animated-Tutorials/blob/main/3b1bProbability.py 332 | # https://www.youtube.com/watch?v=t_wBGoO8TA8&t=467s 333 | 334 | # 3Blue1Brown 335 | # https://youtu.be/8idr1WZ1A7Q?t=366 336 | 337 | 338 | class SimulateHistogram(HistoScene): 339 | def construct(self): 340 | self.n = 10 341 | self.p = 0.7 342 | histo_kwargs = { 343 | "width": config["frame_width"] - 2, "height": config["frame_height"] - 3.25, 344 | "x_tick_freq": 1, "x_label_freq": 1, "y_max_value": 0.3, "y_tick_num": 3, 345 | "include_h_lines": True, "bar_colors": [RED, GREEN, BLUE, YELLOW] 346 | } 347 | histo = self.get_histogram(self.n, self.p, **histo_kwargs) 348 | histo.center().to_edge(DOWN) 349 | 350 | 351 | def get_bars(histogram, data): 352 | portions = np.array(data).astype(float) 353 | total = portions.sum() 354 | if total == 0: 355 | portions[:] = 0 356 | else: 357 | portions /= total 358 | 359 | bars = VGroup() 360 | 361 | for x, prop in enumerate(portions): 362 | p1 = VectorizedPoint().move_to(histogram[0].c2p(x, 0)) 363 | p2 = VectorizedPoint().move_to(histogram[0].c2p(x + 1, 0)) 364 | p3 = VectorizedPoint().move_to(histogram[0].c2p(x + 1, prop)) 365 | p4 = VectorizedPoint().move_to(histogram[0].c2p(x, prop)) 366 | points = VGroup(p1, p2, p3, p4) 367 | bar = Rectangle().replace(points, stretch=True) 368 | bar.set_stroke(width = 1) 369 | bars.add(bar) 370 | # bars.set_style(fill_color = [*histo_kwargs["bar_colors"]], fill_opacity = 0.6, stroke_color = WHITE) 371 | return bars 372 | 373 | 374 | data = np.zeros(11) # Possible outcomes as an array 375 | row = get_random_row(p = self.p, n = self.n).shift(0.25*DOWN) 376 | bars = get_bars(histogram=histo, data=data) 377 | 378 | text_counter = Tex("Anzahl: ", font_size = 60).shift(3.5*LEFT + UP) 379 | counter = always_redraw( 380 | lambda: Integer()\ 381 | .scale(1.25)\ 382 | .set_value(sum(data))\ 383 | .next_to(text_counter, RIGHT, buff=0.3, aligned_edge = UP) 384 | ) 385 | arrow = Line(ORIGIN, DOWN * 0.8).add_tip().set_color(PINK) 386 | 387 | # Update function 388 | def update(dummy, n_added_data_points=0): 389 | new_row = get_random_row().shift(0.25*DOWN) 390 | row.become(new_row) 391 | 392 | count = sum([m.positive for m in new_row.nums]) 393 | data[count] += 1 394 | if n_added_data_points: 395 | values = np.random.random((n_added_data_points, 10)) 396 | counts = (values > 0.3).sum(1) # changed from < 0.2 397 | for i in range(len(data)): 398 | data[i] += (counts == i).sum() 399 | 400 | bars.become(get_bars(histogram=histo, data=data)) 401 | 402 | arrow.next_to(bars[count], UP, buff=0.1) 403 | 404 | # bars[2].set_style( 405 | # fill_color = [*histo_kwargs["bar_colors"]], 406 | # fill_opacity = 0.6, 407 | # stroke_color = WHITE, 408 | # ) 409 | 410 | self.add(histo.axes) 411 | self.wait() 412 | 413 | self.play( 414 | AnimationGroup( 415 | FadeIn(row, shift = DOWN, lag_ratio = 0.1), 416 | lag_ratio = 0.1 417 | ), 418 | run_time = 3 419 | ) 420 | self.wait() 421 | self.play( 422 | AnimationGroup( 423 | Write(text_counter), 424 | FadeIn(counter, shift = UP), 425 | lag_ratio = 0.1 426 | ), 427 | run_time = 2 428 | ) 429 | self.wait() 430 | self.play(Circumscribe(counter, color = YELLOW_D, time_width = 0.75, run_time = 3)) 431 | self.wait() 432 | self.add(bars, arrow) 433 | 434 | 435 | group = VGroup(row, bars, arrow) 436 | self.play(UpdateFromFunc(group, update), run_time = 2) 437 | self.wait(2) 438 | 439 | 440 | self.play( 441 | LaggedStart(*[mark.animate(rate_func = there_and_back).shift(0.5*DOWN) for mark in row.syms], lag_ratio = 0.1), 442 | run_time = 3 443 | ) 444 | self.play(Circumscribe(arrow, color = YELLOW_D, time_width = 0.75, run_time = 3)) 445 | self.wait() 446 | 447 | 448 | self.play(UpdateFromFunc(group, lambda m: update(m, 10)), run_time = 2) 449 | self.wait(2) 450 | self.play(UpdateFromFunc(group, lambda m: update(m, 100)), run_time = 2) 451 | self.play(UpdateFromFunc(group, lambda m: update(m, 500)), run_time = 2) 452 | self.play(UpdateFromFunc(group, lambda m: update(m, 1000)), run_time = 2) 453 | self.play(UpdateFromFunc(group, lambda m: update(m, 1000)), run_time = 2) 454 | self.wait(3) 455 | 456 | 457 | histo_0 = self.get_histogram(self.n, self.p, zeros = True, **histo_kwargs) 458 | histo_0.center().to_edge(DOWN) 459 | 460 | counter.clear_updaters() 461 | self.play( 462 | FadeOut(VGroup(row, text_counter, counter, arrow)), 463 | ReplacementTransform(histo_0.bars, histo.bars, lag_ratio = 0.1), 464 | run_time = 5 465 | ) 466 | self.remove(bars) 467 | self.wait(3) 468 | 469 | 470 | class SimulationAfterEffects(HistoScene, MovingCameraScene): 471 | def construct(self): 472 | self.n = 10 473 | self.p = 0.7 474 | histo_kwargs = { 475 | "width": config["frame_width"] - 2, "height": config["frame_height"] - 3.25, 476 | "x_tick_freq": 1, "x_label_freq": 1, "y_max_value": 0.3, "y_tick_num": 3, 477 | "include_h_lines": True, "bar_colors": [RED, GREEN, BLUE, YELLOW] 478 | } 479 | histo = self.histo = self.get_histogram(self.n, self.p, **histo_kwargs) 480 | histo.center().to_edge(DOWN) 481 | 482 | self.add(histo) 483 | self.wait(2) 484 | 485 | self.connect_to_formula() 486 | self.formula_to_bar() 487 | self.probs_sum_up_to_1() 488 | self.changing_parameters() 489 | 490 | 491 | def connect_to_formula(self): 492 | n, p, histo = self.n, self.p, self.histo 493 | 494 | k = self.k = 7 495 | binom_data = VGroup(*[MathTex(*tex) for tex in (["n", "=", str(n)], ["p", "=", str(p)])])\ 496 | .arrange_submobjects(RIGHT, aligned_edge = UP)\ 497 | .scale(0.6)\ 498 | .to_corner(UL, buff = 0.1)\ 499 | .save_state()\ 500 | .scale(2.5)\ 501 | .center()\ 502 | .shift(LEFT + UP) 503 | 504 | formula = get_binom_formula(n, p, k) 505 | formula.scale(1.25) 506 | formula.to_edge(UP) 507 | formula.shift(1.1*LEFT) 508 | 509 | self.play(ShowIncreasingSubsets(binom_data), run_time = 2) 510 | self.wait() 511 | self.play(Restore(binom_data)) 512 | self.wait(0.5) 513 | 514 | self.play(Write(formula[:7]), run_time = 1) 515 | self.wait() 516 | 517 | self.play(FocusOn(histo.axes.x_labels[k], run_time = 1)) 518 | self.play(Circumscribe(histo.axes.x_labels[k], color = C_COLOR)) 519 | self.wait() 520 | 521 | self.play(Write(formula[7:11])) 522 | self.wait() 523 | self.play(Write(formula[11:14])) 524 | self.wait() 525 | self.play(Write(formula[14:])) 526 | self.wait() 527 | 528 | self.play(Circumscribe(formula, color = BLUE, time_width = 0.75, stroke_width = 2, run_time = 3)) 529 | self.wait() 530 | 531 | self.formula, self.binom_data = formula, binom_data 532 | 533 | def formula_to_bar(self): 534 | k, n, p, histo = self.k, self.n, self.p, self.histo 535 | formula = self.formula 536 | 537 | result = get_binom_result(n, p, k) 538 | result_tex = MathTex("\\approx", str(result)).scale(1.25).next_to(formula, RIGHT, buff = 0.1) 539 | 540 | line = DashedLine(dash_length = 0.01, stroke_width = 1, stroke_color = WHITE) 541 | line.match_width(histo.axes.x_axis) 542 | line.next_to(histo.axes.c2p(0, result), buff = 0) 543 | 544 | self.play(FadeIn(result_tex, shift = 2*LEFT), run_time = 2) 545 | self.play(Circumscribe(result_tex, color = histo.bars[k].get_color(), run_time = 2)) 546 | self.wait() 547 | 548 | dot = Dot(point = histo.axes.c2p(0,0), color = histo.bars[k].get_color()) 549 | self.play(FocusOn(dot)) 550 | self.play(dot.animate.move_to(histo.axes.c2p(0, result)), run_time = 2) 551 | self.play( 552 | Create(line), 553 | dot.animate.move_to(histo.axes.c2p(n + 1, result)), 554 | rate_func = smooth, run_time = 2 555 | ) 556 | self.highlight_single_bar(histo, k, run_time = 2) 557 | self.play(ApplyWave(histo.bars[k], run_time = 2)) 558 | self.play(ShrinkToCenter(dot)) 559 | self.wait() 560 | 561 | 562 | for k in [10, 6, 3]: 563 | new_formula = get_binom_formula(n, p, k)\ 564 | .scale(1.25)\ 565 | .to_edge(UP)\ 566 | .shift(1.1*LEFT) 567 | self.play(Transform(formula, new_formula)) 568 | self.wait(0.5) 569 | 570 | new_result = round(scipy.stats.binom.pmf(k,n,p), 4) 571 | new_tex = MathTex("\\approx", str(new_result)).scale(1.25).next_to(formula, RIGHT, buff = 0.1) 572 | self.play(Transform(result_tex, new_tex)) 573 | self.wait(0.5) 574 | 575 | new_line = DashedLine(dash_length = 0.01, stroke_width = 1, stroke_color = WHITE) 576 | new_line.match_width(histo.axes.x_axis) 577 | new_line.next_to(histo.axes.c2p(0, new_result), buff = 0) 578 | 579 | self.highlight_single_bar(histo, k, run_time = 1.5) 580 | self.play(Transform(line, new_line)) 581 | self.wait() 582 | 583 | self.highlight_group_of_bars(histo, 0, 10, run_time = 3) 584 | self.play( 585 | FadeOut(line), 586 | FadeOut(formula), 587 | FadeOut(result_tex), 588 | FadeOut(self.binom_data) 589 | ) 590 | self.wait() 591 | 592 | 593 | formulas = VGroup(*[MathTex("P", "(", "X", "=", str(num), ")") for num in range(11)]) 594 | formulas.rotate(90*DEGREES) 595 | 596 | for form, bar in zip(formulas, histo.bars): 597 | form[-2].set_color(C_COLOR) 598 | form.add_background_rectangle() 599 | form.next_to(bar.get_top(), UP, buff = 0.15) 600 | 601 | labels = histo.axes.x_labels.copy() 602 | for label, form in zip(labels, formulas): 603 | label.generate_target() 604 | label.target.rotate(90*DEGREES).match_height(form[-2]).move_to(form[-2]).set_color(C_COLOR) 605 | 606 | self.play( 607 | AnimationGroup( 608 | LaggedStartMap(MoveToTarget, labels, lag_ratio = 0.1), 609 | LaggedStartMap(FadeIn, formulas, lag_ratio = 0.1), 610 | lag_ratio = 0.3 611 | ), 612 | run_time = 4 613 | ) 614 | self.remove(*labels) 615 | self.wait() 616 | 617 | self.play( 618 | LaggedStart(*[Indicate(form[1:], color = RED) for form in formulas], lag_ratio = 0.1), 619 | run_time = 3 620 | ) 621 | self.wait() 622 | 623 | self.formulas = formulas 624 | 625 | def probs_sum_up_to_1(self): 626 | histo, formulas = self.histo, self.formulas 627 | 628 | group = VGroup() 629 | formulas.generate_target() 630 | formulas.target.rotate(-90*DEGREES).arrange_submobjects(DOWN, buff = 0.15, aligned_edge = RIGHT).to_edge(LEFT) 631 | 632 | equals = VGroup() 633 | for form in formulas.target: # added .target 634 | equal = MathTex("=") 635 | equal.next_to(form, RIGHT, buff = 0.5) 636 | equals.add(equal) 637 | 638 | datas = np.array([round(scipy.stats.binom.pmf(x, 10, 0.7), 4) for x in range(0, 10 + 1)]) 639 | results = VGroup() 640 | for data, equal in zip(datas, equals): 641 | result = MathTex(str(data)) 642 | result.next_to(equal, RIGHT, buff = 0.5) 643 | results.add(result) 644 | 645 | result0 = MathTex("0.0000").move_to(results[0], aligned_edge=LEFT) 646 | result3 = MathTex("0.0090").move_to(results[3], aligned_edge=LEFT) 647 | results[0] = result0 648 | results[3] = result3 649 | 650 | braces = VGroup() 651 | for result in results: 652 | brace = Brace(VGroup(results[0], result), RIGHT, buff = 0.5, color = GREY) 653 | braces.add(brace) 654 | 655 | cum_datas = np.array([round(scipy.stats.binom.cdf(x, 10, 0.7), 4) for x in range(0, 10 + 1)]) 656 | cum_results = VGroup() 657 | for brace, data in zip(braces, cum_datas): 658 | cum = MathTex(str(data), font_size = 60, color = YELLOW) 659 | cum.next_to(brace, RIGHT, buff = 0.5) 660 | cum_results.add(cum) 661 | 662 | # Show binom probability results 663 | self.play( 664 | FadeOut(histo), 665 | MoveToTarget(formulas), 666 | AnimationGroup( 667 | LaggedStartMap(FadeIn, equals, shift = LEFT, lag_ratio = 0.1), 668 | LaggedStartMap(FadeIn, results, shift = LEFT, lag_ratio = 0.1), 669 | lag_ratio = 0.3 670 | ), 671 | run_time = 3 672 | ) 673 | self.wait() 674 | 675 | cum_brace = braces[0] 676 | cum_result = cum_results[0] 677 | self.play( 678 | Create(cum_brace), 679 | Write(cum_result) 680 | ) 681 | self.wait() 682 | 683 | # Add prob up to 1 684 | for k in range(1, len(braces)): 685 | self.play( 686 | Transform(cum_brace, braces[k]), 687 | Transform(cum_result, cum_results[k]), 688 | run_time = 0.75 689 | ) 690 | self.wait(0.25) 691 | 692 | # highlight 1 693 | self.play(Circumscribe(cum_result, color = YELLOW_D, run_time = 3)) 694 | self.wait() 695 | 696 | 697 | # 698 | group.add(formulas, equals, results, cum_brace, cum_result) 699 | 700 | self.play( 701 | group.animate.scale(0.75).shift(RIGHT + UP), 702 | FadeIn(self.histo) 703 | ) 704 | 705 | histo_one_kwargs = { 706 | "width": config["frame_width"] - 2, "height": 10/3*(config["frame_height"] - 3.25), 707 | "x_tick_freq": 1, "x_label_freq": 1, "y_max_value": 1, "y_tick_num": 10, 708 | "include_h_lines": True, "bar_colors": [RED, GREEN, BLUE, YELLOW] 709 | } 710 | histo_one = self.get_histogram(10, 0.7, **histo_one_kwargs) 711 | histo_one.center().to_edge(DOWN) 712 | 713 | bars = self.histo.bars 714 | bars.save_state() 715 | bars.generate_target() 716 | bars.target.arrange_submobjects(DOWN, buff = 0).next_to(histo.axes.c2p(7.5,0), UP, buff = 0) 717 | 718 | self.play( 719 | MoveToTarget(bars, lag_ratio = 0.1), 720 | run_time = 3 721 | ) 722 | 723 | self.camera.frame.save_state() 724 | self.play( 725 | self.camera.frame.animate.shift(10*UP), 726 | group.animate.shift(9*UP), 727 | FadeIn(histo_one.axes), 728 | run_time = 3 729 | ) 730 | 731 | dot = Dot(point = histo_one.axes.c2p(0,1), color = YELLOW_D) 732 | trace = TracedPath(dot.get_center, dissipating_time=0.5, stroke_width = 4, stroke_color = YELLOW_D, stroke_opacity=[1,0]) 733 | self.add(dot, trace) 734 | self.play( 735 | Circumscribe(histo_one.axes.y_labels[-1], color = YELLOW_D, run_time = 3), 736 | dot.animate(run_time = 3).move_to(histo_one.axes.c2p(11,1)), 737 | ) 738 | trace.clear_updaters() 739 | dot.clear_updaters() 740 | self.play(FadeOut(dot), FadeOut(trace)) 741 | self.wait() 742 | 743 | 744 | self.play( 745 | Restore(self.camera.frame), 746 | Restore(bars), 747 | FadeOut(histo_one.axes), 748 | run_time = 4 749 | ) 750 | self.remove(*group) 751 | self.wait() 752 | 753 | def changing_parameters(self): 754 | num_line = NumberLine(x_range = [0, 1, 0.25], length = 6, include_numbers=True, decimal_number_config={"num_decimal_places": 2}) 755 | num_line.to_edge(UP, buff = 1) 756 | 757 | label = MathTex("p", "=").next_to(num_line, RIGHT, buff = 0.75) 758 | 759 | p_val = ValueTracker(0.7) 760 | p_dec = DecimalNumber(p_val.get_value())\ 761 | .next_to(label, RIGHT, aligned_edge=UP)\ 762 | .shift(0.1*UP) 763 | 764 | dot = Dot(point = num_line.n2p(p_val.get_value()), color = PINK, radius = 0.1) 765 | dot.set_sheen(-0.3, DR) 766 | 767 | self.play( 768 | Create(num_line, run_time = 2), 769 | Write(label), 770 | Write(p_dec), 771 | FadeIn(dot, shift = DOWN, run_time = 2) 772 | ) 773 | self.wait() 774 | 775 | p_dec.add_updater(lambda dec: dec.set_value(p_val.get_value())) 776 | dot.add_updater(lambda d: d.move_to(num_line.n2p(p_val.get_value()))) 777 | 778 | histo = self.histo 779 | histo.p_val = p_val 780 | histo.n = self.n 781 | def update_histogram(hist): 782 | new_dist = scipy.stats.binom(hist.n, hist.p_val.get_value()) 783 | new_data = np.array([new_dist.pmf(x) for x in range(0, hist.n + 1)]) 784 | new_bars = hist.get_bars(new_data) 785 | new_bars.match_style(hist.bars) 786 | hist.bars.become(new_bars) 787 | 788 | for prop in [0.5, 0.1, 0.4, 0.8]: 789 | self.play( 790 | p_val.animate.set_value(prop), 791 | UpdateFromFunc(histo, update_histogram, suspend_mobject_updating=False), 792 | run_time = 4.5 793 | ) 794 | self.wait(0.5) 795 | self.wait(3) 796 | 797 | 798 | class NoNeedFor320000Calc(Scene): 799 | def construct(self): 800 | panic = Tex("Keine Panik auf der Titanic") 801 | panic.scale(1.75) 802 | panic.to_corner(UL) 803 | 804 | rescue = Tex("Rettung naht...") 805 | rescue.scale(1.25) 806 | rescue.to_edge(DOWN, buff = 0.5) 807 | 808 | self.play(FadeIn(panic, shift = 5*RIGHT), run_time = 1.5) 809 | self.wait(0.5) 810 | 811 | self.play(FadeIn(rescue, shift = 5*LEFT), run_time = 1.5) 812 | self.wait() 813 | 814 | bernoulli = Tex("Bernoulli", "$-$", "Formel") 815 | bernoulli[0].set_color(BLUE) 816 | bernoulli[-1].set_color(YELLOW_D) 817 | def update(mob): 818 | x = random.uniform(-5,5) 819 | y = random.uniform(-2.5,2.5) 820 | 821 | bernoulli.move_to(x * RIGHT + y * UP) 822 | mob.become(bernoulli) 823 | 824 | self.add(bernoulli) 825 | self.play( 826 | UpdateFromFunc(bernoulli, update), 827 | run_time = 2 828 | ) 829 | bernoulli.scale(2) 830 | bernoulli.center() 831 | 832 | brain = SVGMobject(SVG_DIR + "BrainBulb") 833 | brain.next_to(bernoulli, RIGHT) 834 | self.play(Create(brain), run_time = 2) 835 | self.play(Indicate(brain), run_time = 1) 836 | self.wait(2) 837 | 838 | 839 | class Thumbnail(HistoScene): 840 | def construct(self): 841 | total_calc = 319152 842 | n = 10 843 | p = 0.7 844 | histo_kwargs = { 845 | "width": config["frame_width"] - 2, "height": config["frame_height"] - 3.25, 846 | "x_tick_freq": 1, "x_label_freq": 1, "y_max_value": 0.3, "y_tick_num": 3, 847 | "bar_colors": [YELLOW, GREEN, BLUE] 848 | } 849 | histo = self.get_histogram(n, p, **histo_kwargs) 850 | histo.center().to_edge(DOWN) 851 | self.add(histo) 852 | 853 | 854 | calc1 = Tex("$319.152$ ") 855 | calc1.scale(2.5) 856 | calc1.move_to(histo.axes.c2p(2.5, 0.25)) 857 | calc1.set_color(RED) 858 | 859 | calc2 = Tex("Wiederholungen?!") 860 | calc2.set(width = calc1.width + 1) 861 | calc2.next_to(calc1, DOWN) 862 | calc2.set_color_by_gradient(RED, WHITE) 863 | calc2.add_background_rectangle() 864 | self.add(calc1, calc2) 865 | 866 | 867 | arrow = ArcBetweenPoints( 868 | calc1.get_corner(UR) + 0.25*RIGHT, 869 | histo.bars[6].get_top() + 0.2*UP, 870 | angle = -90*DEGREES, 871 | stroke_width = 6 872 | ) 873 | arrow.set_color([histo.bars[6].get_color(), RED]) 874 | arrow.add_tip(tip_length = 0.35) 875 | arrow[-1].set_color(histo.bars[6].get_color()) 876 | self.add(arrow) 877 | 878 | 879 | title = Tex("Histogramme") 880 | title.scale(4) 881 | title.set_color_by_gradient(YELLOW_E, GREEN, BLUE) 882 | title.set_stroke(color = WHITE, width = 1) 883 | title.to_edge(UP, buff = 0.2) 884 | self.add(title) 885 | 886 | 887 | 888 | 889 | 890 | 891 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/Blood_Donation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 15 | 23 | 24 | 25 | 26 | 27 | 29 | 30 | 31 | 32 | 40 | 48 | 49 | 50 | 51 | 52 | 54 | 55 | 56 | 57 | 65 | 69 | 73 | 75 | 78 | 82 | 87 | 88 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/BrainBulb.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 55 | 60 | 62 | 78 | 85 | 88 | 97 | 101 | 103 | 105 | 107 | 109 | 111 | 161 | 166 | 168 | 184 | 191 | 194 | 203 | 206 | 208 | 210 | 212 | 214 | 216 | 217 | 218 | 225 | 232 | 237 | 238 | 239 | 241 | 244 | 247 | 249 | 252 | 255 | 258 | 260 | 263 | 266 | 268 | 271 | 272 | 273 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/GummyBear.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 22 | 29 | 32 | 35 | 37 | 39 | 41 | 43 | 45 | 47 | 49 | 51 | 53 | 55 | 57 | 59 | 61 | 63 | 65 | 68 | 71 | 72 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/Jakob_Bernoulli.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visual-x/manim-projects/00d8b9f715212c2de35c9c1f8f894b0823167bdc/2022/Binomial Distribution/SVGs and IMGs/Jakob_Bernoulli.jpg -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/Rabbit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 12 | 14 | 16 | 18 | 19 | 22 | 23 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/clubs.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/diamonds.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/emoji_couple_holding_hands.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 15 | 19 | 22 | 28 | 31 | 34 | 36 | 38 | 40 | 42 | 44 | 46 | 47 | 48 | 49 | 51 | 57 | 60 | 63 | 65 | 67 | 69 | 71 | 73 | 75 | 76 | 77 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/emoji_couple_holding_hands_ww.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 20 | 23 | 29 | 32 | 35 | 37 | 39 | 41 | 43 | 45 | 47 | 48 | 49 | 51 | 53 | 57 | 60 | 66 | 69 | 72 | 74 | 76 | 78 | 80 | 82 | 84 | 85 | 86 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/emoji_heart_eyes.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 9 | 14 | 15 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/emoji_middle_finger.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | 20 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/emoji_sunglas.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/hearts.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/open-tafelwerk-tables.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visual-x/manim-projects/00d8b9f715212c2de35c9c1f8f894b0823167bdc/2022/Binomial Distribution/SVGs and IMGs/open-tafelwerk-tables.png -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/rose_illustration.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 34 | 38 | 41 | 46 | 49 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/smartwatch.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 14 | 18 | 20 | 22 | 24 | 26 | 27 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/spades.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/table_binom_cdf_100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visual-x/manim-projects/00d8b9f715212c2de35c9c1f8f894b0823167bdc/2022/Binomial Distribution/SVGs and IMGs/table_binom_cdf_100.png -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/table_binom_cdf_10_20_25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visual-x/manim-projects/00d8b9f715212c2de35c9c1f8f894b0823167bdc/2022/Binomial Distribution/SVGs and IMGs/table_binom_cdf_10_20_25.png -------------------------------------------------------------------------------- /2022/Binomial Distribution/SVGs and IMGs/table_binom_cdf_50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visual-x/manim-projects/00d8b9f715212c2de35c9c1f8f894b0823167bdc/2022/Binomial Distribution/SVGs and IMGs/table_binom_cdf_50.png -------------------------------------------------------------------------------- /2022/TrigFunc-Parameter-d.py: -------------------------------------------------------------------------------- 1 | from manim import * 2 | 3 | XMARK_TEX = "\\ding{55}" 4 | 5 | def p2c(y_value, min, max, colors): 6 | alpha = inverse_interpolate(min, max, y_value) 7 | index, sub_alpha = integer_interpolate(0, len(colors) - 1, alpha) 8 | 9 | return interpolate_color(colors[index], colors[index + 1], sub_alpha) 10 | 11 | 12 | class Intro(Scene): 13 | def construct(self): 14 | 15 | scr = VGroup(*[ScreenRectangle(height = 3, stroke_width = 3, stroke_color = GREY) for x in range(4)]) 16 | scr.arrange_in_grid(2,2) 17 | scr.to_edge(DOWN, buff = 0.4) 18 | 19 | func = MathTex("f(x)", "=", "a", "\\cdot", "\\sin", "\\big(", "b", "\\cdot", "(", "x", "+", "c", ")","\\big)", "+", "d", font_size = 80) 20 | func.to_edge(UP, buff = 0.3) 21 | func[2].set_color(RED) 22 | func[6].set_color(BLUE) 23 | func[11].set_color(YELLOW) 24 | func[-1].set_color(GREEN) 25 | 26 | self.play( 27 | Create(scr[:-1], lag_ratio = 0.2, run_time = 3), 28 | Write(func, run_time = 1), 29 | ) 30 | self.wait() 31 | 32 | abcd = VGroup(*[func[index].copy() for index in [2, 6, 11, -1]]) 33 | for alph, rect, direc in zip(abcd, scr, [LEFT, RIGHT, LEFT, RIGHT]): 34 | alph.generate_target() 35 | alph.target.next_to(rect, direc) 36 | 37 | self.play( 38 | LaggedStart(*[MoveToTarget(alph) for alph in abcd[:-1]], lag_ratio = 0.2), 39 | run_time = 3 40 | ) 41 | self.wait() 42 | 43 | 44 | sur = SurroundingRectangle(abcd[-1], color = GREEN) 45 | self.play(Create(sur), run_time = 2) 46 | self.wait(0.5) 47 | self.play(FadeOut(sur, scale = 2)) 48 | self.wait() 49 | 50 | 51 | self.play( 52 | MoveToTarget(abcd[-1]), 53 | Create(scr[-1]), 54 | run_time = 2 55 | ) 56 | self.wait(3) 57 | 58 | 59 | group = Group(*self.mobjects) 60 | self.play(FadeOut(group, scale = 5), run_time = 1.5) 61 | self.wait() 62 | 63 | 64 | class TableToGraph(Scene): 65 | def construct(self): 66 | self.x_values = np.linspace(0, 2*np.pi, 9) 67 | self.sin_values = [round(np.sin(x), 2) for x in self.x_values] 68 | self.sin_values[-1] = 0.00 69 | self.sind_values = [x + 2 for x in self.sin_values] 70 | 71 | axes = self.axes = NumberPlane( 72 | x_range = [0, 9*PI/4, 1], y_range = [-4, 4, PI/4], 73 | x_length = config["frame_width"] * 2/5, y_length = 7, 74 | background_line_style={"stroke_color": BLUE_E, "stroke_width": 1} 75 | ) 76 | axes.to_edge(RIGHT) 77 | self.origin = axes.c2p(0,0) 78 | axes.x_axis.add_tip(tip_length = 0.25) 79 | axes.y_axis.add_tip(tip_length = 0.25) 80 | 81 | self.x_axis_label = MathTex("x", color = GREY, font_size = 24).next_to(axes.x_axis, UP, buff = 0.1, aligned_edge=RIGHT) 82 | self.y_axis_label = MathTex("y", color = GREY, font_size = 24).next_to(axes.y_axis, UP, buff = 0.1) 83 | 84 | self.x_axis_numbers = self.get_x_axis_numbers() 85 | self.y_axis_numbers = self.get_y_axis_numbers() 86 | 87 | self.colors = [PINK, YELLOW, GREEN, RED, BLUE] 88 | 89 | self.myTemplate = TexTemplate() 90 | self.myTemplate.add_to_preamble(r"\usepackage{pifont}") 91 | 92 | self.build_table_and_sin_graph() 93 | self.get_idea_for_new_parameter() 94 | self.explain_parameter() 95 | 96 | 97 | def build_table_and_sin_graph(self): 98 | x_values, sin_values, sind_values = self.x_values, self.sin_values, self.sind_values 99 | axes = self.axes 100 | 101 | x_strings = [ 102 | "0", "\\frac{1}{4}\\pi", "\\frac{1}{2}\\pi", "\\frac{3}{4}\\pi", "\\pi", 103 | "\\frac{5}{4}\\pi", "\\frac{3}{2}\\pi", "\\frac{7}{4}\\pi", "2\\pi" 104 | ] 105 | 106 | x_texs = VGroup(*[MathTex(x_str, font_size = 36) for x_str in x_strings]) 107 | for index in [1,2,3,5,6,7]: 108 | x_texs[index][0][:3].scale(0.65) 109 | sin_texs = VGroup(*[MathTex(str(sin), font_size = 36) for sin in sin_values]) 110 | sind_texs = VGroup(*[MathTex(str(sind), font_size = 36) for sind in sind_values]) 111 | 112 | 113 | table = VGroup(*x_texs, *sin_texs, *sind_texs)\ 114 | .arrange_in_grid(rows = len(x_texs), cols = 3, col_widths=[1, 2, 3], flow_order = "dr")\ 115 | .to_edge(LEFT, buff = 1)\ 116 | .shift(0.5*DOWN) 117 | 118 | 119 | x_label = MathTex("x", font_size = 40).next_to(table[0], UP, buff = 0.6) 120 | sin_label = MathTex("\\sin", "(x)", font_size = 40).next_to(table[9], UP, buff = 0.5) 121 | sind_label = MathTex("\\sin", "(x)", "+", "2", font_size = 40).next_to(table[18], UP, buff = 0.5) 122 | for label in sin_label, sind_label: 123 | label.set_color_by_tex_to_color_map({"+": YELLOW, "2": YELLOW, "\\sin": RED}) 124 | 125 | 126 | self.play( 127 | Write(x_label), 128 | FadeIn(x_texs, shift = 0.5*DOWN, lag_ratio = 0.1), 129 | run_time = 2 130 | ) 131 | self.wait() 132 | 133 | # Create sin_values and transform dots_x into dots_sin 134 | dots_axis = VGroup(*[Dot(axes.c2p(x_val, 0), radius = 0.06) for x_val in x_values]) 135 | self.play( 136 | LaggedStartMap( 137 | Create, VGroup(axes, self.x_axis_label, self.y_axis_label, self.x_axis_numbers, self.y_axis_numbers), 138 | lag_ratio = 0.2, run_time = 2 139 | ), 140 | AnimationGroup( 141 | *[Transform(tex.copy(), dot) for tex, dot in zip(x_texs, dots_axis)], 142 | lag_ratio = 0.2, run_time = 3 143 | ), 144 | ) 145 | self.wait() 146 | 147 | self.play( 148 | FocusOn(sin_label, run_time = 1), 149 | Write(sin_label, rate_func = squish_rate_func(smooth, 0.5, 1), run_time = 2) 150 | ) 151 | self.play(AnimationGroup(*[Write(tex) for tex in sin_texs], lag_ratio = 0.2, run_time = 2)) 152 | self.wait() 153 | 154 | dots_sin = VGroup(*[Dot(axes.c2p(x_val, sin_val), radius = 0.06, color = RED) for x_val, sin_val in zip(x_values, sin_values)]) 155 | dots_sin2 = dots_sin.copy() 156 | graph_sin = axes.get_graph(lambda x: np.sin(x), x_range = [0, 2*np.pi], color = RED) 157 | 158 | self.play( 159 | AnimationGroup( 160 | *[ReplacementTransform(tex.copy(), dot) for tex, dot in zip(sin_texs, dots_sin)], 161 | lag_ratio = 0.2, run_time = 3 162 | ), 163 | ) 164 | self.add(dots_sin2) 165 | 166 | self.play( 167 | TransformFromCopy(dots_axis, dots_sin.copy()), 168 | Create(graph_sin), 169 | run_time = 2 170 | ) 171 | self.remove(dots_sin2) 172 | self.wait() 173 | 174 | 175 | self.x_texs, self.sin_texs, self.sind_texs = x_texs, sin_texs, sind_texs 176 | self.sin_label, self.sind_label = sin_label, sind_label 177 | self.graph_sin, self.dots_sin = graph_sin, dots_sin 178 | 179 | def get_idea_for_new_parameter(self): 180 | sind_label = self.sind_label 181 | 182 | zero_zero_rect = SurroundingRectangle(VGroup(self.x_texs[0], self.sin_texs[0]), color = RED) 183 | self.play(FadeIn(zero_zero_rect, scale = 5), run_time = 2) 184 | self.wait() 185 | 186 | xmark = Tex(XMARK_TEX, tex_template = self.myTemplate, color = RED) 187 | xmark.move_to(self.origin) 188 | 189 | self.play(ReplacementTransform(zero_zero_rect, xmark)) 190 | self.wait() 191 | 192 | trans_group = VGroup(self.graph_sin, self.dots_sin, xmark) 193 | for c in [-PI, 3*PI/2, -PI/2]: 194 | self.play( 195 | trans_group.animate.shift(c * self.axes.x_axis.unit_size * RIGHT), run_time = 1.5 196 | ) 197 | self.wait(0.5) 198 | self.wait() 199 | 200 | 201 | trans_group2 = trans_group.copy().set_color(BLUE) 202 | self.add(trans_group2) 203 | self.bring_to_front(trans_group) 204 | for d in [1, -3, 4]: 205 | self.play( 206 | trans_group2.animate.shift(d * self.axes.y_axis.unit_size * UP), run_time = 1.5 207 | ) 208 | self.wait(0.5) 209 | self.wait() 210 | 211 | def explain_parameter(self): 212 | sin_texs = self.sin_texs 213 | dots_sind = self.dots_sind = VGroup(*[ 214 | Dot(self.axes.c2p(x_val, sind_val), radius = 0.06, color = BLUE) 215 | for x_val, sind_val in zip(self.x_values, self.sind_values) 216 | ]) 217 | 218 | 219 | 220 | graph_arrows = self.get_graph_arrows() 221 | table_arrows = self.table_arrows = self.get_table_arrows() 222 | multiplicators = self.get_multiplicators(number = 2) 223 | 224 | 225 | sur_rect_input = SurroundingRectangle(sin_texs[2]) 226 | self.play(Flash(self.dots_sin[2]), run_time = 2) 227 | self.play(Create(sur_rect_input), run_time = 1.5) 228 | self.wait() 229 | 230 | self.play(GrowFromEdge(graph_arrows[2], DOWN), run_time = 2) 231 | self.play(Flash(dots_sind[2]), run_time = 2) 232 | self.wait() 233 | 234 | sur_rect_output = SurroundingRectangle(self.sind_texs[2]) 235 | self.play(ReplacementTransform(sur_rect_input, sur_rect_output, path_arc = np.pi/3), run_time = 1) 236 | self.play(Write(self.sind_texs[2])) 237 | self.wait() 238 | 239 | self.play( 240 | GrowFromEdge(table_arrows[2], LEFT, run_time = 2), 241 | Write(multiplicators[2]), 242 | Uncreate(sur_rect_output) 243 | ) 244 | self.wait() 245 | 246 | 247 | # Adding all other arrows and multiplicators 248 | self.play( 249 | AnimationGroup( 250 | *[GrowFromEdge(graph_arrows[index], DOWN) for index in range(len(graph_arrows)) if index != 2], 251 | *[GrowFromEdge(table_arrows[index], LEFT) for index in range(len(graph_arrows)) if index != 2], 252 | *[Write(multiplicators[index]) for index in range(len(graph_arrows)) if index != 2], 253 | *[FadeIn(self.sind_texs[index]) for index in range(len(graph_arrows)) if index != 2], 254 | lag_ratio = 0.1 255 | ), 256 | run_time = 8 257 | ) 258 | self.wait() 259 | 260 | 261 | # Write equation 262 | self.play( 263 | AnimationGroup( 264 | *[Indicate(number, color = YELLOW, scale_factor = 1.5) for number in multiplicators], 265 | lag_ratio = 0.1 266 | ), 267 | run_time = 3 268 | ) 269 | 270 | self.play( 271 | TransformFromCopy(self.sin_label[:2], self.sind_label[:2], path_arc = np.pi/3), 272 | run_time = 2 273 | ) 274 | self.play(FadeIn(self.sind_label[2:], shift = 2*LEFT), run_time = 2) 275 | self.play(Circumscribe(self.sind_label, color = BLUE, fade_out=True, run_time = 3)) 276 | self.wait(3) 277 | 278 | 279 | # functions 280 | def get_x_axis_numbers(self): 281 | x_axis_nums = [np.pi/2, np.pi, 3/2*np.pi, 2*np.pi] 282 | x_axis_coords = VGroup(*[ 283 | MathTex(tex, color = LIGHT_GREY, font_size = 24)\ 284 | .add_background_rectangle()\ 285 | .next_to(self.axes.c2p(num, 0), DOWN) 286 | for tex, num in zip( 287 | ["\\pi/2", "\\pi", "3\\pi/2", "2\\pi"], 288 | x_axis_nums 289 | ) 290 | ]) 291 | return x_axis_coords 292 | 293 | def get_y_axis_numbers(self): 294 | y_axis_nums = list(range(-3,4)) 295 | y_axis_coords = VGroup(*[ 296 | MathTex(tex, color = LIGHT_GREY, font_size = 24).next_to(self.axes.y_axis.n2p(num), LEFT) 297 | for tex, num in zip( 298 | [-3,-2,-1,0,1,2,3], 299 | y_axis_nums 300 | ) 301 | ]) 302 | return y_axis_coords 303 | 304 | def get_graph_arrows(self): 305 | 306 | graph_arrows = VGroup(*[ 307 | Line(start.get_center(), end.get_center(), buff = 0).set_color([RED, BLUE]) 308 | for start, end in zip(self.dots_sin, self.dots_sind) 309 | ]) 310 | for line in graph_arrows: 311 | line.add_tip(tip_length = 0.2) # adding a tip 312 | line[1].set_color(BLUE) # color the tip 313 | 314 | return graph_arrows 315 | 316 | def get_table_arrows(self): 317 | table_arrows = VGroup(*[ 318 | Line(ORIGIN, RIGHT, buff = 0).set_color([BLUE, RED]) 319 | for _ in range(len(self.sin_texs)) 320 | ]) 321 | 322 | for arrow, tex in zip(table_arrows, self.sin_texs): 323 | arrow.add_tip(tip_length = 0.2) 324 | arrow[1].set_color(BLUE) 325 | arrow.next_to(tex, RIGHT, buff = 0.5) 326 | 327 | table_arrows.shift(0.1*RIGHT) 328 | for arrow in table_arrows[1:]: 329 | arrow.align_to(table_arrows[0], LEFT) 330 | 331 | return table_arrows 332 | 333 | def get_multiplicators(self, number, font_size = 24): 334 | mults = VGroup() 335 | if number > 0: 336 | sign = "+" 337 | else: 338 | sign = "-" 339 | for arrow in self.table_arrows: 340 | mult = MathTex(sign, str(abs(number)), font_size = 24, color = YELLOW) 341 | mult.next_to(arrow, UP, buff = 0) 342 | mults.add(mult) 343 | 344 | return mults 345 | 346 | 347 | class DifferentFunctions(Scene): 348 | def construct(self): 349 | self.axes_kwargs = { 350 | "x_length": 5, "y_length": 5 * 9/16, 351 | "background_line_style": {"stroke_color": BLUE_E, "stroke_width": 1} 352 | } 353 | self.part_buff = 0.75 354 | self.colors = [BLUE, RED, YELLOW, GREEN] 355 | self.d_val = ValueTracker(0) 356 | 357 | self.starting_mobs = VGroup() 358 | self.titles = VGroup() 359 | 360 | self.linear() 361 | self.quadratic() 362 | self.power() 363 | self.trig() 364 | self.play_animations() 365 | 366 | def linear(self): 367 | axes = NumberPlane(x_range = [-4, 4, 4], y_range = [-10, 20, 1], **self.axes_kwargs) 368 | axes.to_corner(UL, buff = self.part_buff) 369 | frame = ScreenRectangle(height = axes.height, color = GREY, stroke_width = 2) 370 | frame.move_to(axes) 371 | 372 | title = Tex("Lineare Funktionen") 373 | title.next_to(frame, UP, buff = 0.1) 374 | 375 | graph1 = axes.get_graph(lambda x: x, x_range = [-4, 4], color = RED) 376 | graph2 = always_redraw(lambda: axes.get_graph( 377 | lambda x: x + self.d_val.get_value(), 378 | x_range = [-4,4], 379 | color = p2c(self.d_val.get_value(), -5, 10, self.colors) 380 | )) 381 | 382 | self.starting_mobs.add(axes, frame, graph2, graph1) 383 | self.titles.add(title) 384 | 385 | def quadratic(self): 386 | axes = NumberPlane(x_range = [-4, 4, 4], y_range = [-10, 20, 1], **self.axes_kwargs) 387 | axes.to_corner(UR, buff = self.part_buff) 388 | frame = ScreenRectangle(height = axes.height, color = GREY, stroke_width = 2) 389 | frame.move_to(axes) 390 | 391 | title = Tex("Quadratische Funktionen") 392 | title.next_to(frame, UP, buff = 0.1) 393 | 394 | graph1 = axes.get_graph(lambda x: 1/2 * x**2, x_range = [-4, 4], color = RED) 395 | graph2 = always_redraw(lambda: axes.get_graph( 396 | lambda x: 1/2 * x**2 + self.d_val.get_value(), 397 | x_range = [-4,4], 398 | color = p2c(self.d_val.get_value(), -5, 10, self.colors) 399 | )) 400 | 401 | self.starting_mobs.add(axes, frame, graph2, graph1) 402 | self.titles.add(title) 403 | 404 | def power(self): 405 | axes = NumberPlane(x_range = [-4, 4, 4], y_range = [-10, 20, 1], **self.axes_kwargs) 406 | axes.to_corner(DL, buff = self.part_buff) 407 | frame = ScreenRectangle(height = axes.height, color = GREY, stroke_width = 2) 408 | frame.move_to(axes) 409 | 410 | title = Tex("Potenzfunktionen") 411 | title.next_to(frame, DOWN, buff = 0.1) 412 | 413 | graph1 = axes.get_graph(lambda x: 3*np.sqrt(x), x_range = [0, 4, 0.05], color = RED) 414 | graph2 = always_redraw(lambda: axes.get_graph( 415 | lambda x: 3*np.sqrt(x) + self.d_val.get_value(), 416 | x_range = [0, 4, 0.05], 417 | color = p2c(self.d_val.get_value(), -5, 10, self.colors) 418 | )) 419 | 420 | self.starting_mobs.add(axes, frame, graph2, graph1) 421 | self.titles.add(title) 422 | 423 | def trig(self): 424 | axes = NumberPlane(x_range = [-4, 4, 4], y_range = [-10, 20, 1], **self.axes_kwargs) 425 | axes.to_corner(DR, buff = self.part_buff) 426 | frame = ScreenRectangle(height = axes.height, color = GREY, stroke_width = 2) 427 | frame.move_to(axes) 428 | 429 | title = Tex("Trigonometr. Funktionen") 430 | title.next_to(frame, DOWN, buff = 0.1) 431 | 432 | graph1 = axes.get_graph(lambda x: 5*np.sin(1.75*x), x_range = [-4, 4], color = RED) 433 | graph2 = always_redraw(lambda: axes.get_graph( 434 | lambda x: 5*np.sin(1.75*x) + self.d_val.get_value(), 435 | x_range = [-4,4], 436 | color = p2c(self.d_val.get_value(), -5, 10, self.colors) 437 | )) 438 | 439 | self.starting_mobs.add(axes, frame, graph2, graph1) 440 | self.titles.add(title) 441 | 442 | def play_animations(self): 443 | self.play(Create(self.starting_mobs, lag_ratio = 0.1), run_time = 3) 444 | self.wait() 445 | 446 | self.play( 447 | AnimationGroup(*[Write(title) for title in self.titles], lag_ratio = 0.25), 448 | run_time = 3 449 | ) 450 | self.wait() 451 | 452 | eq = MathTex("g(x)", "=", "f(x)", "+", "d", font_size = 90) 453 | eq[0].add_updater(lambda mob: mob.set_color(p2c(self.d_val.get_value(), -5, 10, self.colors))) 454 | eq[3].add_updater(lambda mob: mob.set_color(p2c(self.d_val.get_value(), -5, 10, self.colors))) 455 | eq[4].add_updater(lambda mob: mob.set_color(p2c(self.d_val.get_value(), -5, 10, self.colors))) 456 | eq[2].set_color(RED) 457 | eq.add_background_rectangle(buff = 0.2, stroke_width = 1, stroke_opacity = 0.5) 458 | 459 | self.play( 460 | FadeIn(eq[0]), 461 | Write(eq[1:]), 462 | ) 463 | self.wait() 464 | 465 | ds = [10, -5, 12, 5] 466 | for d in ds: 467 | self.play(self.d_val.animate.set_value(d), run_time = 3) 468 | self.wait() 469 | 470 | par_tex = Tex("Parameter ", "$d$")\ 471 | .rotate(90*DEGREES)\ 472 | .set_fill(opacity = 0)\ 473 | .set_stroke(width = 0.75, opacity = 0.75, color = GREY)\ 474 | .set(height = 4, color = GREY)\ 475 | .move_to(np.array([-1.06481703, 0, 0])) 476 | 477 | d_copy = eq[-1].copy() 478 | self.play(Transform(d_copy, par_tex[-1]), run_time = 2) 479 | self.wait(2) 480 | 481 | 482 | class ParameterInfluence(Scene): 483 | def construct(self): 484 | self.x_min = 0 485 | self.x_max = 2*PI 486 | 487 | self.axes_kwargs = { 488 | "x_range": [self.x_min - 0.25, self.x_max + 0.5, 1], "y_range": [-4.25, 4.25, PI/4], 489 | "x_length": config["frame_width"] * 2/5, "y_length": 7, 490 | "background_line_style": {"stroke_color": GREY_D, "stroke_width": 1} 491 | } 492 | self.axes = NumberPlane(**self.axes_kwargs).to_edge(RIGHT, buff = 1.5) 493 | self.origin = self.axes.c2p(0,0) 494 | self.axes.x_axis.add_tip(tip_length = 0.25) 495 | self.axes.y_axis.add_tip(tip_length = 0.25) 496 | 497 | self.d_val = ValueTracker(0) 498 | self.colors = [PINK, BLUE, RED, YELLOW, GREEN] 499 | 500 | 501 | self.setup_scene() 502 | 503 | 504 | def setup_scene(self): 505 | axes, d_val = self.axes, self.d_val 506 | 507 | x_axis_ticks = self.get_x_axis_ticks([PI/2, PI, 3/2*PI, TAU]) 508 | x_axis_numbers = self.get_x_axis_numbers(font_size = 30) 509 | y_axis_ticks = self.get_y_axis_ticks(-4, 4) 510 | y_axis_numbers = self.get_y_axis_numbers(-4, 3, font_size = 30) 511 | 512 | graph_ref = axes.get_graph(lambda x: np.sin(x), x_range = [self.x_min, self.x_max], color = RED, stroke_opacity = 0.5) 513 | graph = always_redraw(lambda: axes.get_graph( 514 | lambda x: np.sin(x) + d_val.get_value(), x_range = [self.x_min, self.x_max], 515 | color = p2c(d_val.get_value(), -3, 3, self.colors) 516 | ) 517 | ) 518 | 519 | graph_tex = always_redraw(lambda: MathTex("\\sin", "(", "x", ")")\ 520 | .add_background_rectangle()\ 521 | .next_to(graph.point_from_proportion(1), RIGHT + UP)\ 522 | .shift(LEFT) 523 | ) 524 | d_graph_dec = always_redraw(lambda: DecimalNumber(d_val.get_value(), num_decimal_places=1, include_sign=True)\ 525 | .next_to(graph_tex, RIGHT, buff = 0.1)\ 526 | .set_color(p2c(d_val.get_value(), -3, 3, self.colors)) 527 | ) 528 | 529 | d_line = self.d_line = self.get_d_line( 530 | -4.25, 4.25, x_step = 0.5, line_length = self.axes_kwargs["y_length"], 531 | numbers_to_exclude = [-3.5 + k for k in range(8)] 532 | ) 533 | d_dot = self.d_dot = always_redraw(lambda: self.get_d_dot()) 534 | d_par_line = always_redraw(lambda: self.get_dot_to_axes_line()) 535 | 536 | par_tex = Tex("Parameter ", "$d$")\ 537 | .rotate(90*DEGREES)\ 538 | .set_fill(opacity = 0)\ 539 | .set_stroke(width = 0.75, opacity = 0.75)\ 540 | .set(height = 4, color = GREY)\ 541 | .move_to(midpoint(d_line.get_center(), axes.y_axis.get_center())) 542 | 543 | brace_up = Brace(Line(d_line.n2p(0), d_line.n2p(+4.25)), LEFT, buff = 0.75) 544 | brace_down = Brace(Line(d_line.n2p(0), d_line.n2p(-4.25)), LEFT, buff = 0.75) 545 | 546 | def update_d_pos(mob): 547 | mob.set_color(p2c(d_val.get_value(), -3, 3, self.colors)) 548 | if d_val.get_value() <= 0: 549 | mob.set_color(DARK_GREY) 550 | def update_d_neg(mob): 551 | mob.set_color(p2c(d_val.get_value(), -3, 3, self.colors)) 552 | if d_val.get_value() >= 0: 553 | mob.set_color(DARK_GREY) 554 | 555 | brace_up.add_updater(update_d_pos) 556 | brace_down.add_updater(update_d_neg) 557 | 558 | brace_text_up = Tex("Verschiebung\\\\", "nach oben")\ 559 | .next_to(brace_up, LEFT) 560 | brace_text_down = Tex("Verschiebung\\\\", "nach unten")\ 561 | .next_to(brace_down, LEFT) 562 | 563 | def update_tex_pos(mob): 564 | mob.set_color(WHITE) 565 | if d_val.get_value() <= 0: 566 | mob.set_color(DARK_GREY) 567 | def update_tex_neg(mob): 568 | mob.set_color(WHITE) 569 | if d_val.get_value() >= 0: 570 | mob.set_color(DARK_GREY) 571 | 572 | brace_text_up.add_updater(update_tex_pos) 573 | brace_text_down.add_updater(update_tex_neg) 574 | 575 | # ANIMATIONS 576 | self.add(par_tex[-1]) 577 | self.wait(2) 578 | 579 | self.play( 580 | LaggedStartMap(Create, VGroup(axes, x_axis_ticks, x_axis_numbers, y_axis_ticks, y_axis_numbers), lag_ratio = 0.25), 581 | Create(par_tex[:-1]), 582 | FadeIn(d_line, shift = 3*RIGHT, lag_ratio = 0.1), 583 | run_time = 2 584 | ) 585 | self.wait() 586 | 587 | self.play( 588 | LaggedStartMap(FadeIn, VGroup(d_par_line, d_dot), shift = 3*RIGHT, lag_ratio = 0.35), 589 | run_time = 3 590 | ) 591 | self.play(Create(graph), run_time = 2.5) 592 | self.play( 593 | Create(graph_tex), 594 | FadeIn(d_graph_dec, shift = DOWN) 595 | ) 596 | self.add(graph_ref) 597 | self.bring_to_front(graph) 598 | self.wait() 599 | 600 | # d bigger than 0 601 | self.play(d_val.animate.set_value(3), run_time = 4) 602 | self.play( 603 | Create(brace_up), 604 | Write(brace_text_up) 605 | ) 606 | self.wait() 607 | 608 | self.play(d_val.animate.set_value(0.5), rate_func = double_smooth, run_time = 3) 609 | self.wait() 610 | 611 | # d smaller than 0 612 | self.play(d_val.animate.set_value(-3), run_time = 3) 613 | self.play( 614 | Create(brace_down), 615 | Write(brace_text_down) 616 | ) 617 | self.wait() 618 | 619 | self.play(d_val.animate.set_value(+3), rate_func = linear, run_time = 9) 620 | self.play(d_val.animate.set_value(-3), rate_func = linear, run_time = 9) 621 | self.wait(3) 622 | 623 | 624 | # functions 625 | def get_x_axis_ticks(self, numbers, tick_length = 0.2): 626 | ticks = VGroup() 627 | for num in numbers: 628 | tick = Line(UP, DOWN)\ 629 | .set_length(tick_length)\ 630 | .move_to(self.axes.c2p(num, 0)) 631 | ticks.add(tick) 632 | return ticks 633 | 634 | def get_x_axis_numbers(self, **kwargs): 635 | numbers = [PI/2, PI, 3*PI/2, TAU] 636 | strings = ["\\pi/2", "\\pi", "3\\pi/2", "2\\pi"] 637 | 638 | axis_numbers = VGroup() 639 | for num, string in zip(numbers, strings): 640 | tex = MathTex(string, color = GREY, **kwargs) 641 | tex.next_to(self.axes.c2p(num, 0), DOWN) 642 | axis_numbers.add(tex) 643 | return axis_numbers 644 | 645 | def get_y_axis_ticks(self, start, end, tick_length = 0.2): 646 | ticks = VGroup() 647 | for y in range(start, end + 1): 648 | tick = Line(LEFT, RIGHT)\ 649 | .set_length(tick_length)\ 650 | .move_to(self.axes.c2p(0, y)) 651 | ticks.add(tick) 652 | return ticks 653 | 654 | def get_y_axis_numbers(self, start, end, **kwargs): 655 | axis_numbers = VGroup() 656 | for y in range(start, end + 1): 657 | num = MathTex(str(y), color = GREY, **kwargs) 658 | num.next_to(self.axes.c2p(0, y), LEFT) 659 | axis_numbers.add(num) 660 | return axis_numbers 661 | 662 | def get_d_line(self, x_min, x_max, x_step, line_length, **kwargs): 663 | d_line = NumberLine( 664 | x_range = [x_min, x_max, x_step], length = line_length, rotation = PI/2, color = WHITE, 665 | include_numbers = True, label_direction = LEFT, decimal_number_config = {"num_decimal_places": 0, "color": GREY}, font_size = 30, 666 | **kwargs 667 | ) 668 | d_line.shift(2*LEFT) 669 | return d_line 670 | 671 | def get_d_dot(self, **kwargs): 672 | d_line, d_val = self.d_line, self.d_val 673 | d_dot = Dot( 674 | point = d_line.n2p(d_val.get_value()), 675 | color = p2c(d_val.get_value(), -3, 3, self.colors), 676 | **kwargs 677 | ) 678 | d_dot.set_sheen(-0.3, DR) 679 | d_dot.set_stroke(width = 1, color = WHITE) 680 | 681 | return d_dot 682 | 683 | def get_dot_to_axes_line(self): 684 | line = Line( 685 | self.d_dot.get_center(), 686 | self.axes.c2p(0, self.d_val.get_value()), 687 | color = p2c(self.d_val.get_value(), -3, 3, self.colors) 688 | ) 689 | line.set_stroke(opacity = [0,1,0]) 690 | return line 691 | 692 | 693 | 694 | 695 | 696 | class Thumbnail(Scene): 697 | def construct(self): 698 | x_min, x_max = -3*PI, 3*PI 699 | axes = Axes(x_range = [x_min, x_max]) 700 | 701 | sin_graph = axes.get_graph(lambda x: np.sin(x), x_range = [x_min, x_max], stroke_width = 8)\ 702 | .set_color([RED, RED_E, RED]) 703 | sind_graph = axes.get_graph(lambda x: np.sin(x) + 3, x_range = [x_min, x_max], stroke_width = 8)\ 704 | .set_color([BLUE, BLUE_E, BLUE]) 705 | 706 | dots_sin, dots_sind = VGroup(), VGroup() 707 | for x in np.linspace(0, 1, 21): 708 | dot_sin = Dot(point = sin_graph.point_from_proportion(x), color = sin_graph.get_color(), radius = 0.1) 709 | dot_sind = Dot(point = sind_graph.point_from_proportion(x), color = sind_graph.get_color(), radius = 0.1) 710 | 711 | dot_sin.set_stroke(width = 1, color = BLACK).set_sheen(-0.3, DR) 712 | dot_sind.set_stroke(width = 1, color = BLACK).set_sheen(-0.3, DR) 713 | 714 | dots_sin.add(dot_sin) 715 | dots_sind.add(dot_sind) 716 | 717 | 718 | arrows = VGroup(*[ 719 | Line(start.get_center(), end.get_center(), buff = 0.1).set_color([RED, BLUE]) 720 | for start, end in zip(dots_sin, dots_sind) 721 | ]) 722 | for line in arrows: 723 | line.add_tip(tip_length = 0.2) # adding a tip 724 | line[1].set_color(BLUE) # color the tip 725 | 726 | 727 | eq = MathTex("\\sin", "(", "x", ")", "+", "d", font_size = 160)\ 728 | .to_edge(DOWN, buff = 1) 729 | eq[0].set_color(RED) 730 | eq[1:4].set_color(LIGHT_GREY) 731 | eq[4:].set_color(BLUE) 732 | 733 | 734 | self.add(sin_graph, sind_graph, dots_sin, dots_sind, arrows, eq) 735 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # manim-projects 2 | 3 | This project contains the code used to generate the videos found on [my youtube channel!](https://www.youtube.com/c/VisualXAnimation) 4 | 5 | Videos are generated using the library Manim. 6 | 7 | Since june 2021 i'm using the community version of Manim, also called Manim CE. Check out their [official documentation!](https://docs.manim.community/en/latest/#). 8 | --------------------------------------------------------------------------------