import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

# -------------------------------
# Simulation Parameters
# -------------------------------
num_strands = 8
slots_per_strand = 4
total_slots = num_strands * slots_per_strand

# Initialize lattice analogs (D1-D32)
lattice = np.random.uniform(0.5, 1.5, (num_strands, slots_per_strand))
r_dim = np.linspace(0.3, 1.0, num_strands)
slot_scale = np.array([1.0, 1.05, 1.1, 1.2])

# Phase offsets for each slot (cross-strand modulation)
phases = np.random.uniform(0, 2*np.pi, (num_strands, slots_per_strand))

# Sampling
fs = 2000
duration = 0.05
t = np.linspace(0, duration, int(fs*duration))

# Composite output waveform
fig, ax = plt.subplots(figsize=(12,6))
line_output, = ax.plot([], [], lw=2, color='cyan')
ax.set_xlim(0, duration)
ax.set_ylim(-5, 5)
ax.set_title("HDGL Lattice Analog Signal Modulation")
ax.set_xlabel("Time (s)")
ax.set_ylabel("Amplitude")

# -------------------------------
# Update function
# -------------------------------
def update(frame):
    global lattice, phases

    # Step lattice analogs with cross-strand resonance
    lattice_new = np.copy(lattice)
    for s in range(num_strands):
        for i in range(slots_per_strand):
            # base increment
            lattice_new[s,i] += 0.02 * r_dim[s] * slot_scale[i]
            # resonance with all other slots
            resonance = np.mean(lattice[np.arange(num_strands)!=s,i])
            lattice_new[s,i] += 0.01 * resonance

            # phase drift proportional to slot analog
            phases[s,i] += 0.05 * lattice[s,i]

    lattice[:] = lattice_new

    # Generate composite waveform
    waveform = np.zeros_like(t)
    for s in range(num_strands):
        for i in range(slots_per_strand):
            freq = 50 + 50*lattice[s,i]          # frequency modulated
            amp  = 0.3 + 0.7*lattice[s,i]/np.max(lattice)  # amplitude
            waveform += amp * np.sin(2*np.pi*freq*t + phases[s,i])

    line_output.set_data(t, waveform)
    return [line_output]

# -------------------------------
# Run animation
# -------------------------------
ani = animation.FuncAnimation(fig, update, frames=500, blit=True, interval=30)
plt.show()
