Загрузка данных
import numpy as np
import matplotlib.pyplot as plt
def generate_signals_and_plots():
# 1. Основные параметры дискретизации
fs = 1000 # Частота дискретизации (Гц)
duration = 2.0 # Длительность сигнала (в секундах)
t = np.arange(0, duration, 1/fs)
# Частоты сигналов по заданию (Гц)
frequencies = [1, 2, 4, 8]
# Создаем сетку графиков: 4 строки (по частотам), 4 колонки (сигнал и спектр)
fig, axes = plt.subplots(4, 4, figsize=(16, 11))
fig.suptitle("Лабораторная работа №1: Спектры сигналов (Исправленная версия)", fontsize=16, fontweight='bold')
for i, f in enumerate(frequencies):
# --- ГЕНЕРАЦИЯ СИГНАЛОВ ---
# Гармонический сигнал (синусоида) с амплитудой 1.0
sin_signal = np.sin(2 * np.pi * f * t)
# Цифровой сигнал (однополярный меандр: принимает значения 0 или 1)
# Сначала получаем значения -1 и 1, затем сдвигаем и нормируем в диапазон [0, 1]
square_signal = (np.sign(np.sin(2 * np.pi * f * t)) + 1) / 2
# Убираем возможные артефакты функции np.sign в точках перехода через ноль
square_signal = np.where(square_signal >= 0.5, 1.0, 0.0)
# --- РАСЧЕТ СПЕКТРОВ (БПФ / FFT) ---
n = len(t)
# Формируем ось частот для положительной половины спектра
freq_axis = np.fft.fftfreq(n, 1/fs)[:n//2]
# Спектр синусоиды: берем модуль БПФ, делим на n и умножаем на 2 (для одностороннего спектра)
sin_fft = np.abs(np.fft.fft(sin_signal))[:n//2] * 2 / n
# Спектр меандра: корректный расчет одностороннего спектра с постоянной составляющей
square_fft_raw = np.abs(np.fft.fft(square_signal))[:n//2] / n
# Умножаем на 2 амплитуды всех частот, КРОМЕ постоянной составляющей (индекс 0)
square_fft_raw[1:] = square_fft_raw[1:] * 2
square_fft = square_fft_raw
# --- ВИЗУАЛИЗАЦИЯ (СТРОКА i) ---
# Для временных графиков отображаем только первую секунду, чтобы сигналы не сливались
time_limit = t <= 1.0
# Колонка 0: График синусоиды
axes[i, 0].plot(t[time_limit], sin_signal[time_limit], color='blue')
axes[i, 0].set_title(f"Синусоида {f} Гц")
axes[i, 0].grid(True)
axes[i, 0].set_ylabel("Амплитуда")
axes[i, 0].set_ylim(-1.2, 1.2)
# Колонка 1: Спектр синусоиды (ограничиваем ось X до 15 Гц)
axes[i, 1].stem(freq_axis, sin_fft, linefmt='blue', markerfmt='bo', basefmt=' ')
axes[i, 1].set_xlim(-0.5, 15)
axes[i, 1].set_title(f"Спектр синусоиды {f} Гц")
axes[i, 1].grid(True)
axes[i, 1].set_ylim(-0.05, 1.1)
# Колонка 2: График меандра
axes[i, 2].plot(t[time_limit], square_signal[time_limit], color='green')
axes[i, 2].set_title(f"Меандр {f} Гц")
axes[i, 2].grid(True)
axes[i, 2].set_ylim(-0.2, 1.2)
# Колонка 3: Спектр меандра (ограничиваем ось X до 40 Гц, чтобы видеть гармоники)
axes[i, 3].stem(freq_axis, square_fft, linefmt='green', markerfmt='go', basefmt=' ')
axes[i, 3].set_xlim(-1.0, 40)
axes[i, 3].set_title(f"Спектр меандра {f} Гц")
axes[i, 3].grid(True)
axes[i, 3].set_ylim(-0.05, 0.7)
# Красиво распределяем графики в окне
plt.tight_layout()
# Автоматическое сохранение новой картинки для архива лабораторной работы
plt.savefig("signals_and_spectra_fixed.png", dpi=300)
print("Исправленный график сохранен под именем 'signals_and_spectra_fixed.png'")
# Вывод графиков на экран
plt.show()
if __name__ == "__main__":
generate_signals_and_plots()