810 lines
40 KiB
Python
810 lines
40 KiB
Python
"""Отображение данных"""
|
||
|
||
import sys
|
||
import os.path
|
||
import datetime
|
||
import time
|
||
|
||
import numpy as np
|
||
|
||
from PyQt5.QtCore import QIODevice
|
||
from PyQt5.QtSerialPort import QSerialPortInfo, QSerialPort
|
||
|
||
from PyQt5.QtGui import *
|
||
from PyQt5 import QtWidgets, uic, QtGui
|
||
from PyQt5.QtWidgets import QFileDialog
|
||
from PyQt5 import QtCore
|
||
from pyqtgraph import TextItem
|
||
import pyqtgraph as pg
|
||
import project.controller as my_data
|
||
from project import mes
|
||
|
||
# выбор режима чения из файла или из com-порта
|
||
MODE_COM_PORT = False
|
||
MODE_FILE = False
|
||
|
||
# объявили экземпляры класса, для обработки данных из файла или из com-порта
|
||
data_IN_FILE = my_data.DataClass()
|
||
data_IN_COM = my_data.DataClass()
|
||
|
||
# создание приложения
|
||
app = QtWidgets.QApplication(sys.argv)
|
||
|
||
|
||
class Ui(QtWidgets.QMainWindow):
|
||
"""Класс отображения данных"""
|
||
|
||
def __init__(self):
|
||
# создание графического отображения
|
||
super(Ui, self).__init__()
|
||
uic.loadUi('design_viewer_v1.ui', self)
|
||
self.setWindowTitle("Pacemaker viewer")
|
||
self.setWindowIcon(QtGui.QIcon("source/logo.ICO"))
|
||
|
||
self.counter_com_port = [] # координата x для вывода графиков
|
||
|
||
self.point = 0 # координата, откуда начинать отрисовку, если используется полоса прокрутки??
|
||
self.file = "" # файл
|
||
self.file_name = "" # наименование файла
|
||
self.sub_mode_previous = -1 # предыдущее значение подрежима, для вывода времени зарядки конденсатора
|
||
self.start_time_charging = 0 # начало подчета времени зарядки конденсатора
|
||
self.end_time_charging = 0 # конец подчета времени зарядки конденсатора
|
||
self.charging_time = 0 # время зарядки конденсатора
|
||
self.U_cap_max = 0 # максимальное напряжение на конденсаторе
|
||
|
||
# Создание графиков
|
||
self.graph_init()
|
||
|
||
def set_up_controls():
|
||
"""
|
||
Настройка элементов управления в визуале
|
||
"""
|
||
self.OpenB.setVisible(False)
|
||
self.CloseB.setVisible(False)
|
||
self.Play.setVisible(False)
|
||
self.Pause.setVisible(False)
|
||
self.horizontalScrollBar.setVisible(False)
|
||
self.horizontalScrollBar.valueChanged.connect(self.on_scroll)
|
||
self.radioButton_work_mode_com_port.toggled.connect(self.check_work_mode_viewer)
|
||
self.Play.clicked.connect(self.on_play)
|
||
self.Pause.clicked.connect(self.on_pause)
|
||
self.OpenB.clicked.connect(self.on_open)
|
||
self.CloseB.clicked.connect(self.on_close)
|
||
self.Write_file.clicked.connect(self.write_file)
|
||
self.Close_file.clicked.connect(self.close_file)
|
||
self.Read.clicked.connect(self.on_start)
|
||
self.Stop.clicked.connect(self.on_stop)
|
||
self.Restart.clicked.connect(self.restart)
|
||
self.SD_card_Box.currentTextChanged.connect(self.set_SD_card)
|
||
self.Send_mode_Box.currentTextChanged.connect(self.set_send_mode)
|
||
self.Port_ch.addItems(self.update_list())
|
||
self.horizontalScrollBar.valueChanged.connect(self.on_scroll)
|
||
self.RA_scale_BOX.currentTextChanged.connect(self.on_scale_change)
|
||
self.f_count_spinBox.valueChanged.connect(self.set_fibr_cnt_max)
|
||
self.t2_count_spinBox.valueChanged.connect(self.set_tachy_2_cnt_max)
|
||
self.t1_count_spinBox.valueChanged.connect(self.set_tachy_1_cnt_max)
|
||
|
||
self.RA_max_time_ms_BOX.editTextChanged.connect(self.set_RA_max_time_ms_BOX)
|
||
self.RA_min_sensitivity_BOX.editTextChanged.connect(self.set_RA_min_sensitivity_BOX)
|
||
self.RA_max_sensitivity_BOX.editTextChanged.connect(self.set_RA_max_sensitivity_BOX)
|
||
self.RA_square_time_ms_BOX.editTextChanged.connect(self.set_RA_square_time_ms_BOX)
|
||
self.RA_square_coeff_BOX.editTextChanged.connect(self.set_RA_square_coeff_BOX)
|
||
self.RA_all_time_ms_BOX.editTextChanged.connect(self.set_RA_all_time_ms_BOX)
|
||
self.Signal_Box.currentIndexChanged.connect(self.set_Signal_Box)
|
||
self.Channel_Box.currentIndexChanged.connect(self.set_Channel_Box)
|
||
self.DC_cut_Box.currentIndexChanged.connect(self.set_DC_cut_Box)
|
||
|
||
self.High_Tf_spinBox.valueChanged.connect(self.set_High_Tf_spinBox)
|
||
self.High_Tt2_spinBox.valueChanged.connect(self.set_High_Tt2_spinBox)
|
||
self.High_Tt1_spinBox.valueChanged.connect(self.set_High_Tt1_spinBox)
|
||
self.f_count_spinBox.valueChanged.connect(self.set_f_count_spinBox)
|
||
|
||
self.Work_Mode_pacemaker.editTextChanged.connect(self.set_Work_Mode_pacemaker)
|
||
self.hv_step_number_spinBox.valueChanged.connect(self.set_hv_step_number_spinBox)
|
||
self.min_energy_spinBox.valueChanged.connect(self.set_min_energy_spinBox)
|
||
self.max_energy_spinBox.valueChanged.connect(self.set_max_energy_spinBox)
|
||
self.hv_polarity_BOX.editTextChanged.connect(self.set_hv_polarity_BOX)
|
||
self.hv_blind_time_spinBox.valueChanged.connect(self.set_hv_blind_time_spinBox)
|
||
self.standby_timer_spinBox.valueChanged.connect(self.set_standby_timer_spinBox)
|
||
self.redet_num_spinBox.valueChanged.connect(self.set_redet_num_spinBox)
|
||
self.redet_bad_spinBox.valueChanged.connect(self.set_redet_bad_spinBox)
|
||
self.Spi_spot_set_spinBox.valueChanged.connect(self.set_Spi_spot_set_spinBox)
|
||
self.hv_mode_BOX.editTextChanged.connect(self.set_hv_mode_BOX)
|
||
self.t1_hv_phase_1_duration_SpinBox.valueChanged.connect(self.set_t1_hv_phase_1_duration_SpinBox)
|
||
self.t2_hv_switch_duration_SpinBox.valueChanged.connect(self.set_t2_hv_switch_duration_SpinBox)
|
||
self.t3_hv_phase_2_duration_SpinBox.valueChanged.connect(self.set_t3_hv_phase_2_duration_SpinBox)
|
||
self.u1_hv_switching_voltage_spinBox.valueChanged.connect(self.set_u1_hv_switching_voltage_spinBox)
|
||
self.u2_hv_cutoff_voltage_spinBox.valueChanged.connect(self.set_u2_hv_cutoff_voltage_spinBox)
|
||
self.lv_polarity_BOX.editTextChanged.connect(self.set_lv_polarity_BOX)
|
||
self.lv_mode_BOX.editTextChanged.connect(self.set_lv_mode_BOX)
|
||
self.u_lv_voltage_SpinBox.valueChanged.connect(self.set_u_lv_voltage_SpinBox)
|
||
self.t1_lv_shock_time_SpinBox.valueChanged.connect(self.set_t1_lv_shock_time_SpinBox)
|
||
self.t2_lv_relax_time_spinBox.valueChanged.connect(self.set_t2_lv_relax_time_spinBox)
|
||
self.burst_cnt_spinBox.valueChanged.connect(self.set_burst_cnt_spinBox)
|
||
self.burst_voltage_SpinBox.valueChanged.connect(self.set_burst_voltage_SpinBox)
|
||
self.burst_period_spinBox.valueChanged.connect(self.set_burst_period_spinBox)
|
||
self.u1_hv_switching_voltage_l.setVisible(False)
|
||
self.u2_hv_cutoff_voltage_l.setVisible(False)
|
||
self.u1_hv_switching_voltage_spinBox.setVisible(False)
|
||
self.u2_hv_cutoff_voltage_spinBox.setVisible(False)
|
||
self.burst_frame.setVisible(False)
|
||
|
||
set_up_controls()
|
||
|
||
# создание соединения с устройством для передачи данных
|
||
self.serial = QSerialPort()
|
||
self.serial.setBaudRate(115200)
|
||
self.serial.readyRead.connect(self.on_read)
|
||
|
||
self.send_mode = 1
|
||
|
||
# Создание таймера для отрисовки графиков
|
||
self.timer = QtCore.QTimer()
|
||
self.timer.timeout.connect(self.timerEvent)
|
||
self.timer.start(20)
|
||
|
||
# Создание таймера для отображения параметров стимулятора
|
||
self.timer_LS = QtCore.QTimer()
|
||
self.timer_LS.timeout.connect(self.timerEvent_param)
|
||
self.timer_LS.start(2000)
|
||
|
||
def write_file(self):
|
||
"""
|
||
Открытие на запись файла
|
||
"""
|
||
self.file, file_name = my_data.write_file()
|
||
self.Write_file.setStyleSheet('background-color: green; color: white')
|
||
self.Fname_w_label.setText(os.path.abspath(file_name))
|
||
|
||
def close_file(self):
|
||
"""
|
||
Закончить запись и закрыть файл
|
||
"""
|
||
self.Fname_w_label.setText('')
|
||
self.Write_file.setStyleSheet('background-color: grey; color: black')
|
||
self.file = my_data.close_file(self.file)
|
||
|
||
def restart(self):
|
||
"""
|
||
Перезагрузка устройства
|
||
"""
|
||
param = 1
|
||
my_data.state_packet(self.send_mode, self.serial, 0x1D, param, 1, int)
|
||
|
||
def timerEvent_param(self):
|
||
"""Запуск по таймеру, для синхронизации параметров стимулятора"""
|
||
if MODE_COM_PORT:
|
||
self.synchronise_param(data_IN_COM)
|
||
if MODE_FILE:
|
||
self.synchronise_param(data_IN_FILE)
|
||
# отрисовка
|
||
app.processEvents()
|
||
|
||
def synchronise_param(self, data_in):
|
||
"""Синхронизация параметров стимулятора"""
|
||
self.SD_card_Box.setCurrentIndex(int(data_in.sd_card))
|
||
self.Signal_Box.setCurrentIndex(int(data_in.signal))
|
||
self.Channel_Box.setCurrentIndex(int(data_in.channel))
|
||
self.DC_cut_Box.setCurrentIndex(int(data_in.dc_cut))
|
||
self.RA_max_time_ms_BOX.setEditText(str(data_in.max_search_time))
|
||
self.RA_min_sensitivity_BOX.setEditText(str(data_in.min_treshold))
|
||
self.RA_max_sensitivity_BOX.setEditText(str(data_in.max_treshold))
|
||
self.RA_square_time_ms_BOX.setEditText(str(data_in.square_time))
|
||
self.RA_square_coeff_BOX.setEditText(f'{data_in.square_coef: .2f}')
|
||
self.RA_all_time_ms_BOX.setEditText(str(data_in.max_time))
|
||
self.High_Tf_spinBox.setValue(data_in.fibr_tres)
|
||
self.High_Tt2_spinBox.setValue(data_in.tachy_2_tres)
|
||
self.High_Tt1_spinBox.setValue(data_in.tachy_1_tres)
|
||
self.f_count_spinBox.setValue(data_in.fibr_max_tres)
|
||
self.hv_step_number_spinBox.setValue(data_in.hv_step_number)
|
||
self.min_energy_spinBox.setValue(data_in.min_energy)
|
||
self.max_energy_spinBox.setValue(data_in.max_energy)
|
||
self.hv_blind_time_spinBox.setValue(data_in.hv_blind_time)
|
||
self.standby_timer_spinBox.setValue(data_in.standby_timer)
|
||
self.redet_num_spinBox.setValue(data_in.redet_num)
|
||
self.redet_bad_spinBox.setValue(data_in.redet_bad)
|
||
self.Work_Mode_pacemaker.setCurrentIndex(data_in.Work_Mode_pacemaker)
|
||
self.Spi_spot_set_spinBox.setValue(data_in.spi_pot_set)
|
||
self.hv_polarity_BOX.setValue(data_in.hv_polarity)
|
||
self.hv_mode_BOX.setValue(data_in.hv_mode)
|
||
self.t1_hv_phase_1_duration_SpinBox.setValue(data_in.hv_phase_1_duration / 10.0)
|
||
self.t3_hv_phase_2_duration_SpinBox.setValue(data_in.hv_phase_2_duration / 10.0)
|
||
self.t2_hv_switch_duration_SpinBox.setValue(data_in.hv_switch_duration / 10.0)
|
||
self.u1_hv_switching_voltage_spinBox.setValue(data_in.hv_switching_voltage)
|
||
self.u2_hv_cutoff_voltage_spinBox.setValue(data_in.hv_cutoff_voltage)
|
||
self.lv_polarity_BOX.setValue(data_in.lv_polarity)
|
||
self.lv_mode_BOX.setValue(data_in.lv_mode)
|
||
self.t1_lv_shock_time_SpinBox().setValue(data_in.lv_shock_time / 10.0)
|
||
self.t2_lv_relax_time_spinBox().setValue(data_in.lv_relax_time)
|
||
self.u_lv_voltage_SpinBox().setValue(data_in.lv_voltage / 10.0)
|
||
self.burst_cnt_spinBox.setValue(data_in.burst_cnt)
|
||
self.burst_voltage_SpinBox.setValue(data_in.burst_voltage / 10.0)
|
||
self.burst_period.setValue(data_in.burst_period)
|
||
|
||
|
||
def timerEvent(self):
|
||
if MODE_COM_PORT:
|
||
self.draw_data(data_IN_COM)
|
||
if MODE_FILE:
|
||
scale = self.get_scale()
|
||
points_count = scale * my_data.DATA_RATE
|
||
if points_count < data_IN_FILE.data_length:
|
||
data_IN_FILE.data_length = points_count
|
||
self.horizontalScrollBar.setValue(data_IN_FILE.i)
|
||
data_IN_FILE.parse_list(data_IN_FILE.chunk[data_IN_FILE.i:data_IN_FILE.i + 640])
|
||
data_IN_FILE.i += 640
|
||
self.graph_1.setXRange(self.counter_com_port[0], self.counter_com_port[0] + scale)
|
||
self.graph_2.setXRange(self.counter_com_port[0], self.counter_com_port[0] + scale)
|
||
self.graph_3.setXRange(self.counter_com_port[0], self.counter_com_port[0] + scale)
|
||
self.draw_data(data_IN_FILE)
|
||
|
||
# отрисовка
|
||
app.processEvents()
|
||
|
||
def on_start(self):
|
||
"""
|
||
Старт обмена с com-портом
|
||
"""
|
||
global MODE_COM_PORT
|
||
data_IN_COM.clear_data()
|
||
self.serial.setPortName(self.Port_ch.currentText())
|
||
self.serial.open(QIODevice.ReadWrite)
|
||
self.serial.flush()
|
||
self.serial.write(mes.encode())
|
||
self.on_close()
|
||
MODE_COM_PORT = True
|
||
self.graph_init()
|
||
scale = self.get_scale()
|
||
data_IN_COM.data_length = scale * my_data.DATA_RATE
|
||
data_IN_COM.update_data(data_IN_COM.data_length)
|
||
self.counter_com_port = list(map(lambda x: x / my_data.DATA_RATE, range(0, data_IN_COM.data_length)))
|
||
|
||
def graph_init(self):
|
||
"""
|
||
Создние графиков
|
||
"""
|
||
# Создание графиков
|
||
self.curve10 = self.graph_1.plot(pen=(0, 0, 255))
|
||
self.curve20 = self.graph_2.plot(pen=(0, 0, 0))
|
||
pen_din_tres = pg.mkPen(color=(255, 0, 0), width=1)
|
||
self.curve21 = self.graph_2.plot(pen=pen_din_tres)
|
||
pen_peak = None
|
||
self.curve22 = self.graph_2.plot(pen=pen_peak)
|
||
self.curve23 = self.graph_2.plot(pen=pen_peak)
|
||
pen_min_tres = pg.mkPen(color=(0, 255, 0), width=2, style=QtCore.Qt.DashLine)
|
||
pen_max_tres = pg.mkPen(color=(0, 0, 255), width=2, style=QtCore.Qt.DashLine)
|
||
self.curve24 = self.graph_2.plot(pen=pen_min_tres)
|
||
self.curve25 = self.graph_2.plot(pen=pen_max_tres)
|
||
self.curve26 = self.graph_2.plot(pen=(0, 0, 0))
|
||
self.curve30 = self.graph_3.plot(pen=(0, 0, 255))
|
||
|
||
def edit_graph(graph):
|
||
"""
|
||
Форматирование полей графиков
|
||
:param graph: поле графика
|
||
"""
|
||
graph.showGrid(x=True, y=True)
|
||
graph.setBackground('w')
|
||
# делаем поле графика нечувствительным к мышке
|
||
graph.setMouseEnabled(x=False, y=False)
|
||
graph.hideButtons()
|
||
graph.getPlotItem().setMenuEnabled(False)
|
||
graph.addLegend(enableMouse=False)
|
||
|
||
edit_graph(self.graph_1)
|
||
edit_graph(self.graph_2)
|
||
edit_graph(self.graph_3)
|
||
|
||
def graph_clear(self):
|
||
"""
|
||
Очистка графиков
|
||
"""
|
||
self.graph_1.clear()
|
||
self.graph_2.clear()
|
||
self.graph_3.clear()
|
||
|
||
def on_read(self):
|
||
"""
|
||
Чтение серии данных
|
||
"""
|
||
rx = self.serial.readAll()
|
||
if self.file != "":
|
||
my_data.write_in_file(self.file, rx)
|
||
data_IN_COM.parse_list(rx)
|
||
|
||
def draw_data(self, data_in):
|
||
"""
|
||
Отрисовка данных
|
||
:param data_in: модель данных
|
||
"""
|
||
self.curve10.setData(self.counter_com_port, data_in.ECG_RA)
|
||
self.curve20.setData(self.counter_com_port, data_in.ECG_RA_pos_sig)
|
||
self.curve21.setData(self.counter_com_port, data_in.ECG_RA_din_threshold)
|
||
self.curve26.setData(self.counter_com_port, np.zeros(len(data_in.ECG_RA)))
|
||
self.curve24.setData(self.counter_com_port, data_in.ECG_RA_min_threshold)
|
||
self.curve25.setData(self.counter_com_port, data_in.ECG_RA_max_threshold)
|
||
self.curve30.setData(self.counter_com_port, data_in.Last_RR_poz_rel)
|
||
self.Vs_cnt_label.setText(str(data_in.Vs_cnt))
|
||
self.Vp_cnt_label.setText(str(data_in.Vp_cnt))
|
||
self.Vn_cnt_label.setText(str(data_in.Vn_cnt))
|
||
self.U_batt_label.setText(str(float(data_in.bat_volt / 1000)))
|
||
self.U_batt_p_label.setText(str(data_in.bat_pers))
|
||
U_cap = float(data_in.hv_volt / 10)
|
||
self.U_cap_label.setText(str(U_cap))
|
||
if U_cap > self.U_cap_max:
|
||
self.U_cap_max = U_cap
|
||
self.Umax_cap_label.setText(str(self.U_cap_max))
|
||
self.now_energy_label.setText(str(data_in.now_energy))
|
||
self.filt_period_label.setText(str(data_in.filt_period))
|
||
self.last_period_label.setText(str(data_in.last_period_stat))
|
||
self.hv_step_cnt_label.setText(str(data_in.hv_step_cnt))
|
||
|
||
self.progressBar_f.setValue(data_in.fibr_cnt)
|
||
self.progressBar_t2.setValue(data_in.tachy_2_cnt)
|
||
self.progressBar_t1.setValue(data_in.tachy_1_cnt)
|
||
self.progressBar_n.setValue(data_in.norm_cnt)
|
||
|
||
if data_in.terapy_now == 0:
|
||
self.terapy_nowB.setStyleSheet('background-color: green; color: white')
|
||
self.terapy_nowB.setText("Поиск корзин")
|
||
if data_in.terapy_now == 1:
|
||
self.terapy_nowB.setStyleSheet('background-color: red; color: white')
|
||
self.terapy_nowB.setText("Терапия фибрилляции")
|
||
|
||
if data_in.terapy_now == 2:
|
||
self.terapy_nowB.setStyleSheet('background-color: yellow; color: black')
|
||
self.terapy_nowB.setText("Терапия сильной тахикардии")
|
||
|
||
if data_in.terapy_now == 3:
|
||
self.terapy_nowB.setStyleSheet('background-color: yellow; color: black')
|
||
self.terapy_nowB.setText("Терапия слабой тахикардии")
|
||
|
||
if data_in.sub_mode == 0:
|
||
self.sub_modeB.setStyleSheet('background-color: green; color: white')
|
||
self.sub_modeB.setText("Терапия неактивна")
|
||
if data_in.sub_mode == 1:
|
||
self.sub_modeB.setStyleSheet('background-color: blue; color: white')
|
||
self.sub_modeB.setText("Зарядка конденсатора")
|
||
|
||
if data_in.sub_mode == 2:
|
||
self.sub_modeB.setStyleSheet('background-color: yellow; color: black')
|
||
self.sub_modeB.setText("Редетекция")
|
||
|
||
if data_in.sub_mode == 3:
|
||
self.sub_modeB.setStyleSheet('background-color: red; color: white')
|
||
self.sub_modeB.setText("Стимуляция")
|
||
if data_in.sub_mode == 4:
|
||
self.sub_modeB.setStyleSheet('background-color: grey; color: black')
|
||
self.sub_modeB.setText("Терапия не сработала")
|
||
|
||
# Вывод времени зарядки конденсатора
|
||
if data_in.sub_mode == 1 and self.sub_mode_previous != 1:
|
||
self.start_time_charging = time.time()
|
||
if data_in.sub_mode == 1 and self.sub_mode_previous == 1:
|
||
self.end_time_charging = time.time()
|
||
self.sub_mode_previous = data_in.sub_mode
|
||
self.charge_timer_label.setText(f"{(self.end_time_charging - self.start_time_charging):.2f}")
|
||
|
||
# так удаляются элементы
|
||
# стирание элементов спереди
|
||
all_items = self.graph_1.items() # Получаем все элементы
|
||
text_items = [item for item in all_items if isinstance(item, TextItem)]
|
||
for text_item in text_items:
|
||
if data_in.draw_cnt / my_data.DATA_RATE - 0.02 < text_item.pos().x() and data_in.draw_cnt / my_data.DATA_RATE + 0.1 > text_item.pos().x():
|
||
self.graph_1.removeItem(text_item)
|
||
|
||
if data_in.V_print:
|
||
data_in.V_print = 0
|
||
if data_in.draw_last_QRS == 0:
|
||
self.text = pg.TextItem('Vs\nT:' + str(data_in.draw_last_period))
|
||
self.text.setColor('green')
|
||
self.text.setFont(QFont('Arial', 7))
|
||
self.text.setPos(data_in.draw_cnt_last / my_data.DATA_RATE, (0 if data_in.dc_cut else 15))
|
||
self.graph_1.addItem(self.text)
|
||
if data_in.draw_last_QRS == 1:
|
||
self.text = pg.TextItem('Vp\nT:' + str(data_in.draw_last_period))
|
||
self.text.setColor('red')
|
||
self.text.setPos(data_in.draw_cnt_last / my_data.DATA_RATE, (0 if data_in.dc_cut else 15))
|
||
self.graph_1.addItem(self.text)
|
||
|
||
def on_stop(self):
|
||
self.close_file()
|
||
global MODE_COM_PORT
|
||
MODE_COM_PORT = False
|
||
self.graph_clear()
|
||
# Создание графиков
|
||
self.graph_init()
|
||
self.serial.flush()
|
||
self.serial.close()
|
||
data_IN_COM.clear_data()
|
||
self.terapy_nowB.setStyleSheet('background-color: lightGray; color: black')
|
||
self.terapy_nowB.setText("")
|
||
self.sub_modeB.setStyleSheet('background-color: lightGray; color: black')
|
||
self.sub_modeB.setText("")
|
||
self.last_period_label.setText("")
|
||
self.filt_period_label.setText("")
|
||
self.Vs_cnt_label.setText("")
|
||
self.Vp_cnt_label.setText("")
|
||
self.Vn_cnt_label.setText("")
|
||
self.progressBar_f.setValue(0)
|
||
self.progressBar_t2.setValue(0)
|
||
self.progressBar_t1.setValue(0)
|
||
self.progressBar_n.setValue(0)
|
||
self.hv_step_cnt_label.setText("")
|
||
self.now_energy_label.setText("")
|
||
self.HR_label.setText("")
|
||
self.OpenB.setEnabled(True)
|
||
self.CloseB.setEnabled(True)
|
||
|
||
def on_open(self):
|
||
"""
|
||
Открыть файл для чтения
|
||
"""
|
||
global MODE_FILE
|
||
self.on_close()
|
||
file, _ = QFileDialog.getOpenFileName(self, 'Open File')
|
||
if file:
|
||
self.timer.start()
|
||
self.timer_LS.start()
|
||
data_IN_FILE.clear_data()
|
||
self.file_name = file
|
||
self.Fname_label.setText(self.file_name)
|
||
my_data.get_data_bin(self.file_name, data_IN_FILE)
|
||
self.counter_com_port = list(map(lambda x: x / my_data.DATA_RATE, range(0, data_IN_FILE.data_length)))
|
||
self.horizontalScrollBar.setMinimum(0)
|
||
self.horizontalScrollBar.setMaximum(len(data_IN_FILE.chunk))
|
||
MODE_FILE = True
|
||
|
||
def on_play(self):
|
||
"""
|
||
Запустить отрисовку
|
||
"""
|
||
self.timer.start()
|
||
self.timer_LS.start()
|
||
|
||
def on_pause(self):
|
||
"""
|
||
Остановить отрисовку
|
||
"""
|
||
self.timer.stop()
|
||
self.timer_LS.stop()
|
||
|
||
|
||
def draw_file(self):
|
||
scale = self.get_scale()
|
||
size = scale * my_data.DATA_RATE
|
||
for x in range(self.point, data_IN_FILE.data_length, 20):
|
||
self.curve10.setData(self.counter_com_port[x: x + size], data_IN_FILE.ECG_RA[x: x + size])
|
||
self.curve20.setData(self.counter_com_port[x: x + size], data_IN_FILE.ECG_RA_pos_sig[x: x + size])
|
||
self.curve21.setData(self.counter_com_port[x: x + size], data_IN_FILE.ECG_RA_din_threshold[x: x + size])
|
||
self.curve26.setData(self.counter_com_port[x: x + size], np.zeros(len(self.counter_com_port[x: x + size])))
|
||
self.curve24.setData(self.counter_com_port[x: x + size], data_IN_FILE.ECG_RA_min_threshold[x: x + size])
|
||
self.curve25.setData(self.counter_com_port[x: x + size], data_IN_FILE.ECG_RA_max_threshold[x: x + size])
|
||
self.curve30.setData(self.counter_com_port[x: x + size], data_IN_FILE.Last_RR_poz_rel[x: x + size])
|
||
app.processEvents()
|
||
time.sleep(0.05)
|
||
|
||
def re_scale(self):
|
||
scale = self.get_scale()
|
||
if len(data_IN_FILE.counter) != 0:
|
||
position = self.horizontalScrollBar.value()
|
||
# self.point = int((len(data_IN_FILE.counter) / my_data.DATA_RATE) * (position / 1000))
|
||
# data_IN_FILE.i = self.point
|
||
data_IN_FILE.i = position
|
||
|
||
def on_scroll(self):
|
||
self.re_scale()
|
||
|
||
def on_close(self):
|
||
"""
|
||
Закрыть открытый для чтения файл
|
||
"""
|
||
global MODE_FILE
|
||
MODE_FILE = False
|
||
# очистка графиков
|
||
self.graph_clear()
|
||
# Пересоздание графиков
|
||
self.graph_init()
|
||
# очистка модели
|
||
data_IN_FILE.clear_data()
|
||
|
||
self.Fname_label.setText('')
|
||
|
||
def get_scale(self):
|
||
scale = int(self.RA_scale_BOX.currentText())
|
||
return scale
|
||
|
||
def on_scale_change(self):
|
||
scale = self.get_scale()
|
||
data_IN_COM.data_length = scale * my_data.DATA_RATE
|
||
data_IN_COM.update_data(data_IN_COM.data_length)
|
||
|
||
if MODE_FILE:
|
||
self.draw_file()
|
||
|
||
all_items = self.graph_1.items() # Получаем все элементы
|
||
text_items = [item for item in all_items if isinstance(item, TextItem)]
|
||
for text_item in text_items:
|
||
self.graph_1.removeItem(text_item)
|
||
self.counter_com_port = list(map(lambda x: x / my_data.DATA_RATE, range(0, data_IN_COM.data_length)))
|
||
|
||
def update_list(self):
|
||
"""Создание списка доступных для ввода/вывода портов"""
|
||
portlist = [] # создадим пустой список в который и будем всё записывать
|
||
ports = QSerialPortInfo().availablePorts() # доступные порты для обмена данными
|
||
for port in ports:
|
||
portlist.append(port.portName())
|
||
return portlist
|
||
|
||
def check_work_mode_viewer(self):
|
||
"""
|
||
Выбор режима работы (чтение данных из файла/из com-порта), в случае чего некоторые элементы отображения
|
||
становятся видимыми и доступными, а другие наоборот становятся недоступными.
|
||
"""
|
||
if self.radioButton_work_mode_com_port.isChecked():
|
||
self.OpenB.setVisible(False)
|
||
self.CloseB.setVisible(False)
|
||
self.Play.setVisible(False)
|
||
self.Pause.setVisible(False)
|
||
self.label_com_port.setVisible(True)
|
||
self.Fname_w_label.setVisible(True)
|
||
self.Port_ch.setVisible(True)
|
||
self.Read.setVisible(True)
|
||
self.Stop.setVisible(True)
|
||
self.Write_file.setVisible(True)
|
||
self.Close_file.setVisible(True)
|
||
self.Restart.setVisible(True)
|
||
self.horizontalScrollBar.setVisible(False)
|
||
else:
|
||
self.on_stop()
|
||
self.OpenB.setVisible(True)
|
||
self.CloseB.setVisible(True)
|
||
self.Play.setVisible(True)
|
||
self.Pause.setVisible(True)
|
||
self.label_com_port.setVisible(False)
|
||
self.Fname_w_label.setVisible(False)
|
||
self.Port_ch.setVisible(False)
|
||
self.Read.setVisible(False)
|
||
self.Stop.setVisible(False)
|
||
self.Write_file.setVisible(False)
|
||
self.Close_file.setVisible(False)
|
||
self.Restart.setVisible(False)
|
||
self.horizontalScrollBar.setVisible(True)
|
||
|
||
def set_send_mode(self):
|
||
"""Установка режима передачи данных (Bluetooth/433)"""
|
||
self.send_mode = int(self.Send_mode_Box.currentIndex())
|
||
|
||
# настройка параметров работы стимулятора с помощью программы
|
||
def set_DC_cut_Box(self):
|
||
"""Настройка вывода сигнала с/без постоянной составляющей"""
|
||
param = int(self.DC_cut_Box.currentIndex())
|
||
my_data.state_packet(self.send_mode, self.serial, 0x21, param, 1, int)
|
||
|
||
def set_Signal_Box(self):
|
||
"""Настройка вывода сигнала с/без фильтром(а)"""
|
||
param = int(self.Signal_Box.currentIndex())
|
||
my_data.state_packet(self.send_mode, self.serial, 0x1E, param, 1, int)
|
||
|
||
def set_Channel_Box(self):
|
||
"""Установка активного канала передачи"""
|
||
param = int(self.Channel_Box.currentIndex())
|
||
my_data.state_packet(self.send_mode, self.serial, 0x1F, param, 1, int)
|
||
|
||
def set_SD_card(self):
|
||
"""Установка режима записи на карту памяти"""
|
||
param = int(self.SD_card_Box.currentIndex())
|
||
my_data.state_packet(self.send_mode, self.serial, 0x20, param, 1, int)
|
||
|
||
def set_Spi_spot_set_spinBox(self):
|
||
"""Установка коэффициента усиления сигнала"""
|
||
param = int(self.Spi_spot_set_spinBox.value())
|
||
my_data.state_packet(self.send_mode, self.serial, 0x1C, param, 1, int)
|
||
|
||
def set_Work_Mode_pacemaker(self):
|
||
"""Установка текущего режима работы стимулятора(без/с стимуляцией или в режиме принудительной стимуляции)"""
|
||
param = int(self.Work_Mode_pacemaker.currentIndex()) # << 20
|
||
my_data.state_packet(self.send_mode, self.serial, 0x05, param, 2, int)
|
||
|
||
def set_RA_max_time_ms_BOX(self):
|
||
"""Установка длительности поиска максимума"""
|
||
param = int(self.RA_max_time_ms_BOX.currentText())
|
||
my_data.state_packet(self.send_mode, self.serial, 0x0D, param, 2, int)
|
||
|
||
def set_RA_min_sensitivity_BOX(self):
|
||
"""Установка минимальной чувствительности"""
|
||
param = float(self.RA_min_sensitivity_BOX.currentText())
|
||
my_data.state_packet(self.send_mode, self.serial, 0x01, param, 4, float)
|
||
|
||
def set_RA_max_sensitivity_BOX(self):
|
||
"""Установка максимальной чувствительности"""
|
||
param = float(self.RA_max_sensitivity_BOX.currentText())
|
||
my_data.state_packet(self.send_mode, self.serial, 0x02, param, 4, float)
|
||
|
||
def set_RA_square_time_ms_BOX(self):
|
||
"""Установка длительности защиты от Т волны"""
|
||
param = int(self.RA_square_time_ms_BOX.currentText())
|
||
my_data.state_packet(self.send_mode, self.serial, 0x07, param, 2, int)
|
||
|
||
def set_RA_square_coeff_BOX(self):
|
||
"""Установка порога чувствительности Т волны"""
|
||
param = float(self.RA_square_coeff_BOX.currentText())
|
||
my_data.state_packet(self.send_mode, self.serial, 0x03, param, 4, float)
|
||
|
||
def set_RA_all_time_ms_BOX(self):
|
||
"""Установка максимального размера RR-интервала"""
|
||
param = int(self.RA_all_time_ms_BOX.currentText())
|
||
my_data.state_packet(self.send_mode, self.serial, 0x09, param, 2, int)
|
||
|
||
def set_High_Tf_spinBox(self):
|
||
"""Установка длительности RR-интервала для определения события как фибрилляции"""
|
||
param = self.High_Tf_spinBox.value()
|
||
my_data.state_packet(self.send_mode, self.serial, 0x10, param, 2, int)
|
||
|
||
def set_High_Tt2_spinBox(self):
|
||
"""Установка длительности RR-интервала для определения события как тахикардии 2ст"""
|
||
param = self.High_Tt2_spinBox.value()
|
||
my_data.state_packet(self.send_mode, self.serial, 0x11, param, 2, int)
|
||
|
||
def set_High_Tt1_spinBox(self):
|
||
"""Установка длительности RR-интервала для определения события как тахикардии 1ст"""
|
||
param = self.High_Tt1_spinBox.value()
|
||
my_data.state_packet(self.send_mode, self.serial, 0x12, param, 2, int)
|
||
|
||
def set_f_count_spinBox(self):
|
||
"""Установка порога корзины фибрилляции"""
|
||
param = self.f_count_spinBox.value()
|
||
my_data.state_packet(self.send_mode, self.serial, 0x13, param, 1, int)
|
||
|
||
def set_hv_step_number_spinBox(self):
|
||
"""Установка количества ступеней BB - терапии"""
|
||
param = self.hv_step_number_spinBox.value()
|
||
my_data.state_packet(self.send_mode, self.serial, 0x14, param, 1, int)
|
||
|
||
def set_min_energy_spinBox(self):
|
||
"""Установка минимальной энергии стимулятора"""
|
||
param = self.min_energy_spinBox.value()
|
||
my_data.state_packet(self.send_mode, self.serial, 0x15, param, 2, int)
|
||
|
||
def set_max_energy_spinBox(self):
|
||
"""Установка максимальной энергии стимулятора"""
|
||
param = self.max_energy_spinBox.value()
|
||
my_data.state_packet(self.send_mode, self.serial, 0x16, param, 2, int)
|
||
|
||
def set_hv_blind_time_spinBox(self):
|
||
"""Установка времени слепоты после разряда"""
|
||
param = self.hv_blind_time_spinBox.value()
|
||
my_data.state_packet(self.send_mode, self.serial, 0x18, param, 2, int)
|
||
|
||
def set_standby_timer_spinBox(self):
|
||
"""Установка таймаута отключения"""
|
||
param = self.standby_timer_spinBox.value()
|
||
my_data.state_packet(self.send_mode, self.serial, 0x1B, param, 4, int)
|
||
|
||
def set_redet_num_spinBox(self):
|
||
"""Установка размера буффера редетекции"""
|
||
param = self.redet_num_spinBox.value()
|
||
my_data.state_packet(self.send_mode, self.serial, 0x19, param, 1, int)
|
||
|
||
def set_redet_bad_spinBox(self):
|
||
"""Установка порога буффера редетекции"""
|
||
param = self.redet_bad_spinBox.value()
|
||
my_data.state_packet(self.send_mode, self.serial, 0x1A, param, 1, int)
|
||
|
||
def set_fibr_cnt_max(self):
|
||
"""Визуализация корзины фибрилляции"""
|
||
# + отправить стимулятору
|
||
self.progressBar_f.setMaximum(self.f_count_spinBox.value())
|
||
|
||
def set_tachy_2_cnt_max(self):
|
||
"""Визуализация корзины тахикардии 2ст"""
|
||
self.progressBar_t2.setMaximum(self.t2_count_spinBox.value())
|
||
|
||
def set_tachy_1_cnt_max(self):
|
||
"""Визуализация корзины тахикардии 1ст"""
|
||
self.progressBar_t1.setMaximum(self.t1_count_spinBox.value())
|
||
|
||
def set_hv_polarity_BOX(self):
|
||
"""Выбор полярности"""
|
||
param = int(self.hv_polarity_BOX.currentIndex())
|
||
match param:
|
||
case 0:
|
||
self.picture_1.setVisible(True)
|
||
self.picture_2.setVisible(False)
|
||
self.picture_3.setVisible(False)
|
||
case 1:
|
||
self.picture_2.setVisible(True)
|
||
self.picture_1.setVisible(False)
|
||
self.picture_3.setVisible(False)
|
||
case 2:
|
||
self.picture_3.setVisible(True)
|
||
self.picture_1.setVisible(False)
|
||
self.picture_2.setVisible(False)
|
||
my_data.state_packet(self.send_mode, self.serial, 0x30, param, 1, int)
|
||
|
||
def set_hv_mode_BOX(self):
|
||
"""Выбор режима высоковольтной стимуляции"""
|
||
param = int(self.hv_mode_BOX.currentIndex())
|
||
match param:
|
||
case 0:
|
||
self.picture_4.setVisible(True)
|
||
self.picture_5.setVisible(False)
|
||
self.u1_hv_switching_voltage_l.setVisible(False)
|
||
self.u2_hv_cutoff_voltage_l.setVisible(False)
|
||
self.u1_hv_switching_voltage_spinBox.setVisible(False)
|
||
self.u2_hv_cutoff_voltage_spinBox.setVisible(False)
|
||
case 1:
|
||
self.picture_5.setVisible(True)
|
||
self.picture_4.setVisible(False)
|
||
self.u1_hv_switching_voltage_l.setVisible(True)
|
||
self.u2_hv_cutoff_voltage_l.setVisible(True)
|
||
self.u1_hv_switching_voltage_spinBox.setVisible(True)
|
||
self.u2_hv_cutoff_voltage_spinBox.setVisible(True)
|
||
my_data.state_packet(self.send_mode, self.serial, 0x31, param, 1, int)
|
||
|
||
def set_t1_hv_phase_1_duration_SpinBox(self):
|
||
"""Выбор времени положительной полуволны"""
|
||
param = int(self.t1_hv_phase_1_duration_SpinBox.value()*10)
|
||
my_data.state_packet(self.send_mode, self.serial, 0x32, param, 1, int)
|
||
|
||
def set_t2_hv_switch_duration_SpinBox(self):
|
||
"""Выбор времени задержки"""
|
||
param = int(self.t2_hv_switch_duration_SpinBox.value()*10)
|
||
my_data.state_packet(self.send_mode, self.serial, 0x34, param, 1, int)
|
||
|
||
def set_t3_hv_phase_2_duration_SpinBox(self):
|
||
"""Выбор времени отрицательной полуволны"""
|
||
param = int(self.t3_hv_phase_2_duration_SpinBox.value()*10)
|
||
my_data.state_packet(self.send_mode, self.serial, 0x33, param, 1, int)
|
||
|
||
def set_u1_hv_switching_voltage_spinBox(self):
|
||
"""Выбор процента от максимального напряжения для смены полярности"""
|
||
param = int(self.u1_hv_switching_voltage_spinBox.value())
|
||
my_data.state_packet(self.send_mode, self.serial, 0x35, param, 1, int)
|
||
|
||
def set_u2_hv_cutoff_voltage_spinBox(self):
|
||
"""Выбор процента от максимального напряжения для окончания стимуляции"""
|
||
param = int(self.u2_hv_cutoff_voltage_spinBox.value())
|
||
my_data.state_packet(self.send_mode, self.serial, 0x36, param, 1, int)
|
||
|
||
def set_lv_mode_BOX(self):
|
||
"""Выбор режима низковольтной стимуляции"""
|
||
param = self.lv_mode_BOX.currentIndex()
|
||
match param:
|
||
case 3:
|
||
self.burst_frame.setVisible(True)
|
||
case _:
|
||
self.burst_frame.setVisible(False)
|
||
my_data.state_packet(self.send_mode, self.serial, 0x23, param, 1, int)
|
||
|
||
|
||
def set_lv_polarity_BOX(self):
|
||
"""Выбор полярности для НВ"""
|
||
param = int(self.lv_polarity_BOX.currentIndex())
|
||
my_data.state_packet(self.send_mode, self.serial, 0x22, param, 1, int)
|
||
|
||
def set_u_lv_voltage_SpinBox(self):
|
||
"""Выбор напряжения НВ стимуляции"""
|
||
param = int(self.u_lv_voltage_SpinBox.value()*10)
|
||
my_data.state_packet(self.send_mode, self.serial, 0x26, param, 1, int)
|
||
|
||
def set_t1_lv_shock_time_SpinBox(self):
|
||
"""Выбор времени импульса НВ стимуляции"""
|
||
param = int(self.t1_lv_shock_time_SpinBox.value() * 10)
|
||
my_data.state_packet(self.send_mode, self.serial, 0x24, param, 1, int)
|
||
def set_t2_lv_relax_time_spinBox(self):
|
||
"""Выбор времени стабилизации после НВ стимуляции"""
|
||
param = int(self.t2_lv_relax_time_spinBox.value() * 10)
|
||
my_data.state_packet(self.send_mode, self.serial, 0x25, param, 1, int)
|
||
def set_burst_cnt_spinBox(self):
|
||
"""Выбор количества импульсов в пачке при НВ стимуляции"""
|
||
param = self.burst_cnt_spinBox.value()
|
||
my_data.state_packet(self.send_mode, self.serial, 0x27, param, 1, int)
|
||
def set_burst_voltage_SpinBox(self):
|
||
"""Выбор напряжения импульсов при НВ стимуляции"""
|
||
param = int(self.burst_voltage_SpinBox.value() * 10)
|
||
my_data.state_packet(self.send_mode, self.serial, 0x28, param, 1, int)
|
||
def set_burst_period_spinBox(self):
|
||
"""Выбор периода следования импульсов при НВ стимуляции"""
|
||
param = self.burst_period_spinBox.value()
|
||
my_data.state_packet(self.send_mode, self.serial, 0x29, param, 2, int) |