Лаба1
.docxМИНОБРНАУКИ РОССИИ
Санкт-Петербургский государственный
электротехнический университет
«ЛЭТИ» им. В.И. Ульянова (Ленина)
Кафедра БТС
отчет
по лабораторной работе №1
по дисциплине «Технологии автоматизации лечебного процесса»
Тема: Разработка базы данных для системы оценки состояния пациента методами ритмокардиографии
Студент гр. 7503 |
|
Исаков А.О. |
Преподаватель |
|
Садыкова Е.В. |
Санкт-Петербург
2022
Цель работы: разработка базы данных для системы помощи принятия решения врачу при оценке состояния здоровья пациента методами ритмокардиографии.
Задание:
Анализ предметной области;
Проектирование базы данных (БД) и создание структуры в SQLite (DB Browser);
Разработка интерфейса взаимодействия с БД в PyQT5 (Python 10.0)
ХОД ВЫПОЛНЕНИЯ РАБОТЫ
Анализ предметной области
Ритмокардиография – это метод оценки ритма сердца, основанный на графическом представлении последовательности значений длительности каридоцикла (RR-интервалов). Используются три вида графиков:
Ритмограмма – зависимость значений длительности RR-интервала от порядкового номера цикла измерения;
Гистограмма – относительное число RR-интервалов, относящихся к различным диапазонам значений их длительности;
Скаттерограмма – двумерное отображение ритма сердца, которое строится как совокупность точек, координаты каждой из которых на плоскости соответствуют величинам двух смежных RR-интервалов.
Для количественной оценки вариабельности сердечного ритма рассчитывается некоторые статистические показатели, в частности:
Среднее значение
Минимальное и максимальное значения
Вариационный размах
Мода
Амплитуда моды
Проектирование БД и создание структуры в SQLite
База данных SQLite разрабатывалась в приложении DB Browser. Она состоит из двух таблиц: users и diag (см. рисунок 1). Кроме этого, присутствует техническая таблица sqlite_sequence, содержащая общую информацию о наполнении БД (количество таблиц, ключевые поля, текущий номер счетчика id и т.д.).
Рисунок 1 – Структура базы данных
Таблица users содержит информацию о пользователе, которую врач ввел в форму: ФИО и возраст. Через ключевое поле id она соединяется с таблицей diag по user_id (см. рисунок 2). В таблице diag располагаются пути к файлам ритмограммы и поставленный врачом диагноз.
Рисунок 2 – Диаграмма базы данных
Поля id, user_id и age сохраняют данные в формате INTEGER. Прочие поля (name, file, diagnosis) сохраняют данные в формате TEXT.
Разработка интерфейса взаимодействия с БД в PyQT5
Разработанная программа позволяет врачу визуально оценить последовательности значений длительности каридоцикла (RR-интервалов) используя три вида графиков: ритмограмму (см. рисунок 3), гистограмму (см. рисунок 4) и скаттерограмму (см. рисунок 5).
Рисунок 3 – Экранный вид программы
На рисунке 3 изображено первоначальное рабочее поле врача. Здесь необходимо указать ФИО, возраст пациента и выбрать соответствующий ему сигнал. Врачебное заключение сохраняется при нажатии на кнопку «Записать» (см. рисунок 6,7).
Рисунок 4 – Гистограмма диапазонов значений длительности RR интервалов
Рисунок 5 – Скаттерограмма двух смежных RR интервалов
Рисунок 6 – Экранный вид окна статуса выполнения операции
Рисунок 7 – Экранный вид базы данных приложения
Все выставленные врачом диагнозы хранятся во вкладке «База данных». При необходимости через двойной клик можно повторно вызвать соответствующее исследование и отредактировать запись. Пользуясь элементами управления, записи можно удалять и перемещать относительно друг друга.
ТЕКСТ ПРОГРАММЫ
«mainF.py»
import sys
import os
import numpy as np
import sqlite3
import matplotlib
matplotlib.use('Qt5Agg')
import design
from design import Ui_MainWindow
from PyQt5 import QtWidgets
from PyQt5 import uic
from PyQt5.QtWidgets import QMainWindow, QApplication, QFileDialog, QMessageBox
from PyQt5.uic import loadUi
class RitmApp(QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
#loadUi("design.ui", self)
self.setupUi(self)
self.pushButton.clicked.connect(self.open_file)
self.pushButton_2.clicked.connect(self.addToDB)
self.tableWidget.setColumnWidth(0,160)
self.tableWidget.setColumnWidth(1,180)
self.tableWidget.setColumnWidth(2,251)
self.tabWidget.tabBarClicked.connect(self.getFromDB)
self.initialLoadFromDB()
def open_file(self):
path = QFileDialog.getOpenFileName(self, "Open", "", "txt Files (*.txt);;All Files (*)")
if path[0] != "":
data = np.genfromtxt(path[0])
self.lineEdit_5.setText(path[0])
self.MplWidget.axes.clear()
self.MplWidget.axes.stem(range(0,len(data)), data, markerfmt = "none")
self.MplWidget.axes.set_title('Ритмограмма')
self.MplWidget.axes.set_xlabel('RR')
self.MplWidget.axes.set_ylabel('R-R интервалы, сек')
self.MplWidget.canvas.draw()
self.MplWidget2.axes.clear()
self.MplWidget2.axes.hist(data)
self.MplWidget2.axes.set_title('Гистограмма')
self.MplWidget2.axes.set_xlabel('R-R интервалы, сек')
self.MplWidget2.axes.set_ylabel('Кол-во ед.')
self.MplWidget2.canvas.draw()
self.MplWidget3.axes.clear()
self.MplWidget3.axes.scatter(data[1:len(data)-1], data[2:len(data)])
self.MplWidget3.axes.set_title('Скаттерограмма')
self.MplWidget3.axes.set_xlabel('RR(1:L-1)')
self.MplWidget3.axes.set_ylabel('RR(2:L)')
self.MplWidget3.canvas.draw()
def addToDB(self):
path = os.path.dirname(os.path.abspath(__file__))
db = os.path.join(path, 'ritmogramma.db')
con = sqlite3.connect(db)
cur = con.cursor()
cur.execute("""INSERT INTO users (name,age,file,diagnosis)
VALUES (?,?,?,?)""",
(self.lineEdit.text()+" "+self.lineEdit_2.text()+" "+self.lineEdit_3.text(),
self.lineEdit_4.text(),self.lineEdit_5.text(),self.lineEdit_6.text()))
con.commit()
con.close()
QMessageBox.about(self, "Статус выполнения операции", "Успешно сохранено")
def getFromDB(self, tabIndex):
if tabIndex == 1:
path = os.path.dirname(os.path.abspath(__file__))
db = os.path.join(path, 'ritmogramma.db')
con = sqlite3.connect(db)
cur = con.cursor()
cur.execute("""SELECT name, age, file, diagnosis FROM users""")
res = cur.fetchall()
con.close()
tableRow = 0
self.tableWidget.setRowCount(len(res))
for row in res:
self.tableWidget.setItem(tableRow, 0, QtWidgets.QTableWidgetItem(f"{row[0]}, {row[1]}"))
self.tableWidget.setItem(tableRow, 1, QtWidgets.QTableWidgetItem(row[3]))
self.tableWidget.setItem(tableRow, 2, QtWidgets.QTableWidgetItem(row[2]))
tableRow += 1
def initialLoadFromDB(self):
path1 = __file__
path = os.path.dirname(os.path.abspath(__file__))
db = os.path.join(path, 'ritmogramma.db')
con = sqlite3.connect(db)
cur = con.cursor()
cur.execute("""SELECT name, age, file, diagnosis FROM users""")
res = cur.fetchall()
con.close()
tableRow = 0
self.tableWidget.setRowCount(len(res))
for row in res:
self.tableWidget.setItem(tableRow, 0, QtWidgets.QTableWidgetItem(f"{row[0]}, {row[1]}"))
self.tableWidget.setItem(tableRow, 1, QtWidgets.QTableWidgetItem(row[3]))
self.tableWidget.setItem(tableRow, 2, QtWidgets.QTableWidgetItem(row[2]))
tableRow += 1
if __name__ == '__main__':
app = QApplication(sys.argv)
window = RitmApp()
window.show()
sys.exit(app.exec_())
«mplwidget.py»
from PyQt5.QtWidgets import QWidget, QVBoxLayout
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
class MplWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.canvas = FigureCanvas(Figure())
self.axes = self.canvas.figure.add_subplot(111)
layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self.canvas)
self.setLayout(layout)