Untitled

 avatar
unknown
python
a year ago
11 kB
5
Indexable
import sys
import PyQt5.QtWidgets
import pyqtgraph as pg
import numpy as np
from scipy.io import wavfile
from scipy.fft import fft
import csv
    class SignalGenerator:
        def __init__(self, sampling_rate, duration):
            self.sampling_rate = sampling_rate
            self.duration = duration

        def generate_sine(self, frequency, amplitude):
            t = np.linspace(0, self.duration, int(self.sampling_rate * self.duration), endpoint=False)
            signal = amplitude * np.sin(2 * np.pi * frequency * t)
            return t, signal

        def generate_square(self, frequency, amplitude):
            t = np.linspace(0, self.duration, int(self.sampling_rate * self.duration), endpoint=False)
            signal = amplitude * np.sign(np.sin(2 * np.pi * frequency * t))
            return t, signal

        def generate_sawtooth(self, frequency, amplitude):
            t = np.linspace(0, self.duration, int(self.sampling_rate * self.duration), endpoint=False)
            signal = amplitude * (2 * (frequency * t - np.floor(0.5 + frequency * t)))
            return t, signal

        def generate_triangle(self, frequency, amplitude):
            t = np.linspace(0, self.duration, int(self.sampling_rate * self.duration), endpoint=False)
            signal = amplitude * np.abs((2 * (frequency * t - np.floor(0.5 + frequency * t))) - 1)
            return t, signal

        def generate_white_noise(self, amplitude):
            signal = amplitude * np.random.uniform(-1, 1, int(self.sampling_rate * self.duration))
            t = np.linspace(0, self.duration, int(self.sampling_rate * self.duration), endpoint=False)
            return t, signal

        def plot_fourier_transform(self, signal, title, plot_widget):
            N = len(signal)
            T = 1 / self.sampling_rate
            yf = fft(signal)
            xf = np.fft.fftfreq(N, T)[:N // 2]
            plot_widget.plot(xf, 2.0 / N * np.abs(yf[0:N // 2]))
            plot_widget.setTitle(title)
            plot_widget.setLabel('bottom', 'Częstotliwość (Hz)')
            plot_widget.setLabel('left', 'Amplituda')
            plot_widget.setXRange(0, 3000)
            plot_widget.setYRange(0, 0.0125)
            plot_widget.getAxis('bottom').setTicks([[(i, str(i)) for i in range(0, 3001, 500)]])
            plot_widget.getAxis('left').setTicks([[(i, str(i)) for i in np.arange(0, 0.0126, 0.0025)]])
            plot_widget.show()

        def save_fourier_to_csv(self, signal, filename):
            N = len(signal)
            T = 1 / self.sampling_rate
            yf = fft(signal)
            xf = np.fft.fftfreq(N, T)[:N // 2]

            with open(filename, 'w', newline='') as csvfile:
                csvwriter = csv.writer(csvfile)
                csvwriter.writerow(['Częstotliwość', 'Amplituda'])
                for freq, amp in zip(xf, 2.0 / N * np.abs(yf[0:N // 2])):
                    csvwriter.writerow([freq, amp])

        def save_to_wav(self, t, signal, filename):
            scaled_data = np.int16(signal / np.max(np.abs(signal)) * 32767)
            wavfile.write(filename, self.sampling_rate, scaled_data)

    class SignalGeneratorGUI(PyQt5.QtWidgets.QMainWindow):
        def __init__(self):
            super().__init__()

            self.generator = SignalGenerator(44100, 5)

            self.central_widget = PyQt5.QtWidgets.QWidget()
            self.setCentralWidget(self.central_widget)

            self.init_ui()

        def init_ui(self):
            # Layouts
            main_layout = PyQt5.QtWidgets.QHBoxLayout()

            # Left-side layout for signal options
            options_layout = PyQt5.QtWidgets.QVBoxLayout()

            # Signal Type
            signal_type_label = PyQt5.QtWidgets.QLabel("Typ sygnału:")
            self.signal_type_combo = PyQt5.QtWidgets.QComboBox()
            self.signal_type_combo.addItems(['Sine', 'Square', 'Triangle', 'Sawtooth', 'White Noise'])
            options_layout.addWidget(signal_type_label)
            options_layout.addWidget(self.signal_type_combo)

            # Sampling Rate
            sampling_rate_label = PyQt5.QtWidgets.QLabel("Częstotliwość próbkowania:")
            self.sampling_rate_spin = PyQt5.QtWidgets.QSpinBox()
            self.sampling_rate_spin.setValue(44100)
            options_layout.addWidget(sampling_rate_label)
            options_layout.addWidget(self.sampling_rate_spin)

            # Duration
            duration_label = PyQt5.QtWidgets.QLabel("Długość trwania:")
            self.duration_spin = PyQt5.QtWidgets.QSpinBox()
            self.duration_spin.setValue(5)
            options_layout.addWidget(duration_label)
            options_layout.addWidget(self.duration_spin)

            # Frequency
            frequency_label = PyQt5.QtWidgets.QLabel("Częstotliwość:")
            self.frequency_double_spin = PyQt5.QtWidgets.QDoubleSpinBox()
            self.frequency_double_spin.setValue(440)
            options_layout.addWidget(frequency_label)
            options_layout.addWidget(self.frequency_double_spin)

            # Amplitude
            amplitude_label = PyQt5.QtWidgets.QLabel("Amplituda:")
            self.amplitude_double_spin = PyQt5.QtWidgets.QDoubleSpinBox()
            self.amplitude_double_spin.setValue(1.0)
            options_layout.addWidget(amplitude_label)
            options_layout.addWidget(self.amplitude_double_spin)

            # Generate Button
            generate_button = PyQt5.QtWidgets.QPushButton("Generuj sygnał")
            generate_button.clicked.connect(self.generate_signal)
            options_layout.addWidget(generate_button)

            # Right-side layout for plots and tables
            plots_layout = PyQt5.QtWidgets.QVBoxLayout()

            # Table for time domain
            self.table = PyQt5.QtWidgets.QTableWidget()
            self.table.setColumnCount(2)
            self.table.setHorizontalHeaderLabels(['Czas', 'Amplituda'])
            plots_layout.addWidget(self.table)

            # Middle layout for plots
            middle_layout = PyQt5.QtWidgets.QVBoxLayout()

            # Plot
            self.plot_widget = pg.PlotWidget()
            self.plot_widget.setLabel('bottom', 'Czas (s)')
            self.plot_widget.setLabel('left', 'Amplituda')
            middle_layout.addWidget(self.plot_widget)

            # Fourier Transform Plot
            self.fourier_plot_widget = pg.PlotWidget()
            self.fourier_plot_widget.setLabel('bottom', 'Częstotliwość (Hz)')
            self.fourier_plot_widget.setLabel('left', 'Amplituda')
            middle_layout.addWidget(self.fourier_plot_widget)

            plots_layout.addLayout(middle_layout)

            main_layout.addLayout(options_layout)
            main_layout.addLayout(plots_layout)

            # Menu Bar
            menubar = self.menuBar()
            file_menu = menubar.addMenu('Plik')

            # Save to WAV
            save_wav_action = PyQt5.QtWidgets.QAction('Zapisz do WAV', self)
            save_wav_action.triggered.connect(self.save_to_wav)
            file_menu.addAction(save_wav_action)

            # Save to CSV
            save_csv_action = PyQt5.QtWidgets.QAction('Zapisz do CSV', self)
            save_csv_action.triggered.connect(self.save_to_csv)
            file_menu.addAction(save_csv_action)

            self.central_widget.setLayout(main_layout)
            self.setWindowTitle("Generator Sygnałów")
            self.show()

        def generate_signal(self):
            signal_type = self.signal_type_combo.currentText()
            frequency = self.frequency_double_spin.value()
            amplitude = self.amplitude_double_spin.value()
            duration = self.duration_spin.value()
            sampling_rate = self.sampling_rate_spin.value()

            t, signal = self.generator.generate_sine(frequency, amplitude)  # Default to sine for simplicity

            # Update Table
            self.table.setRowCount(len(t))
            for i in range(len(t)):
                self.table.setItem(i, 0, PyQt5.QtWidgets.QTableWidgetItem(str(t[i])))
                self.table.setItem(i, 1, PyQt5.QtWidgets.QTableWidgetItem(str(signal[i])))

            # Update Plot
            self.plot_widget.clear()
            self.plot_widget.plot(t, signal, pen='b')

            # Update Fourier Transform Plot
            self.fourier_plot_widget.clear()
            self.generator.plot_fourier_transform(signal, 'Fourier Transform', self.fourier_plot_widget)

        def save_to_wav(self):
            filename, _ = PyQt5.QtWidgets.QFileDialog.getSaveFileName(self, 'Zapisz do pliku WAV', '',
                                                      'Wave Files (*.wav);;All Files (*)')
            if filename:
                self.generator.save_to_wav(self.table, filename)

        def save_to_csv(self):
            filename, _ = PyQt5.QtWidgets.QFileDialog.getSaveFileName(self, 'Zapisz do pliku CSV', '',
                                                      'CSV Files (*.csv);;All Files (*)')
            if filename:
                self.generator.save_fourier_to_csv(self.table, filename)

    if __name__ == '__main__':
        app = PyQt5.QtWidgets.QApplication(sys.argv)
        window = SignalGeneratorGUI()
        sys.exit(app.exec_())

    def generate_signal(self):
        signal_type = self.signal_type_combo.currentText()
        frequency = self.frequency_double_spin.value()
        amplitude = self.amplitude_double_spin.value()
        duration = self.duration_spin.value()
        sampling_rate = self.sampling_rate_spin.value()

        t, signal = self.generator.generate_sine(frequency, amplitude)  # Default to sine for simplicity

        # Update Table
        self.table.setRowCount(len(t))
        for i in range(len(t)):
            self.table.setItem(i, 0, PyQt5.QtWidgets.QTableWidgetItem(str(t[i])))
            self.table.setItem(i, 1, PyQt5.QtWidgets.QTableWidgetItem(str(signal[i])))

        # Update Plot
        self.plot_widget.clear()
        self.plot_widget.plot(t, signal, pen='b')

        # Update Fourier Transform Plot
        self.fourier_plot_widget.clear()
        self.generator.plot_fourier_transform(signal, 'Fourier Transform', self.fourier_plot_widget)

    def save_to_wav(self):
        filename, _ = PyQt5.QtWidgets.QFileDialog.getSaveFileName(self, 'Zapisz do pliku WAV', '', 'Wave Files (*.wav);;All Files (*)')
        if filename:
            self.generator.save_to_wav(self.table, filename)

    def save_to_csv(self):
        filename, _ = PyQt5.QtWidgets.QFileDialog.getSaveFileName(self, 'Zapisz do pliku CSV', '', 'CSV Files (*.csv);;All Files (*)')
        if filename:
            self.generator.save_fourier_to_csv(self.table, filename)

if __name__ == '__main__':
    app = PyQt5.QtWidgets.QApplication(sys.argv)
    window = SignalGeneratorGUI()
    sys.exit(app.exec_())
Editor is loading...
Leave a Comment