Used Black to reformat the code in the repository.

This commit is contained in:
Alec Helbling
2023-01-01 23:24:59 -05:00
parent 334662e8c8
commit 3d6e8072e1
71 changed files with 1701 additions and 1135 deletions

View File

@ -13,6 +13,7 @@ config.pixel_width = 1200
config.frame_height = 12.0
config.frame_width = 12.0
def make_moon_points(num_samples=100, noise=0.1, random_seed=1):
"""Make two half moon point shapes"""
# Make sure the points are normalized
@ -24,17 +25,19 @@ def make_moon_points(num_samples=100, noise=0.1, random_seed=1):
return X
def make_epsilon_balls(epsilon_value, points, axes, ball_color=RED, opacity=0.0):
"""Draws epsilon balls """
"""Draws epsilon balls"""
balls = []
for point in points:
ball = Circle(epsilon_value, color=ball_color, fill_opacity=opacity)
global_location = axes.coords_to_point(*point)
ball.move_to(global_location)
balls.append(ball)
return VGroup(*balls)
def make_epsilon_graph(epsilon_value, dots, points, edge_color=ORANGE):
"""Makes an epsilon nearest neighbor graph for the given dots"""
# First compute the adjacency matrix from the epsilon value and the points
@ -46,7 +49,7 @@ def make_epsilon_graph(epsilon_value, dots, points, edge_color=ORANGE):
dist = np.linalg.norm(dots[i].get_center() - dots[j].get_center())
is_connected = 1 if dist < epsilon_value else 0
adjacency_matrix[i, j] = is_connected
# Draw a graph based on the adjacency matrix
# Draw a graph based on the adjacency matrix
edges = []
for i in range(num_dots):
for j in range(i):
@ -56,28 +59,28 @@ def make_epsilon_graph(epsilon_value, dots, points, edge_color=ORANGE):
dot_a = dots[i]
dot_b = dots[j]
edge = Line(
dot_a.get_center(),
dot_b.get_center(),
dot_a.get_center(),
dot_b.get_center(),
color=edge_color,
stroke_width=3
stroke_width=3,
)
edges.append(edge)
return VGroup(*edges), adjacency_matrix
def perform_spectral_clustering(adjacency_matrix):
"""Performs spectral clustering given adjacency matrix"""
clustering = SpectralClustering(
n_clusters=2,
affinity="precomputed",
random_state=0
n_clusters=2, affinity="precomputed", random_state=0
).fit(adjacency_matrix)
labels = clustering.labels_
return labels
def make_color_change_animation(labels, dots, colors=[ORANGE, GREEN]):
"""Makes a color change animation """
"""Makes a color change animation"""
anims = []
for index in range(len(labels)):
@ -86,21 +89,30 @@ def make_color_change_animation(labels, dots, colors=[ORANGE, GREEN]):
anims.append(dot.animate.set_color(color))
return AnimationGroup(*anims, lag_ratio=0.0)
class EpsilonNearestNeighborScene(Scene):
def construct(self, num_points=200, dot_radius=0.1,
dot_color=BLUE, ball_color=WHITE, noise=0.1, ball_opacity=0.0,
random_seed=2):
class EpsilonNearestNeighborScene(Scene):
def construct(
self,
num_points=200,
dot_radius=0.1,
dot_color=BLUE,
ball_color=WHITE,
noise=0.1,
ball_opacity=0.0,
random_seed=2,
):
# Make moon shape points
# Note: dot is the drawing object and point is the math concept
moon_points = make_moon_points(num_samples=num_points, noise=noise, random_seed=random_seed)
moon_points = make_moon_points(
num_samples=num_points, noise=noise, random_seed=random_seed
)
# Make an axes
axes = Axes(
x_range=[-6, 6, 1],
y_range=[-6, 6, 1],
x_length=12,
y_length=12,
x_length=12,
y_length=12,
tips=False,
axis_config={"stroke_color": "#000000"},
)
@ -116,8 +128,10 @@ class EpsilonNearestNeighborScene(Scene):
dots = VGroup(*dots)
self.play(Create(dots))
# Draw epsilon bar with initial value
epsilon_bar = NumberLine([0, 2], length=8, stroke_width=2, include_ticks=False, include_numbers=False)
epsilon_bar.shift(4.5*DOWN)
epsilon_bar = NumberLine(
[0, 2], length=8, stroke_width=2, include_ticks=False, include_numbers=False
)
epsilon_bar.shift(4.5 * DOWN)
self.play(Create(epsilon_bar))
current_epsilon = ValueTracker(0.3)
epsilon_point = epsilon_bar.number_to_point(current_epsilon.get_value())
@ -128,7 +142,7 @@ class EpsilonNearestNeighborScene(Scene):
label_text = MathTex("\epsilon").scale(1.5)
# label_text = Text("Epsilon")
label_text.move_to(epsilon_bar.get_center())
label_text.shift(DOWN*0.5)
label_text.shift(DOWN * 0.5)
self.add(label_text)
# Make an updater for the dot
def dot_updater(epsilon_dot):
@ -139,12 +153,17 @@ class EpsilonNearestNeighborScene(Scene):
epsilon_dot.add_updater(dot_updater)
# Make the epsilon balls
epsilon_balls = make_epsilon_balls(
current_epsilon.get_value(), moon_points, axes, ball_color=ball_color, opacity=ball_opacity
current_epsilon.get_value(),
moon_points,
axes,
ball_color=ball_color,
opacity=ball_opacity,
)
# Set up updater for radius of balls
def epsilon_balls_updater(epsilon_balls):
for ball in epsilon_balls:
ball.set_width(current_epsilon.get_value())
# Turn epsilon up and down
epsilon_balls.add_updater(epsilon_balls_updater)
# Fade in the initial balls
@ -156,10 +175,7 @@ class EpsilonNearestNeighborScene(Scene):
epsilon_value = 0.9
# Show connecting graph
epsilon_graph, adjacency_matrix = make_epsilon_graph(
current_epsilon.get_value(),
dots,
moon_points,
edge_color=WHITE
current_epsilon.get_value(), dots, moon_points, edge_color=WHITE
)
self.play(FadeOut(epsilon_balls))
self.play(FadeIn(epsilon_graph))
@ -172,4 +188,4 @@ class EpsilonNearestNeighborScene(Scene):
self.play(color_change_animation)
# Fade out graph edges
self.play(FadeOut(epsilon_graph))
self.play(Wait(5.0))
self.play(Wait(5.0))