Spaces:
Running on Zero
Running on Zero
File size: 5,626 Bytes
2dd1cd7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | import numpy as np
SPEAKER_COLORS = [
"#76B900", # Green
"#49A4DE", # Blue
"#E06C75", # Red
"#C678DD", # Purple
"#E5A84B", # Orange
"#36CFC9", # Cyan
"#FF7AB2", # Pink
"#F5F5F5", # White
]
def array_to_gradient_html(arr=None, num_frames=125, num_of_speakers=4, partitions=None):
"""
Convert num_of_speakers by num_frames numpy array to HTML gradient boxes.
Parameters:
-----------
arr : numpy.ndarray, optional
num_of_speakers by num_frames array with values from 0.0 to 1.0
Shape: (num_of_speakers, num_frames)
If None, creates a default random array
num_frames : int, default 125
Number of frames/columns (only used if arr is None)
num_of_speakers : int, default 4
Number of speakers/rows (only used if arr is None)
partitions : list of dict, optional
Named activity arrays rendered as proportional sections. Each dictionary contains
``name``, ``values``, ``capacity``, and optionally ``valid_frames``.
Returns:
--------
str : HTML string with colored gradient boxes
Example:
--------
>>> arr = np.array([[0.0, 0.25, 0.5, 0.75, 1.0]]) # 1 speaker, 5 frames
>>> html = array_to_gradient_html(arr)
>>> print(html)
"""
# Color map for different speakers (black background to full color)
# Matching the app.py color scheme for dark theme
color_map = {
speaker_idx: tuple(int(color[offset : offset + 2], 16) for offset in (1, 3, 5))
for speaker_idx, color in enumerate(SPEAKER_COLORS)
}
def value_to_color(value, speaker_idx):
"""
Convert a value from 0.0 to 1.0 to a color gradient for a specific speaker.
0.0 -> #000000 (black background)
1.0 -> speaker's color (green, blue, gray, or red)
"""
# Clamp value between 0 and 1
value = max(0.0, min(1.0, value))
# Get speaker's target color (cycle through colors if more speakers than colors)
speaker_color = color_map.get(speaker_idx % len(color_map), (0, 0, 0))
target_r, target_g, target_b = speaker_color
# Gradient from black (0, 0, 0) to speaker's color
# Linear interpolation between black and target color
r = int(target_r * value)
g = int(target_g * value)
b = int(target_b * value)
return f"#{r:02X}{g:02X}{b:02X}"
if partitions is None:
if arr is None:
arr = np.random.rand(num_of_speakers, num_frames)
partitions = [{"name": "DIARIZATION", "values": arr, "capacity": num_frames}]
prepared_partitions = []
for partition in partitions:
capacity = max(1, int(partition["capacity"]))
values = partition.get("values")
if values is None:
values = np.zeros((num_of_speakers, 0), dtype=np.float32)
values = np.asarray(values)
if values.ndim != 2:
raise ValueError(f"Expected a 2-D speaker activity array, but received shape {values.shape}")
if values.shape[0] < num_of_speakers:
values = np.pad(values, ((0, num_of_speakers - values.shape[0]), (0, 0)), mode='constant')
else:
values = values[:num_of_speakers]
if values.shape[1] < capacity:
values = np.pad(values, ((0, 0), (capacity - values.shape[1], 0)), mode='constant')
else:
values = values[:, -capacity:]
prepared_partitions.append(
{
"name": partition["name"],
"values": values,
"capacity": capacity,
"valid_frames": min(int(partition.get("valid_frames", values.shape[1])), capacity),
}
)
column_weights = " ".join(f"{partition['capacity']}fr" for partition in prepared_partitions)
html = '<div class="diar-partition-labels">'
for partition in prepared_partitions:
html += (
f'<span class="diar-partition-label">{partition["name"]} '
f'{partition["valid_frames"]}/{partition["capacity"]}</span>'
)
html += '</div>'
html += '<div class="diar-map">'
for speaker_idx in range(num_of_speakers):
html += (
f'<div class="diar-row" style="grid-template-columns:{column_weights};" '
f'title="Speaker {speaker_idx + 1}">'
)
for partition in prepared_partitions:
html += (
f'<div class="diar-partition" title="{partition["name"]}" '
f'style="grid-template-columns:repeat({partition["capacity"]}, minmax(0, 1fr));">'
)
for val in partition["values"][speaker_idx]:
color = value_to_color(val, speaker_idx)
html += f'<span class="diar-cell" style="background-color:{color};"></span>'
html += '</div>'
html += '</div>'
html += '</div>'
return html
if __name__ == "__main__":
# Example 3: Default parameters
print("Example 3: Using default parameters (4 speakers x 125 frames)")
html3 = array_to_gradient_html()
# print(html3[:500] + "...") # Print first 500 chars
print(html3)
print(f"\nTotal HTML length: {len(html3)} characters")
# Example 4: Show the 20-step gradient like in the original example
# print("\n" + "="*50 + "\n")
# print("Example 4: 20-step gradient (like the original) - 1 speaker x 20 frames")
# gradient_arr = np.linspace(0, 1, 20).reshape(1, 20) # Shape: (1, 20)
# html4 = array_to_gradient_html(gradient_arr)
# print(html4)
|