2025-09-26 16:43:46 +03:00

878 lines
43 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Отображение данных"""
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 mes1, mes2, mes3
# выбор режима чения из файла или из 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.Psense_period_spinBox.valueChanged.connect(self.set_Psense_period_spinBox)
self.Post_pace_block_period_spinBox.valueChanged.connect(self.set_Post_pace_block_period_spinBox)
self.Post_pace_amplitude_SpinBox.valueChanged.connect(self.set_Post_pace_amplitude_SpinBox)
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.burst_end_period_spinBox.valueChanged.connect(self.set_burst_end_period_spinBox)
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)
self.burst_frame.setVisible(True)
self.HV_Box.currentIndexChanged.connect(self.set_HV_Box)
self.LV_Box.currentIndexChanged.connect(self.set_LV_Box)
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)
# Создание таймера для отображения зарядки конденсатора
self.timer_charge = QtCore.QTimer()
self.timer_charge.timeout.connect(self.timerEvent_charge)
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 timerEvent_charge(self):
if MODE_COM_PORT:
self.draw_charge(data_IN_COM)
if MODE_FILE:
self.draw_charge(data_IN_FILE)
app.processEvents()
def draw_charge(self, data_in):
self.text = pg.TextItem('*')
self.text.setColor('red')
self.text.setFont(QFont('Arial', 20))
self.text.setPos(data_in.draw_cnt / my_data.DATA_RATE, (0.05 if data_in.dc_cut else 16))
self.graph_1.addItem(self.text)
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.setCurrentIndex(data_in.hv_polarity)
self.hv_mode_BOX.setCurrentIndex(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.setCurrentIndex(data_in.lv_polarity)
self.lv_mode_BOX.setCurrentIndex(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_spinBox.setValue(data_in.burst_period)
self.burst_end_period_spinBox.setValue(data_in.burst_end_period)
self.Psense_period_spinBox.setValue(data_in.Psense_period)
self.Post_pace_block_period_spinBox.setValue(data_in.post_pace_block_period)
self.Post_pace_amplitude_SpinBox.setValue(data_in.post_pace_amplitude)
self.HV_Box.setCurrentIndex(int(data_in.hv))
self.LV_Box.setCurrentIndex(int(data_in.lv))
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()
if self.device.currentIndex() == 0:
self.serial.write(mes1.encode())
if self.device.currentIndex() == 1:
self.serial.write(mes2.encode())
if self.device.currentIndex() == 2:
self.serial.write(mes3.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()
self.U_cap_max = 0
self.timer_charge.start(100)
if data_in.sub_mode == 1 and self.sub_mode_previous == 1:
self.end_time_charging = time.time()
if data_in.sub_mode != 1 and self.sub_mode_previous == 1:
self.timer_charge.stop()
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)
if data_in.draw_last_QRS == 2:
self.text = pg.TextItem('Vn\nT:' + str(data_in.draw_last_period))
self.text.setColor('blue')
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)
self.device.setVisible(True)
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)
self.device.setVisible(False)
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)
case 1:
self.picture_5.setVisible(True)
self.picture_4.setVisible(False)
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()
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())
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)
def set_burst_end_period_spinBox(self):
"""Выбор периода следования импульсов при НВ стимуляции"""
param = self.burst_end_period_spinBox.value()
my_data.state_packet(self.send_mode, self.serial, 0x37, param, 2, int)
def set_Psense_period_spinBox(self):
"""Выбор длительность поиска события после Vp, мс"""
param = int(self.Psense_period_spinBox.value())
my_data.state_packet(self.send_mode, self.serial, 0x00, param, 2, int)
def set_Post_pace_block_period_spinBox(self):
"""Выбор времени слепоты после Vp, мс """
param = int(self.Post_pace_block_period_spinBox.value())
my_data.state_packet(self.send_mode, self.serial, 0x00, param, 2, int)
def set_Post_pace_amplitude_SpinBox(self):
"""Выбор амплитуды сигнала после Vp, мВ"""
param = int(self.Post_pace_amplitude_SpinBox.value())
my_data.state_packet(self.send_mode, self.serial, 0x00, param, 1, int)
def set_HV_Box(self):
"""Настройка активации режима высоковольтной стимуляции"""
param = int(self.HV_Box.currentIndex())
my_data.state_packet(self.send_mode, self.serial, 0x0F, param, 1, int)
def set_LV_Box(self):
"""Настройка активации режима низковольтной стимуляции"""
param = int(self.LV_Box.currentIndex())
my_data.state_packet(self.send_mode, self.serial, 0x0E, param, 1, int)