animations for listening to pixels explanation

This commit is contained in:
Grant Sanderson 2015-12-21 12:46:33 -08:00
parent f21f6619a5
commit 5848f03249

View file

@ -1,26 +1,46 @@
from mobject import Mobject, Point
from mobject.tex_mobject import TexMobject, TextMobject, Brace
from mobject.image_mobject import ImageMobject
from mobject.tex_mobject import \
TexMobject, TextMobject, Brace
from mobject.image_mobject import \
ImageMobject, MobjectFromRegion
from scene import Scene
from animation import Animation
from animation.transform import Transform, CounterclockwiseTransform, \
ApplyMethod, GrowFromCenter
from animation.simple_animations import ShowCreation, ShimmerIn
from animation.meta_animations import DelayByOrder, TransformAnimations
from animation.playground import VibratingString
from animation.transform import \
Transform, CounterclockwiseTransform, ApplyMethod,\
GrowFromCenter, ClockwiseTransform
from animation.simple_animations import \
ShowCreation, ShimmerIn, FadeOut, FadeIn
from animation.meta_animations import \
DelayByOrder, TransformAnimations
from animation.playground import Vibrate
from topics.geometry import Line, Dot, Arrow
from topics.geometry import \
Line, Dot, Arrow, Grid, Square, Point
from topics.characters import ThoughtBubble
from topics.number_line import UnitInterval
from topics.three_dimensions import Stars
from region import region_from_polygon_vertices
import displayer as disp
from hilbert.curves import \
TransformOverIncreasingOrders, FlowSnake
from helpers import *
from hilbert.curves import TransformOverIncreasingOrders, FlowSnake
def get_grid():
return Grid(64, 64)
def get_freq_line():
return UnitInterval().shift(2*DOWN) ##Change?
class AboutSpaceFillingCurves(TransformOverIncreasingOrders):
@staticmethod
def args_to_string():
@ -131,7 +151,7 @@ class WriteSomeSoftware(Scene):
class ImageToSound(Scene):
def construct(self):
string = VibratingString(color = BLUE_D, run_time = 5)
string = Vibrate(color = BLUE_D, run_time = 5)
picture = ImageMobject("lion", invert = False)
picture.scale(0.8)
picture_copy = picture.copy()
@ -181,11 +201,11 @@ class SoundDataIsOneDimensional(Scene):
def construct(self):
overtones = 5
floor = 2*DOWN
main_string = VibratingString(color = BLUE_D)
main_string = Vibrate(color = BLUE_D)
component_strings = [
VibratingString(
Vibrate(
num_periods = k+1,
overtones = 2,
overtones = 1,
color = color,
center = 2*DOWN + UP*k
)
@ -202,7 +222,7 @@ class SoundDataIsOneDimensional(Scene):
for string in component_strings
]
freq_line = UnitInterval()
freq_line = get_freq_line()
freq_line.shift(floor)
freq_line.sort_points(np.linalg.norm)
brace = Brace(freq_line, UP)
@ -242,7 +262,243 @@ class SoundDataIsOneDimensional(Scene):
)
self.dither(0.5)
class GridOfPixels(Scene):
def construct(self):
low_res = ImageMobject("low_resolution_lion", invert = False)
high_res = ImageMobject("Lion", invert = False)
grid = get_grid()
for mob in low_res, high_res:
mob.replace(grid, stretch = True)
for mob in low_res, high_res, grid:
mob.sort_points(np.linalg.norm)
side_brace = Brace(grid, LEFT)
top_brace = Brace(grid, UP)
top_words = TextMobject("256 Px", size = "\\normal")
side_words = top_words.copy().rotate(np.pi/2)
top_words.next_to(top_brace, UP)
side_words.next_to(side_brace, LEFT)
self.add(high_res)
self.dither()
self.play(DelayByOrder(Transform(high_res, low_res)))
self.dither()
self.play(DelayByOrder(Transform(high_res, grid)))
self.clear()
self.add(grid)
self.play(
GrowFromCenter(top_brace),
GrowFromCenter(side_brace),
ShimmerIn(top_words),
ShimmerIn(side_words)
)
self.dither()
class ShowFrequencySpace(Scene):
def construct(self):
freq_line = get_freq_line()
self.add(freq_line)
self.dither()
for tex, vect in zip(["20 Hz", "20{,}000 Hz"], [LEFT, RIGHT]):
tex_mob = TextMobject(tex)
tex_mob.to_edge(vect)
tex_mob.shift(UP)
arrow = Arrow(tex_mob, freq_line.get_edge_center(vect))
self.play(
ShimmerIn(tex_mob),
ShowCreation(arrow)
)
self.dither()
class AssociatePixelWithFrequency(Scene):
def construct(self):
big_grid_dim = 20.
small_grid_dim = 6.
big_grid = Grid(64, 64, height = big_grid_dim, width = big_grid_dim)
big_grid.to_corner(UP+RIGHT, buff = 2)
small_grid = big_grid.copy()
small_grid.scale(small_grid_dim/big_grid_dim)
small_grid.center()
pixel = MobjectFromRegion(
region_from_polygon_vertices(*0.2*np.array([
RIGHT+DOWN,
RIGHT+UP,
LEFT+UP,
LEFT+DOWN
]))
)
pixel.set_color(WHITE)
pixel_width = big_grid.width/big_grid.columns
pixel.scale_to_fit_width(pixel_width)
pixel.to_corner(UP+RIGHT, buff = 2)
pixel.shift(5*pixel_width*(2*LEFT+DOWN))
freq_line = get_freq_line()
dot = Dot()
dot.shift(freq_line.get_center() + 2*RIGHT)
string = Line(LEFT, RIGHT, color = GREEN)
arrow = Arrow(
dot, string.get_center(),
color = YELLOW_C
)
vibration_config = {
"overtones" : 1,
"spatial_period" : 2,
}
vibration, loud_vibration, quiet_vibration = [
Vibrate(string.copy(), amplitude = a, **vibration_config)
for a in [0.5, 1., 0.25]
]
self.add(small_grid)
self.dither()
self.play(
Transform(small_grid, big_grid)
)
self.play(FadeIn(pixel))
self.dither()
self.play(
FadeOut(small_grid),
ShowCreation(freq_line)
)
self.remove(small_grid)
self.play(
Transform(pixel, dot),
)
self.dither()
self.play(ShowCreation(arrow))
self.play(loud_vibration)
self.play(
TransformAnimations(loud_vibration, quiet_vibration),
ApplyMethod(dot.fade, 0.1)
)
self.clear()
self.add(freq_line, dot, arrow)
self.play(quiet_vibration)
class ListenToAllPixels(Scene):
def construct(self):
grid = get_grid()
grid.sort_points(np.linalg.norm)
freq_line = get_freq_line()
freq_line.sort_points(lambda p : p[0])
red, blue = Color(RED), Color(BLUE)
freq_line.gradient_highlight(red, blue)
colors = [
Color(rgb = interpolate(
np.array(red.rgb),
np.array(blue.rgb),
alpha
))
for alpha in np.arange(4)/3.
]
string = Line(3*LEFT, 3*RIGHT, color = colors[1])
vibration = Vibrate(string)
vibration_copy = vibration.copy()
vibration_copy.mobject.point_thickness = 1
sub_vibrations = [
Vibrate(
string.copy().shift((n-1)*UP).highlight(colors[n]),
overtones = 1,
spatial_period = 6./(n+1),
temporal_period = 1./(n+1),
amplitude = 0.5/(n+1)
)
for n in range(4)
]
words = TexMobject("&\\vdots \\\\ \\text{thousands }& \\text{of frequencies} \\\\ &\\vdots")
words.to_edge(UP, buff = 0.1)
self.add(grid)
self.dither()
self.play(DelayByOrder(ApplyMethod(
grid.gradient_highlight, red, blue
)))
self.play(Transform(grid, freq_line))
self.dither()
self.play(
ShimmerIn(
words,
alpha_func = squish_alpha_func(smooth, 0, 0.2)
),
*sub_vibrations,
run_time = 5
)
self.play(
*[
TransformAnimations(
sub_vib, vibration
)
for sub_vib in sub_vibrations
]+[FadeOut(words)]
)
self.clear()
self.add(freq_line)
self.play(vibration)
class LayAsideSpeculation(Scene):
def construct(self):
words = TextMobject("Would this actually work?")
grid = get_grid()
grid.scale_to_fit_width(6)
grid.to_edge(LEFT)
freq_line = get_freq_line()
freq_line.scale_to_fit_width(6)
freq_line.center().to_edge(RIGHT)
mapping = Mobject(
grid, freq_line, Arrow(grid, freq_line)
)
mapping.ingest_sub_mobjects()
lower_left = Point().to_corner(DOWN+LEFT, buff = 0)
lower_right = Point().to_corner(DOWN+RIGHT, buff = 0)
self.add(words)
self.dither()
self.play(
Transform(words, lower_right),
Transform(lower_left, mapping)
)
self.dither()
class RandomMapping(Scene):
def construct(self):
grid = get_grid()
grid.scale_to_fit_width(6)
grid.to_edge(LEFT)
freq_line = get_freq_line()
freq_line.scale_to_fit_width(6)
freq_line.center().to_edge(RIGHT)
# for mob in grid, freq_line:
# indices = np.arange(mob.get_num_points())
# random.shuffle(indices)
# mob.points = mob.points[indices]
stars = Stars(point_thickness = grid.point_thickness)
self.add(grid)
targets = [stars, freq_line]
alphas = [not_quite_there(rush_into), rush_from]
for target, alpha_func in zip(targets, alphas):
self.play(Transform(
grid, target,
run_time = 3,
alpha_func = alpha_func,
interpolation_function = path_along_arc(-np.pi/2)
))
self.dither()
class LeverageExistingIntuitions(Scene):
def construct(self):
self.add(TextMobject("Leverage existing intuitions"))
self.dither()