import numpy as npimport matplotlib.pyplot as pltfrom matplotlib.widgets import Slider
A = 1.0 T = 1.0 initial_duty = 0.5 initial_slew = 0.05 n_max = 80
fig = plt.figure(figsize=(10, 8))ax1 = fig.add_subplot(211) ax2 = fig.add_subplot(212) plt.subplots_adjust(bottom=0.3, hspace=0.5)
n = np.arange(-n_max, n_max+1)f = n / Tc_initial = A * initial_duty * np.sinc(n * initial_duty)
spect_container = ax1.stem(f, 20*np.log10(np.abs(c_initial) + 1e-12), linefmt='b-', markerfmt='bo', basefmt=' ')
ax1.set(xlim=(-80,80), ylim=(-80, 6), xlabel='Frequency (Hz)', ylabel='Amplitude (dB)', title=f'Spectrum with Duty={initial_duty:.2f}, Slew={initial_slew:.2f}')ax1.grid(linestyle=':', alpha=0.6)
stemlines = spect_container.stemlinesmarkers = spect_container.markerline
t = np.linspace(-2*T, 2*T, 2000)
def generate_wave(t, duty, slew_rate): """生成带可调斜边的梯形波""" phase = (t % T)/T rise_time = slew_rate fall_time = slew_rate on_time = duty - (rise_time + fall_time) on_time = max(on_time, 0)
rise_end = rise_time plateau_end = rise_end + on_time fall_end = plateau_end + fall_time
wave = np.zeros_like(phase) mask = phase < rise_end wave[mask] = phase[mask]/rise_time mask = (phase >= rise_end) & (phase < plateau_end) wave[mask] = 1.0 mask = (phase >= plateau_end) & (phase < fall_end) wave[mask] = 1.0 - (phase[mask] - plateau_end)/fall_time return A * wave
wave_initial = generate_wave(t, initial_duty, initial_slew)wave_line, = ax2.plot(t, wave_initial, 'b-')ax2.set(xlim=(-2,2), ylim=(-0.1,1.1), xlabel='Time (s)', ylabel='Amplitude', title='Time Domain Waveform')ax2.grid(linestyle=':', alpha=0.6)
ax_duty = plt.axes([0.25, 0.2, 0.65, 0.03])duty_slider = Slider(ax_duty, 'Duty Cycle', 0.01, 1.0, valinit=initial_duty)
ax_slew = plt.axes([0.25, 0.15, 0.65, 0.03])slew_slider = Slider(ax_slew, 'Slew Rate', 0.0, 0.5, valinit=initial_slew)
def update(val): duty = duty_slider.val slew = slew_slider.val
new_wave = generate_wave(t, duty, slew) wave_line.set_ydata(new_wave)
N = 1024 t_fft = np.linspace(0, T, N, endpoint=False) wave_fft = generate_wave(t_fft, duty, slew)
c_new = [] for ni in n: k = ni integrand = wave_fft * np.exp(-1j*2*np.pi*k*t_fft/T) cn = np.trapz(integrand, t_fft) / T c_new.append(cn) c_new = np.array(c_new)
y_dB = 20*np.log10(np.abs(c_new) + 1e-12)
new_segments = [] for xi, yi in zip(f, y_dB): new_segments.append([(xi, -80), (xi, yi)]) stemlines.set_segments(new_segments)
markers.set_ydata(y_dB)
ax1.set_ylim(-80, 6) ax1.set_title(f'Spectrum with Duty={duty:.2f}, Slew={slew:.2f}') ax2.set_title(f'Time Domain (Duty={duty:.2f}, Slew={slew:.2f})')
fig.canvas.draw_idle()
duty_slider.on_changed(update)slew_slider.on_changed(update)
plt.show()