Загрузка данных


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()