Skip to content

Instantly share code, notes, and snippets.

@asalt
Created March 24, 2025 14:08
Show Gist options
  • Select an option

  • Save asalt/1e5c78b976d0e001a9c656e939003291 to your computer and use it in GitHub Desktop.

Select an option

Save asalt/1e5c78b976d0e001a9c656e939003291 to your computer and use it in GitHub Desktop.
import numpy as np
import matplotlib.pyplot as plt
import argparse
import os
def generate_vectors(num_slots, num_values, spacing, variance, diff_variance, diff_positions, diff_weight=1, aligned=True):
"""Generate two vectors with specified characteristics."""
if spacing == "even":
positions = np.linspace(0, num_slots - 1, num_values, dtype=int)
else:
positions = np.random.choice(np.linspace(0, num_slots-1, dtype=int), num_values)
Va = np.zeros(num_slots)
Vb = np.zeros(num_slots)
values = np.random.uniform(1 - variance, 1 + variance, num_values)
Va[positions] = values
if aligned:
Vb[positions] = values # Start with identical values
else:
shifted_positions = np.random.choice(np.linspace(0, num_slots-1, dtype=int), num_values)
shifted_positions = np.clip(shifted_positions, 0, num_slots - 1)
print(positions, shifted_positions)
Vb[shifted_positions] = values # Start with identical values
if diff_positions:
for pos in diff_positions:
Vb[pos] = np.random.uniform(1 - diff_variance, 1 + diff_variance)* np.random.uniform(.25, .75) * diff_weight # Add differing elements
return Va, Vb
def spectral_angle(Va, Vb):
"""Compute the spectral angle similarity measure."""
dot_product = np.dot(Va, Vb)
norm_a = np.linalg.norm(Va)
norm_b = np.linalg.norm(Vb)
cos_theta = dot_product / (norm_a * norm_b)
theta = np.arccos(np.clip(cos_theta, -1.0, 1.0))
return 1 - 2 * (theta / np.pi)
def plot_vectors_orig(Va, Vb, title, save_path=None):
"""Plot side-by-side bar graphs for two vectors and optionally save the plot."""
num_slots = len(Va)
fig, axes = plt.subplots(1, 2, figsize=(12, 5), sharex=True, sharey=True)
axes[0].bar(range(num_slots), Va, color='blue', alpha=0.7)
axes[1].bar(range(num_slots), Vb, color='red', alpha=0.7)
axes[0].set_title("Va")
axes[1].set_title("Vb")
plt.suptitle(f"{title} | Spectral Angle: {spectral_angle(Va, Vb):.4f}")
if save_path:
# os.makedirs(os.path.dirname(save_path), exist_ok=True)
plt.savefig(save_path)
print(f"Plot saved to {save_path}")
plt.close(fig)
else:
plt.show()
def plot_vectors(Va, Vb, title, save_path=None):
"""Plot side-by-side bar graphs for two vectors and optionally save the plot."""
num_slots = max(len(Va), len(Vb)) # Ensure the x-axis covers both vectors
# Extend Va with NaNs if necessary
Va_extended = np.pad(Va, (0, num_slots - len(Va)), constant_values=np.nan)
Vb_extended = np.pad(Vb, (0, num_slots - len(Vb)), constant_values=np.nan)
fig, axes = plt.subplots(1, 2, figsize=(12, 5), sharex=True, sharey=True)
axes[0].bar(range(len(Va)), Va, color='blue', alpha=0.7)
# Set colors for Vb: red if Va has a value, gray otherwise
colors = ['red' if Va_extended[i] > 0 else 'gray' for i in range(len(Vb))]
axes[1].bar(range(len(Vb)), Vb, color=colors, alpha=0.7)
axes[0].set_title("Va")
axes[1].set_title("Vb")
plt.suptitle(f"{title} | Spectral Angle: {spectral_angle(Va, Vb):.4f}")
# savename = f""
if save_path:
plt.savefig(save_path)
print(f"Plot saved to {save_path}")
plt.close(fig)
else:
plt.show()
def main():
parser = argparse.ArgumentParser(description="Generate and visualize spectral angle comparisons between two vectors.")
parser.add_argument("--not-aligned", default=False, help="", action='store_true')
parser.add_argument("--num-slots", type=int, default=100, help="Length of the vectors (default: 100)")
parser.add_argument("--num-values", type=int, default=5, help="Number of nonzero values (default: 5)")
parser.add_argument("--spacing", type=str, default="even", choices=["even", "random"], help="Spacing of nonzero values (default: even)")
parser.add_argument("--variance", type=float, default=0.5, help="Variance in nonzero values (default: 0.5)")
parser.add_argument("--diff-variance", type=float, default=0.5, help="Variance in nonzero values (default: 0.5)")
parser.add_argument("--diff-weight", type=float, default=1, help="diff weigth")
parser.add_argument("--diff-positions", type=int, nargs='*', default=None, help="Positions to add different values in Vb (default: None)")
parser.add_argument("--save_path", type=str, default=None, help="Path to save the plot (default: None)")
args = parser.parse_args()
print(args.not_aligned)
Va, Vb = generate_vectors(args.num_slots, args.num_values, args.spacing, args.variance, args.diff_variance, args.diff_positions, args.diff_weight, aligned=not args.not_aligned)
plot_vectors(Va, Vb, "Spectral Angle Demonstration", args.save_path)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment