def __init__(self): super(Ui_MainWindow, self).__init__() self.userinfo = UserInfo("userinfo.txt") self.figure = Figure() self.stack1 = QWidget() self.stack2 = QWidget() self.stack3 = QWidget() self.init_main_window() self.init_parameter_window() self.init_egram_window() self.Stack = QStackedWidget(self) self.Stack.addWidget(self.stack1) self.Stack.addWidget(self.stack2) self.Stack.addWidget(self.stack3) hbox = QHBoxLayout(self) hbox.addWidget(self.Stack) self.setLayout(hbox) self.setGeometry(300, 50, 750, 400) self.setWindowTitle('Pacemaker DCM') self.show()
def init_egram_window(self): layout = QFormLayout() layout.setContentsMargins(30, 30, 30, 30) # left,top,right,bottom # matplotlib figure self.figure = CustomFigCanvas((0, 175), (-2, 4), 5, 5, 75) layout.addRow(self.figure) # - Buttons back, start = QPushButton("Back"), QPushButton("Start") layout.addRow(back, start) back.clicked.connect(self.back) start.clicked.connect(self.start) self.stack3.setLayout(layout)
class Ui_MainWindow(QWidget): def __init__(self): super(Ui_MainWindow, self).__init__() self.userinfo = UserInfo("userinfo.txt") self.figure = Figure() self.stack1 = QWidget() self.stack2 = QWidget() self.stack3 = QWidget() self.init_main_window() self.init_parameter_window() self.init_egram_window() self.Stack = QStackedWidget(self) self.Stack.addWidget(self.stack1) self.Stack.addWidget(self.stack2) self.Stack.addWidget(self.stack3) hbox = QHBoxLayout(self) hbox.addWidget(self.Stack) self.setLayout(hbox) self.setGeometry(300, 50, 750, 400) self.setWindowTitle('Pacemaker DCM') self.show() # ---- Init Functions def init_main_window(self): layout = QFormLayout() layout.setContentsMargins(300, 150, 300, 150) # left,top,right,bottom # - Textboxes self.t_username, self.t_password = QLineEdit("test_user"), QLineEdit( "pass") self.t_password.setEchoMode(QLineEdit.Password) layout.addRow("Username:"******"Password:"******"Login"), QPushButton("Register") layout.addRow(b_login, b_register) b_login.clicked.connect(self.login) b_register.clicked.connect(self.register) # - Label self.l_message = QLabel(" ") self.l_message.setStyleSheet("font-weight:bold;color:red") layout.addRow(self.l_message) self.stack1.setLayout(layout) def init_parameter_window(self): layout = QFormLayout() layout.setContentsMargins(300, 150, 300, 150) # left,top,right,bottom # - Parameters # heart rate self.sb_heartrate = QSpinBox() self.sb_heartrate.setRange(30, 175) container = Wrapper((self.sb_heartrate, QLabel(("(bpm)")))) layout.addRow("Heart Rate:", container) # chamber to pulse rbg_chambertopulse = QButtonGroup() self.rb_ctp_A = QRadioButton("A") rbg_chambertopulse.addButton(self.rb_ctp_A) self.rb_ctp_V = QRadioButton("V") rbg_chambertopulse.addButton(self.rb_ctp_V) container = Wrapper((self.rb_ctp_A, self.rb_ctp_V)) layout.addRow("Chamber to Pulse: ", container) # pulse width self.sb_pulsewidth = QDoubleSpinBox() self.sb_pulsewidth.setRange(0.1, 1.9) self.sb_pulsewidth.setDecimals(1) self.sb_pulsewidth.setSingleStep(0.1) container = Wrapper((self.sb_pulsewidth, QLabel(("(msec)")))) layout.addRow("Pulse Width:", container) # pulse amplitude self.sb_pulseamplitude = QDoubleSpinBox() self.sb_pulseamplitude.setRange(0.5, 7.0) self.sb_pulseamplitude.setDecimals(1) self.sb_pulseamplitude.setSingleStep(0.1) container = Wrapper((self.sb_pulseamplitude, QLabel(("(V)")))) layout.addRow("Pulse Amplitude:", container) # chamber to sense rbg_chambertosense = QButtonGroup() self.rb_cts_A = QRadioButton("A") rbg_chambertosense.addButton(self.rb_cts_A) self.rb_cts_V = QRadioButton("V") rbg_chambertosense.addButton(self.rb_cts_V) self.rb_cts_none = QRadioButton("None") rbg_chambertosense.addButton(self.rb_cts_none) container = Wrapper((self.rb_cts_A, self.rb_cts_V, self.rb_cts_none)) layout.addRow("Chamber to Sense: ", container) # ventricular sensitivity self.sb_ventricularsensitivity = QDoubleSpinBox() self.sb_ventricularsensitivity.setRange(1, 10) self.sb_ventricularsensitivity.setDecimals(1) self.sb_ventricularsensitivity.setSingleStep(0.1) container = Wrapper((self.sb_ventricularsensitivity, QLabel(("(mV)")))) layout.addRow("Ventricular Sensitivity: ", container) # atrial sensitivity rbg_atrialsensitivity = QButtonGroup() self.rb_as_25 = QRadioButton("0.25") rbg_atrialsensitivity.addButton(self.rb_as_25) self.rb_as_50 = QRadioButton("0.50") rbg_atrialsensitivity.addButton(self.rb_as_50) self.rb_as_75 = QRadioButton("0.75") rbg_atrialsensitivity.addButton(self.rb_as_75) container = Wrapper( (self.rb_as_25, self.rb_as_50, self.rb_as_75, QLabel("(mV)"))) layout.addRow("Atrial Sensitivity: ", container) # rate adaption rbg_rateadaption = QButtonGroup() self.rb_ra_on = QRadioButton("On") rbg_rateadaption.addButton(self.rb_ra_on) self.rb_ra_off = QRadioButton("Off") rbg_rateadaption.addButton(self.rb_ra_off) container = Wrapper((self.rb_ra_on, self.rb_ra_off)) layout.addRow("Rate Adaption: ", container) # Medium Activity Threshold self.sb_mediumactivitythreshold = QSpinBox() self.sb_mediumactivitythreshold.setRange(0, 500) container = Wrapper((self.sb_mediumactivitythreshold, )) layout.addRow("Medium Activity Threshold: ", container) # High Activity Threshold self.sb_highactivitythreshold = QSpinBox() self.sb_highactivitythreshold.setRange(0, 500) container = Wrapper((self.sb_highactivitythreshold, )) layout.addRow("High Activity Interval: ", container) # Reaction Time self.sb_reactiontime = QSpinBox() self.sb_reactiontime.setRange(10, 50) container = Wrapper((self.sb_reactiontime, QLabel("(s)"))) layout.addRow("Reaction Time: ", container) # Recovery Time self.sb_recoverytime = QSpinBox() self.sb_recoverytime.setRange(2, 16) container = Wrapper((self.sb_recoverytime, QLabel("(min)"))) layout.addRow("Recovery Time: ", container) # hysterisis rbg_hysteris = QButtonGroup() self.rb_h_on = QRadioButton("On") rbg_hysteris.addButton(self.rb_ra_on) self.rb_h_off = QRadioButton("Off") rbg_hysteris.addButton(self.rb_ra_off) container = Wrapper((self.rb_h_on, self.rb_h_off)) layout.addRow("Hysterisis: ", container) # hysterisis interval self.sb_hysterisisinterval = QSpinBox() self.sb_hysterisisinterval.setRange(200, 500) container = Wrapper((self.sb_hysterisisinterval, QLabel(("(msec)")))) layout.addRow("Hysterisis Interval: ", container) # vrp self.sb_vrp = QSpinBox() self.sb_vrp.setRange(150, 500) container = Wrapper((self.sb_vrp, QLabel("(msec)"))) layout.addRow("VRP: ", container) # arp self.sb_arp = QSpinBox() self.sb_arp.setRange(150, 500) container = Wrapper((self.sb_arp, QLabel("(msec)"))) layout.addRow("ARP: ", container) # - Set default parameter values self.param_set_default() # - Buttons b_logout, b_update, b_egram = QPushButton("Logout"), QPushButton( "Update"), QPushButton("Show Electrogram") container = Wrapper((b_logout, b_update, b_egram)) layout.addRow(container) b_logout.clicked.connect(self.logout) b_update.clicked.connect(self.update) b_egram.clicked.connect(self.show_egram) self.rb_ctp_A.clicked.connect(self.check_chamber_pulse) self.rb_ctp_V.clicked.connect(self.check_chamber_pulse) self.rb_cts_A.clicked.connect(self.check_chamber_sense) self.rb_cts_V.clicked.connect(self.check_chamber_sense) self.stack2.setLayout(layout) def param_set_default(self): self.sb_heartrate.setValue(60) self.rb_ctp_V.setChecked(True) self.sb_pulsewidth.setValue(0.4) self.sb_pulseamplitude.setValue(3.5) self.rb_cts_none.setChecked(True) self.sb_ventricularsensitivity.setValue(2.5) self.rb_as_75.setChecked(True) self.rb_ra_off.setChecked(True) self.sb_mediumactivitythreshold.setValue(0) self.sb_highactivitythreshold.setValue(0) self.sb_reactiontime.setValue(10) self.sb_recoverytime.setValue(2) self.rb_h_off.setChecked(True) self.sb_hysterisisinterval.setValue(300) self.sb_vrp.setValue(320) self.sb_arp.setValue(250) def init_egram_window(self): layout = QFormLayout() layout.setContentsMargins(30, 30, 30, 30) # left,top,right,bottom # matplotlib figure self.figure = CustomFigCanvas((0, 175), (-2, 4), 5, 5, 75) layout.addRow(self.figure) # - Buttons back, start = QPushButton("Back"), QPushButton("Start") layout.addRow(back, start) back.clicked.connect(self.back) start.clicked.connect(self.start) self.stack3.setLayout(layout) # ---- Get Functions # Returns a list of parameters if all parameters are within acceptable range # Returns an error message if not def get_parameters(self): # Read values heartrate = int(self.sb_heartrate.value()) chambertopulse = 0 if self.rb_ctp_A.isChecked() else (\ 1 if self.rb_ctp_V.isChecked() else 'P') pulsewidth = int(self.sb_pulsewidth.value() * 10) pulseamplitude = int(self.sb_pulseamplitude.value() * 10) chambertosense = 0 if self.rb_cts_none.isChecked() else (\ 1 if self.rb_cts_V.isChecked() else (\ 2 if self.rb_cts_A.isChecked() else 'S')) ventricularsensitivity = int(self.sb_ventricularsensitivity.value() * 10) atrialsensitivity = 25 if self.rb_cts_A.isChecked() else (\ 50 if self.rb_cts_V.isChecked() else (\ 75 if self.rb_cts_none.isChecked() else '')) rateadaptation = 1 if self.rb_ra_on.isChecked() else (\ 0 if self.rb_ra_off.isChecked() else '') mediumthreshold = self.sb_mediumactivitythreshold.value() highthreshold = self.sb_highactivitythreshold.value() reactiontime = self.sb_reactiontime.value() recoverytime = self.sb_recoverytime.value() hysterisis = 1 if self.rb_h_on.isChecked() else (\ 0 if self.rb_h_off.isChecked() else 'H') hysterisisinterval = self.sb_hysterisisinterval.value() // 2 vrp = self.sb_vrp.value() // 2 arp = self.sb_arp.value() // 2 return [ 22, 85, 0, heartrate, # byte 4 chambertopulse, # byte 5 pulsewidth, # byte 6 mediumthreshold, # byte 7 pulseamplitude, # byte 8 highthreshold, # byte 9 chambertosense, # byte 10 ventricularsensitivity, # byte 11 0, # byte 12 (free) atrialsensitivity, # byte 13 rateadaptation, # byte 14 hysterisis, # byte 15 hysterisisinterval, # byte 16 reactiontime, # byte 17 vrp, # byte 18 recoverytime, # byte 19 arp ] # byte 20 # ---- Button Functions def login(self): user, password = self.t_username.text(), self.t_password.text() if user == '' or password == '': message = "The fields cannot be empty." else: message = self.userinfo.login(user, password) if message == "Login successful.": self.Stack.setCurrentIndex(1) else: self.l_message.setText(message) def register(self): user, password = self.t_username.text(), self.t_password.text() if user == '' or password == '': message = "The fields cannot be empty." else: message = self.userinfo.register(user, password) self.param_set_default() self.l_message.setText(message) def logout(self): self.Stack.setCurrentIndex(0) self.t_username.setText("") self.t_password.setText("") self.l_message.setText("") def update(self): global bpm bpm = int(self.sb_heartrate.value()) par = self.get_parameters() print("Sent:\t", bytearray(par)) serial(bytearray(par)) a = bytearray(par) print([i for i in a]) def show_egram(self): self.Stack.setCurrentIndex(2) def back(self): global stop, start if start: stop = True # kills thread start = False self.t1.join() self.figure.y = self.figure.n * 0.0 self.Stack.setCurrentIndex(1) def start(self): global stop, start if start: print("Cannot start multiple threads.") return stop = False start = True self.t1 = threading.Thread( target=dataSendLoop, daemon=True, args=(self.addData_callback, ) ) # setting daemon to True kills the thread when the main thread exits. self.t1.start() # ensures that pulse and sense are in the same mode at all times def check_chamber_pulse(self): if self.rb_cts_none.isChecked(): return if (self.rb_ctp_A.isChecked()): self.rb_cts_A.setChecked(True) elif (self.rb_ctp_V.isChecked()): self.rb_cts_V.setChecked(True) def check_chamber_sense(self): if (self.rb_cts_A.isChecked()): self.rb_ctp_A.setChecked(True) elif (self.rb_cts_V.isChecked()): self.rb_ctp_V.setChecked(True) # ---- For egram multithreading def addData_callback(self, val): self.figure.add_data(val)