Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,7 +1,159 @@
|
|
| 1 |
import streamlit as st
|
| 2 |
import pandas as pd
|
| 3 |
import numpy as np
|
|
|
|
|
|
|
| 4 |
|
| 5 |
chart_data = pd.DataFrame(np.random.randn(20, 3), columns=["a", "b", "c"])
|
| 6 |
|
| 7 |
-
st.area_chart(chart_data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import streamlit as st
|
| 2 |
import pandas as pd
|
| 3 |
import numpy as np
|
| 4 |
+
import matplotlib.pyplot as plt
|
| 5 |
+
from PIL import Image
|
| 6 |
|
| 7 |
chart_data = pd.DataFrame(np.random.randn(20, 3), columns=["a", "b", "c"])
|
| 8 |
|
| 9 |
+
st.area_chart(chart_data)
|
| 10 |
+
|
| 11 |
+
class BubbleChart:
|
| 12 |
+
def __init__(self, data, bubble_spacing=0, n_bins=5):
|
| 13 |
+
|
| 14 |
+
unity_ids = list(data.keys())
|
| 15 |
+
share_values = list(data.values())
|
| 16 |
+
|
| 17 |
+
area = np.asarray(share_values)
|
| 18 |
+
r = np.sqrt(area / np.pi)
|
| 19 |
+
|
| 20 |
+
self.bubble_spacing = bubble_spacing
|
| 21 |
+
self.bubbles = np.ones((len(area), 4))
|
| 22 |
+
self.bubbles[:, 2] = r
|
| 23 |
+
self.bubbles[:, 3] = area
|
| 24 |
+
self.maxstep = 2 * self.bubbles[:, 2].max() + self.bubble_spacing
|
| 25 |
+
self.step_dist = self.maxstep / 2
|
| 26 |
+
|
| 27 |
+
length = np.ceil(np.sqrt(len(self.bubbles)))
|
| 28 |
+
grid = np.arange(length) * self.maxstep
|
| 29 |
+
gx, gy = np.meshgrid(grid, grid)
|
| 30 |
+
self.bubbles[:, 0] = gx.flatten()[:len(self.bubbles)]
|
| 31 |
+
self.bubbles[:, 1] = gy.flatten()[:len(self.bubbles)]
|
| 32 |
+
|
| 33 |
+
min_size = np.min(area)
|
| 34 |
+
max_size = np.max(area)
|
| 35 |
+
|
| 36 |
+
self.colors = self.quantize_colors(area, min_size, max_size, n_bins)
|
| 37 |
+
|
| 38 |
+
self.com = self.center_of_mass()
|
| 39 |
+
|
| 40 |
+
def quantize_colors(self, sizes, min_size, max_size, n_bins):
|
| 41 |
+
|
| 42 |
+
size_range = max_size - min_size
|
| 43 |
+
bin_size = size_range / n_bins
|
| 44 |
+
|
| 45 |
+
quantized_colors = []
|
| 46 |
+
for size in sizes:
|
| 47 |
+
bin_index = min(int((size - min_size) / bin_size), n_bins - 1)
|
| 48 |
+
quantized_colors.append(self.get_color_from_bin(bin_index, n_bins))
|
| 49 |
+
print(f"Size: {size}, Bin Index: {bin_index}, Color: {self.get_color_from_bin(bin_index, n_bins)}")
|
| 50 |
+
|
| 51 |
+
return quantized_colors
|
| 52 |
+
|
| 53 |
+
def get_color_from_bin(self, bin_index, n_bins):
|
| 54 |
+
# colors = ['#9a9fad', '#848dad', '#7080b5', '#5269b3', '#3654b5']
|
| 55 |
+
colors = ['#42c5ac', '#61d87d', '#a8eb86', '#d3f59a', '#f8ffaf']
|
| 56 |
+
return colors[bin_index]
|
| 57 |
+
|
| 58 |
+
def center_of_mass(self):
|
| 59 |
+
return np.average(
|
| 60 |
+
self.bubbles[:, :2], axis=0, weights=self.bubbles[:, 3]
|
| 61 |
+
)
|
| 62 |
+
|
| 63 |
+
def center_distance(self, bubble, bubbles):
|
| 64 |
+
return np.hypot(bubble[0] - bubbles[:, 0],
|
| 65 |
+
bubble[1] - bubbles[:, 1])
|
| 66 |
+
|
| 67 |
+
def outline_distance(self, bubble, bubbles):
|
| 68 |
+
center_distance = self.center_distance(bubble, bubbles)
|
| 69 |
+
return center_distance - bubble[2] - \
|
| 70 |
+
bubbles[:, 2] - self.bubble_spacing
|
| 71 |
+
|
| 72 |
+
def check_collisions(self, bubble, bubbles):
|
| 73 |
+
distance = self.outline_distance(bubble, bubbles)
|
| 74 |
+
return len(distance[distance < 0])
|
| 75 |
+
|
| 76 |
+
def collides_with(self, bubble, bubbles):
|
| 77 |
+
distance = self.outline_distance(bubble, bubbles)
|
| 78 |
+
idx_min = np.argmin(distance)
|
| 79 |
+
return idx_min if type(idx_min) == np.ndarray else [idx_min]
|
| 80 |
+
|
| 81 |
+
def collapse(self, n_iterations=50):
|
| 82 |
+
for _i in range(n_iterations):
|
| 83 |
+
moves = 0
|
| 84 |
+
for i in range(len(self.bubbles)):
|
| 85 |
+
rest_bub = np.delete(self.bubbles, i, 0)
|
| 86 |
+
|
| 87 |
+
dir_vec = self.com - self.bubbles[i, :2]
|
| 88 |
+
dir_vec = dir_vec / np.sqrt(dir_vec.dot(dir_vec))
|
| 89 |
+
|
| 90 |
+
new_point = self.bubbles[i, :2] + dir_vec * self.step_dist
|
| 91 |
+
new_bubble = np.append(new_point, self.bubbles[i, 2:4])
|
| 92 |
+
|
| 93 |
+
if not self.check_collisions(new_bubble, rest_bub):
|
| 94 |
+
self.bubbles[i, :] = new_bubble
|
| 95 |
+
self.com = self.center_of_mass()
|
| 96 |
+
moves += 1
|
| 97 |
+
else:
|
| 98 |
+
for colliding in self.collides_with(new_bubble, rest_bub):
|
| 99 |
+
dir_vec = rest_bub[colliding, :2] - self.bubbles[i, :2]
|
| 100 |
+
dir_vec = dir_vec / np.sqrt(dir_vec.dot(dir_vec))
|
| 101 |
+
orth = np.array([dir_vec[1], -dir_vec[0]])
|
| 102 |
+
new_point1 = (self.bubbles[i, :2] + orth *
|
| 103 |
+
self.step_dist)
|
| 104 |
+
new_point2 = (self.bubbles[i, :2] - orth *
|
| 105 |
+
self.step_dist)
|
| 106 |
+
dist1 = self.center_distance(
|
| 107 |
+
self.com, np.array([new_point1]))
|
| 108 |
+
dist2 = self.center_distance(
|
| 109 |
+
self.com, np.array([new_point2]))
|
| 110 |
+
new_point = new_point1 if dist1 < dist2 else new_point2
|
| 111 |
+
new_bubble = np.append(new_point, self.bubbles[i, 2:4])
|
| 112 |
+
if not self.check_collisions(new_bubble, rest_bub):
|
| 113 |
+
self.bubbles[i, :] = new_bubble
|
| 114 |
+
self.com = self.center_of_mass()
|
| 115 |
+
|
| 116 |
+
if moves / len(self.bubbles) < 0.1:
|
| 117 |
+
self.step_dist = self.step_dist / 2
|
| 118 |
+
|
| 119 |
+
def plot(self, ax, labels, alpha, edge_alpha = 1):
|
| 120 |
+
for i in range(len(self.bubbles)):
|
| 121 |
+
circ = plt.Circle(
|
| 122 |
+
self.bubbles[i, :2], self.bubbles[i, 2],
|
| 123 |
+
color=self.colors[i], alpha= alpha)
|
| 124 |
+
ax.add_patch(circ)
|
| 125 |
+
ax.text(*self.bubbles[i, :2], labels[i],
|
| 126 |
+
horizontalalignment='center', verticalalignment='center')
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
class GenerateChart:
|
| 130 |
+
def __init__(self, data, bubble_spacing=0, n_bins=5):
|
| 131 |
+
unity_ids = list(data.keys())
|
| 132 |
+
share_values = list(data.values())
|
| 133 |
+
|
| 134 |
+
simulation = BubbleChart(data, bubble_spacing=bubble_spacing, n_bins=n_bins)
|
| 135 |
+
|
| 136 |
+
simulation.collapse()
|
| 137 |
+
|
| 138 |
+
fig, ax = plt.subplots(subplot_kw=dict(aspect="equal"))
|
| 139 |
+
alpha_value = 1
|
| 140 |
+
simulation.plot(ax, unity_ids, alpha=alpha_value)
|
| 141 |
+
ax.axis("off")
|
| 142 |
+
ax.relim()
|
| 143 |
+
ax.autoscale_view()
|
| 144 |
+
ax.set_title('p2p share', color = "white")
|
| 145 |
+
|
| 146 |
+
fig = plt.gcf()
|
| 147 |
+
img = fig2img(fig)
|
| 148 |
+
st.image(image, caption='Bubble chart of gpu pool of each Users')
|
| 149 |
+
|
| 150 |
+
def fig2img(fig):
|
| 151 |
+
"""Convert a Matplotlib figure to a PIL Image and return it"""
|
| 152 |
+
import io
|
| 153 |
+
buf = io.BytesIO()
|
| 154 |
+
fig.savefig(buf)
|
| 155 |
+
buf.seek(0)
|
| 156 |
+
img = Image.open(buf)
|
| 157 |
+
return img
|
| 158 |
+
|
| 159 |
+
chart_generator = GenerateChart(data.get("gpus", {}), bubble_spacing=0.1, n_bins=5)
|