GUI3
unknown
python
2 years ago
11 kB
12
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_to_wav(self, t, signal, filename):
if signal is not None:
scaled_data = np.int16(signal / np.max(np.abs(signal)) * 32767)
scaled_data = scaled_data.flatten()
wavfile.write(filename, self.sampling_rate, scaled_data)
def save_fourier_to_csv(self, signal, filename):
if signal is not None:
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.item(), amp.item()])
class SignalGeneratorGUI(PyQt5.QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.generator = SignalGenerator(44100, 5)
self.t = None
self.signal = None
self.central_widget = PyQt5.QtWidgets.QWidget()
self.setCentralWidget(self.central_widget)
self.init_ui()
def init_ui(self):
main_layout = PyQt5.QtWidgets.QHBoxLayout()
options_layout = PyQt5.QtWidgets.QVBoxLayout()
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_label = PyQt5.QtWidgets.QLabel("Częstotliwość próbkowania (Hz):")
self.sampling_rate_spin = PyQt5.QtWidgets.QSpinBox()
self.sampling_rate_spin.setValue(44100)
self.sampling_rate_spin.setRange(0, 100000)
self.sampling_rate_spin.setSingleStep(1)
options_layout.addWidget(sampling_rate_label)
options_layout.addWidget(self.sampling_rate_spin)
duration_label = PyQt5.QtWidgets.QLabel("Długość trwania (s):")
self.duration_spin = PyQt5.QtWidgets.QSpinBox()
self.duration_spin.setValue(0)
self.duration_spin.setRange(0, 100000)
self.duration_spin.setSingleStep(1)
options_layout.addWidget(duration_label)
options_layout.addWidget(self.duration_spin)
frequency_label = PyQt5.QtWidgets.QLabel("Częstotliwość (Hz):")
self.frequency_double_spin = PyQt5.QtWidgets.QDoubleSpinBox()
self.frequency_double_spin.setValue(0)
self.frequency_double_spin.setRange(0, 100000)
self.frequency_double_spin.setSingleStep(1)
options_layout.addWidget(frequency_label)
options_layout.addWidget(self.frequency_double_spin)
amplitude_label = PyQt5.QtWidgets.QLabel("Amplituda:")
self.amplitude_double_spin = PyQt5.QtWidgets.QDoubleSpinBox()
self.amplitude_double_spin.setValue(0)
self.amplitude_double_spin.setRange(0, 100000)
self.amplitude_double_spin.setSingleStep(1)
options_layout.addWidget(amplitude_label)
options_layout.addWidget(self.amplitude_double_spin)
generate_button = PyQt5.QtWidgets.QPushButton("Generuj sygnał")
generate_button.clicked.connect(self.generate_signal)
options_layout.addWidget(generate_button)
self.sampling_rate_spin.valueChanged.connect(self.update_signal)
self.duration_spin.valueChanged.connect(self.update_signal)
self.frequency_double_spin.valueChanged.connect(self.update_signal)
self.amplitude_double_spin.valueChanged.connect(self.update_signal)
plots_layout = PyQt5.QtWidgets.QHBoxLayout()
self.table = PyQt5.QtWidgets.QTableWidget()
self.table.setColumnCount(2)
self.table.setHorizontalHeaderLabels(['Czas', 'Zbiór wartości'])
plots_layout.addWidget(self.table)
middle_layout = PyQt5.QtWidgets.QVBoxLayout()
self.plot_widget = pg.PlotWidget()
self.plot_widget.setLabel('bottom', 'Czas (s)')
self.plot_widget.setLabel('left', 'Amplituda')
middle_layout.addWidget(self.plot_widget)
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)
menubar = self.menuBar()
file_menu = menubar.addMenu('Plik')
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_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 update_signal(self):
if self.t is not None and self.signal is not None and len(self.t) > 0 and len(self.signal) > 0:
self.table.setRowCount(len(self.t))
for i in range(len(self.t)):
self.table.setItem(i, 0, PyQt5.QtWidgets.QTableWidgetItem(str(self.t[i])))
self.table.setItem(i, 1, PyQt5.QtWidgets.QTableWidgetItem(str(self.signal[i])))
self.plot_widget.clear()
self.plot_widget.plot(self.t, self.signal, pen='b')
self.fourier_plot_widget.clear()
self.generator.plot_fourier_transform(self.signal, 'Fourier Transform', self.fourier_plot_widget)
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()
self.t, self.signal = [], []
if signal_type == 'Sine':
self.t, self.signal = self.generator.generate_sine(frequency, amplitude)
elif signal_type == 'Square':
self.t, self.signal = self.generator.generate_square(frequency, amplitude)
elif signal_type == 'Triangle':
self.t, self.signal = self.generator.generate_triangle(frequency, amplitude)
elif signal_type == 'Sawtooth':
self.t, self.signal = self.generator.generate_sawtooth(frequency, amplitude)
elif signal_type == 'White Noise':
self.t, self.signal = self.generator.generate_white_noise(amplitude)
self.update_signal()
t, signal = self.generator.generate_sine(frequency, amplitude)
self.table.setRowCount(len(self.t))
for i in range(len(self.t)):
self.table.setItem(i, 0, PyQt5.QtWidgets.QTableWidgetItem(str(self.t[i])))
self.table.setItem(i, 1, PyQt5.QtWidgets.QTableWidgetItem(str(self.signal[i])))
self.plot_widget.clear()
self.plot_widget.plot(self.t, self.signal, pen='b')
self.fourier_plot_widget.clear()
self.generator.plot_fourier_transform(self.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.t, self.signal, 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.signal, filename)
if __name__ == '__main__':
app = PyQt5.QtWidgets.QApplication(sys.argv)
window = SignalGeneratorGUI()
sys.exit(app.exec_())
Editor is loading...
Leave a Comment