-
Notifications
You must be signed in to change notification settings - Fork 0
/
serial_plotter.py
128 lines (100 loc) · 4.7 KB
/
serial_plotter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from PyQt5.QtWidgets import QFileDialog, QMainWindow, QVBoxLayout, QHBoxLayout, QPushButton, QWidget, QSizePolicy, QMessageBox, QComboBox
from PyQt5.QtCore import QTimer
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from utils import get_ports, get_baudrates
from serial_connection import SerialConnection
from exporter import Exporter
from patient_info_dialog import PatientInfoDialog
from csv_reader import read_csv_and_plot
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
class SerialPlotter(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Spirometer XL VER. 1.0")
self.setGeometry(100, 100, 1000, 900)
main_widget = QWidget()
self.setCentralWidget(main_widget)
main_layout = QVBoxLayout(main_widget)
self.figure, ((self.ax1, self.ax2), (self.ax3, self.ax4)) = plt.subplots(2, 2)
self.canvas = FigureCanvas(self.figure)
main_layout.addWidget(self.canvas)
controls_layout = QHBoxLayout()
self.port_combo = get_ports()
self.baudrate_combo = get_baudrates()
# Create the buttons
self.connect_button = QPushButton("Connect")
self.connect_button.clicked.connect(self.connect_serial)
# Button to read CSV file
self.read_csv_button = QPushButton("Open ...")
self.read_csv_button.clicked.connect(self.read_csv)
controls_layout.addWidget(self.read_csv_button)
# Add the controls to the controls layout
controls_layout.addWidget(self.port_combo)
controls_layout.addWidget(self.baudrate_combo)
controls_layout.addWidget(self.connect_button)
self.export_start_button = QPushButton("Export")
self.export_start_button.clicked.connect(self.start_export)
self.export_start_button.setEnabled(True)
controls_layout.addWidget(self.export_start_button)
main_layout.addLayout(controls_layout)
self.serial_connection = SerialConnection()
self.exporter = Exporter(self)
# Create an animation for updating the plots
self.animation = FuncAnimation(self.figure, self.update_plot, interval=100)
def read_csv(self):
filename, _ = QFileDialog.getOpenFileName(
self, "Open CSV File", "", "CSV Files (*.csv)"
)
if filename:
read_csv_and_plot(filename, self.figure)
def connect_serial(self):
if self.serial_connection.is_connected:
# Disconnect the serial connection
self.serial_connection.close_connection()
self.connect_button.setText("Connect")
self.export_start_button.setEnabled(True)
else:
# Connect to the serial port
port = self.port_combo.currentText()
baudrate = int(self.baudrate_combo.currentText())
try:
self.serial_connection.connect(port, baudrate)
if self.serial_connection.is_connected:
self.connect_button.setText("Disconnect")
self.export_start_button.setEnabled(False)
self.serial_connection.start_reading(self.update_data)
else:
QMessageBox.warning(self, "Connection Error", "Failed to connect to the serial port.")
except Exception as e:
QMessageBox.warning(self, "Error", f"An error occurred while connecting: {e}")
def update_data(self, values):
self.serial_connection.append_data(values)
def update_plot(self, frame):
self.ax1.clear()
self.ax2.clear()
self.ax3.clear()
self.ax4.clear()
# Update each plot with its respective data
self.serial_connection.update_plot(self.ax1, self.ax2, self.ax3, self.ax4)
# Set labels for each subplot
self.ax1.set_title("Differential Pressure")
self.ax1.set_xlabel("Time (sec)")
self.ax1.set_ylabel("Pressure (Kpa)")
self.ax2.set_title("Flow Rate")
self.ax2.set_xlabel("Time")
self.ax2.set_ylabel("Flow rate")
self.ax3.set_title("Volume")
self.ax3.set_xlabel("Time")
self.ax3.set_ylabel("Volume")
self.ax4.set_title("Volume vs. Flow rate")
self.ax4.set_xlabel("Volume")
self.ax4.set_ylabel("Flow rate")
def start_export(self):
dialog = PatientInfoDialog(self)
if dialog.exec_():
self.exporter.export_data(self.folder_path, self.serial_connection.get_data())
def closeEvent(self, event):
self.serial_connection.close_connection()
event.accept()