initial commit

This commit is contained in:
Yorusora 2025-01-04 17:33:28 +08:00
commit 54f8cc79f6
6 changed files with 4025 additions and 0 deletions

259
.gitignore vendored Normal file
View File

@ -0,0 +1,259 @@
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# ---> JetBrains
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
# ---> JupyterNotebooks
# gitignore template for Jupyter Notebooks
# website: http://jupyter.org/
.ipynb_checkpoints
*/.ipynb_checkpoints/*
# IPython
profile_default/
ipython_config.py
# Remove previous ipynb_checkpoints
# git rm -r .ipynb_checkpoints/
!data
!history
data/*
history/*
.idea/*

781
MainWindow.py Normal file
View File

@ -0,0 +1,781 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'MainWindow.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1920, 1080)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.verticalLayout_left = QtWidgets.QVBoxLayout()
self.verticalLayout_left.setObjectName("verticalLayout_left")
self.groupBox_1 = QtWidgets.QGroupBox(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.groupBox_1.sizePolicy().hasHeightForWidth())
self.groupBox_1.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(10)
self.groupBox_1.setFont(font)
self.groupBox_1.setObjectName("groupBox_1")
self.gridLayout_4 = QtWidgets.QGridLayout(self.groupBox_1)
self.gridLayout_4.setObjectName("gridLayout_4")
self.comboBox_sampID = QtWidgets.QComboBox(self.groupBox_1)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.comboBox_sampID.sizePolicy().hasHeightForWidth())
self.comboBox_sampID.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.comboBox_sampID.setFont(font)
self.comboBox_sampID.setObjectName("comboBox_sampID")
self.gridLayout_4.addWidget(self.comboBox_sampID, 2, 1, 1, 1)
self.lineEdit_start_bcg_index = QtWidgets.QLineEdit(self.groupBox_1)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lineEdit_start_bcg_index.sizePolicy().hasHeightForWidth())
self.lineEdit_start_bcg_index.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.lineEdit_start_bcg_index.setFont(font)
self.lineEdit_start_bcg_index.setObjectName("lineEdit_start_bcg_index")
self.gridLayout_4.addWidget(self.lineEdit_start_bcg_index, 2, 3, 1, 1)
self.label_start_bcg_index = QtWidgets.QLabel(self.groupBox_1)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.label_start_bcg_index.setFont(font)
self.label_start_bcg_index.setObjectName("label_start_bcg_index")
self.gridLayout_4.addWidget(self.label_start_bcg_index, 2, 2, 1, 1)
self.label_sampID = QtWidgets.QLabel(self.groupBox_1)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.label_sampID.setFont(font)
self.label_sampID.setObjectName("label_sampID")
self.gridLayout_4.addWidget(self.label_sampID, 2, 0, 1, 1)
self.verticalLayout_left.addWidget(self.groupBox_1)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout_left.addItem(spacerItem)
self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.groupBox_2.sizePolicy().hasHeightForWidth())
self.groupBox_2.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(10)
self.groupBox_2.setFont(font)
self.groupBox_2.setObjectName("groupBox_2")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.groupBox_2)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.checkBox_OSA = QtWidgets.QCheckBox(self.groupBox_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.checkBox_OSA.sizePolicy().hasHeightForWidth())
self.checkBox_OSA.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.checkBox_OSA.setFont(font)
self.checkBox_OSA.setChecked(True)
self.checkBox_OSA.setObjectName("checkBox_OSA")
self.horizontalLayout_2.addWidget(self.checkBox_OSA)
self.checkBox_CSA = QtWidgets.QCheckBox(self.groupBox_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.checkBox_CSA.sizePolicy().hasHeightForWidth())
self.checkBox_CSA.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.checkBox_CSA.setFont(font)
self.checkBox_CSA.setChecked(True)
self.checkBox_CSA.setObjectName("checkBox_CSA")
self.horizontalLayout_2.addWidget(self.checkBox_CSA)
self.checkBox_MSA = QtWidgets.QCheckBox(self.groupBox_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.checkBox_MSA.sizePolicy().hasHeightForWidth())
self.checkBox_MSA.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.checkBox_MSA.setFont(font)
self.checkBox_MSA.setChecked(True)
self.checkBox_MSA.setObjectName("checkBox_MSA")
self.horizontalLayout_2.addWidget(self.checkBox_MSA)
self.checkBox_HPY = QtWidgets.QCheckBox(self.groupBox_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.checkBox_HPY.sizePolicy().hasHeightForWidth())
self.checkBox_HPY.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.checkBox_HPY.setFont(font)
self.checkBox_HPY.setChecked(True)
self.checkBox_HPY.setObjectName("checkBox_HPY")
self.horizontalLayout_2.addWidget(self.checkBox_HPY)
self.verticalLayout_left.addWidget(self.groupBox_2)
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout_left.addItem(spacerItem1)
self.groupBox_3 = QtWidgets.QGroupBox(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.groupBox_3.sizePolicy().hasHeightForWidth())
self.groupBox_3.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(10)
self.groupBox_3.setFont(font)
self.groupBox_3.setObjectName("groupBox_3")
self.gridLayout_5 = QtWidgets.QGridLayout(self.groupBox_3)
self.gridLayout_5.setObjectName("gridLayout_5")
self.label_frequency = QtWidgets.QLabel(self.groupBox_3)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_frequency.sizePolicy().hasHeightForWidth())
self.label_frequency.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.label_frequency.setFont(font)
self.label_frequency.setObjectName("label_frequency")
self.gridLayout_5.addWidget(self.label_frequency, 0, 0, 1, 1)
self.lineEdit_frequency = QtWidgets.QLineEdit(self.groupBox_3)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lineEdit_frequency.sizePolicy().hasHeightForWidth())
self.lineEdit_frequency.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.lineEdit_frequency.setFont(font)
self.lineEdit_frequency.setObjectName("lineEdit_frequency")
self.gridLayout_5.addWidget(self.lineEdit_frequency, 0, 1, 1, 1)
self.label_bcg_frequency = QtWidgets.QLabel(self.groupBox_3)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.label_bcg_frequency.setFont(font)
self.label_bcg_frequency.setObjectName("label_bcg_frequency")
self.gridLayout_5.addWidget(self.label_bcg_frequency, 1, 0, 1, 1)
self.lineEdit_bcg_frequency = QtWidgets.QLineEdit(self.groupBox_3)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lineEdit_bcg_frequency.sizePolicy().hasHeightForWidth())
self.lineEdit_bcg_frequency.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.lineEdit_bcg_frequency.setFont(font)
self.lineEdit_bcg_frequency.setObjectName("lineEdit_bcg_frequency")
self.gridLayout_5.addWidget(self.lineEdit_bcg_frequency, 1, 1, 1, 1)
self.label_front_add_second = QtWidgets.QLabel(self.groupBox_3)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.label_front_add_second.setFont(font)
self.label_front_add_second.setObjectName("label_front_add_second")
self.gridLayout_5.addWidget(self.label_front_add_second, 2, 0, 1, 1)
self.lineEdit_front_add_second = QtWidgets.QLineEdit(self.groupBox_3)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lineEdit_front_add_second.sizePolicy().hasHeightForWidth())
self.lineEdit_front_add_second.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.lineEdit_front_add_second.setFont(font)
self.lineEdit_front_add_second.setObjectName("lineEdit_front_add_second")
self.gridLayout_5.addWidget(self.lineEdit_front_add_second, 2, 1, 1, 1)
self.label_back_add_second = QtWidgets.QLabel(self.groupBox_3)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.label_back_add_second.setFont(font)
self.label_back_add_second.setObjectName("label_back_add_second")
self.gridLayout_5.addWidget(self.label_back_add_second, 3, 0, 1, 1)
self.lineEdit_back_add_second = QtWidgets.QLineEdit(self.groupBox_3)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lineEdit_back_add_second.sizePolicy().hasHeightForWidth())
self.lineEdit_back_add_second.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.lineEdit_back_add_second.setFont(font)
self.lineEdit_back_add_second.setObjectName("lineEdit_back_add_second")
self.gridLayout_5.addWidget(self.lineEdit_back_add_second, 3, 1, 1, 1)
self.verticalLayout_left.addWidget(self.groupBox_3)
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout_left.addItem(spacerItem2)
self.groupBox_4 = QtWidgets.QGroupBox(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.groupBox_4.sizePolicy().hasHeightForWidth())
self.groupBox_4.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(10)
self.groupBox_4.setFont(font)
self.groupBox_4.setObjectName("groupBox_4")
self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox_4)
self.gridLayout_2.setObjectName("gridLayout_2")
self.lineEdit_remark = QtWidgets.QLineEdit(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lineEdit_remark.sizePolicy().hasHeightForWidth())
self.lineEdit_remark.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.lineEdit_remark.setFont(font)
self.lineEdit_remark.setObjectName("lineEdit_remark")
self.gridLayout_2.addWidget(self.lineEdit_remark, 5, 2, 1, 3)
self.pushButton_left = QtWidgets.QPushButton(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton_left.sizePolicy().hasHeightForWidth())
self.pushButton_left.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.pushButton_left.setFont(font)
self.pushButton_left.setObjectName("pushButton_left")
self.gridLayout_2.addWidget(self.pushButton_left, 15, 0, 1, 1)
self.lineEdit_correctStart = QtWidgets.QLineEdit(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lineEdit_correctStart.sizePolicy().hasHeightForWidth())
self.lineEdit_correctStart.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.lineEdit_correctStart.setFont(font)
self.lineEdit_correctStart.setObjectName("lineEdit_correctStart")
self.gridLayout_2.addWidget(self.lineEdit_correctStart, 7, 2, 1, 3)
self.label_correctStart = QtWidgets.QLabel(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_correctStart.sizePolicy().hasHeightForWidth())
self.label_correctStart.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.label_correctStart.setFont(font)
self.label_correctStart.setObjectName("label_correctStart")
self.gridLayout_2.addWidget(self.label_correctStart, 7, 0, 1, 1)
self.checkBox_examineLabeled = QtWidgets.QCheckBox(self.groupBox_4)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.checkBox_examineLabeled.setFont(font)
self.checkBox_examineLabeled.setObjectName("checkBox_examineLabeled")
self.gridLayout_2.addWidget(self.checkBox_examineLabeled, 0, 0, 1, 4)
self.label_quick_remark_input = QtWidgets.QLabel(self.groupBox_4)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.label_quick_remark_input.setFont(font)
self.label_quick_remark_input.setObjectName("label_quick_remark_input")
self.gridLayout_2.addWidget(self.label_quick_remark_input, 6, 0, 1, 1)
self.lineEdit_correctEnd = QtWidgets.QLineEdit(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lineEdit_correctEnd.sizePolicy().hasHeightForWidth())
self.lineEdit_correctEnd.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.lineEdit_correctEnd.setFont(font)
self.lineEdit_correctEnd.setObjectName("lineEdit_correctEnd")
self.gridLayout_2.addWidget(self.lineEdit_correctEnd, 9, 2, 1, 3)
self.label_correctEnd = QtWidgets.QLabel(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_correctEnd.sizePolicy().hasHeightForWidth())
self.label_correctEnd.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.label_correctEnd.setFont(font)
self.label_correctEnd.setObjectName("label_correctEnd")
self.gridLayout_2.addWidget(self.label_correctEnd, 9, 0, 1, 1)
self.label_BCG_event = QtWidgets.QLabel(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_BCG_event.sizePolicy().hasHeightForWidth())
self.label_BCG_event.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(12)
font.setBold(False)
font.setWeight(50)
self.label_BCG_event.setFont(font)
self.label_BCG_event.setText("")
self.label_BCG_event.setAlignment(QtCore.Qt.AlignCenter)
self.label_BCG_event.setObjectName("label_BCG_event")
self.gridLayout_2.addWidget(self.label_BCG_event, 2, 0, 1, 5)
self.pushButton_quick_remark_input_waitingForTalk = QtWidgets.QPushButton(self.groupBox_4)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.pushButton_quick_remark_input_waitingForTalk.setFont(font)
self.pushButton_quick_remark_input_waitingForTalk.setObjectName("pushButton_quick_remark_input_waitingForTalk")
self.gridLayout_2.addWidget(self.pushButton_quick_remark_input_waitingForTalk, 6, 2, 1, 3)
self.horizontalLayout_radioButton = QtWidgets.QHBoxLayout()
self.horizontalLayout_radioButton.setObjectName("horizontalLayout_radioButton")
self.label_events = QtWidgets.QLabel(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_events.sizePolicy().hasHeightForWidth())
self.label_events.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(14)
self.label_events.setFont(font)
self.label_events.setObjectName("label_events")
self.horizontalLayout_radioButton.addWidget(self.label_events)
self.radioButton_OSA = QtWidgets.QRadioButton(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.radioButton_OSA.sizePolicy().hasHeightForWidth())
self.radioButton_OSA.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(14)
self.radioButton_OSA.setFont(font)
self.radioButton_OSA.setObjectName("radioButton_OSA")
self.horizontalLayout_radioButton.addWidget(self.radioButton_OSA)
self.radioButton_CSA = QtWidgets.QRadioButton(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.radioButton_CSA.sizePolicy().hasHeightForWidth())
self.radioButton_CSA.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(14)
self.radioButton_CSA.setFont(font)
self.radioButton_CSA.setObjectName("radioButton_CSA")
self.horizontalLayout_radioButton.addWidget(self.radioButton_CSA)
self.radioButton_MSA = QtWidgets.QRadioButton(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.radioButton_MSA.sizePolicy().hasHeightForWidth())
self.radioButton_MSA.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(14)
self.radioButton_MSA.setFont(font)
self.radioButton_MSA.setObjectName("radioButton_MSA")
self.horizontalLayout_radioButton.addWidget(self.radioButton_MSA)
self.radioButton_HPY = QtWidgets.QRadioButton(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.radioButton_HPY.sizePolicy().hasHeightForWidth())
self.radioButton_HPY.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(14)
self.radioButton_HPY.setFont(font)
self.radioButton_HPY.setObjectName("radioButton_HPY")
self.horizontalLayout_radioButton.addWidget(self.radioButton_HPY)
self.gridLayout_2.addLayout(self.horizontalLayout_radioButton, 3, 0, 1, 5)
self.label_PSG_event = QtWidgets.QLabel(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_PSG_event.sizePolicy().hasHeightForWidth())
self.label_PSG_event.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(12)
font.setBold(False)
font.setWeight(50)
self.label_PSG_event.setFont(font)
self.label_PSG_event.setText("")
self.label_PSG_event.setAlignment(QtCore.Qt.AlignCenter)
self.label_PSG_event.setObjectName("label_PSG_event")
self.gridLayout_2.addWidget(self.label_PSG_event, 1, 0, 1, 5)
self.label_remark = QtWidgets.QLabel(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_remark.sizePolicy().hasHeightForWidth())
self.label_remark.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.label_remark.setFont(font)
self.label_remark.setObjectName("label_remark")
self.gridLayout_2.addWidget(self.label_remark, 5, 0, 1, 1)
self.pushButton_right = QtWidgets.QPushButton(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton_right.sizePolicy().hasHeightForWidth())
self.pushButton_right.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.pushButton_right.setFont(font)
self.pushButton_right.setObjectName("pushButton_right")
self.gridLayout_2.addWidget(self.pushButton_right, 16, 0, 1, 1)
self.horizontalLayout_12 = QtWidgets.QHBoxLayout()
self.horizontalLayout_12.setObjectName("horizontalLayout_12")
self.label_score = QtWidgets.QLabel(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_score.sizePolicy().hasHeightForWidth())
self.label_score.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.label_score.setFont(font)
self.label_score.setObjectName("label_score")
self.horizontalLayout_12.addWidget(self.label_score)
self.radioButton_1_class = QtWidgets.QRadioButton(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.radioButton_1_class.sizePolicy().hasHeightForWidth())
self.radioButton_1_class.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.radioButton_1_class.setFont(font)
self.radioButton_1_class.setObjectName("radioButton_1_class")
self.horizontalLayout_12.addWidget(self.radioButton_1_class)
self.radioButton_2_class = QtWidgets.QRadioButton(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.radioButton_2_class.sizePolicy().hasHeightForWidth())
self.radioButton_2_class.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.radioButton_2_class.setFont(font)
self.radioButton_2_class.setObjectName("radioButton_2_class")
self.horizontalLayout_12.addWidget(self.radioButton_2_class)
self.radioButton_3_class = QtWidgets.QRadioButton(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.radioButton_3_class.sizePolicy().hasHeightForWidth())
self.radioButton_3_class.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(14)
self.radioButton_3_class.setFont(font)
self.radioButton_3_class.setObjectName("radioButton_3_class")
self.horizontalLayout_12.addWidget(self.radioButton_3_class)
self.gridLayout_2.addLayout(self.horizontalLayout_12, 4, 0, 1, 5)
self.pushButton_confirmLabel = QtWidgets.QPushButton(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton_confirmLabel.sizePolicy().hasHeightForWidth())
self.pushButton_confirmLabel.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(14)
self.pushButton_confirmLabel.setFont(font)
self.pushButton_confirmLabel.setObjectName("pushButton_confirmLabel")
self.gridLayout_2.addWidget(self.pushButton_confirmLabel, 15, 2, 2, 3)
spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_2.addItem(spacerItem3, 16, 1, 1, 1)
spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_2.addItem(spacerItem4, 15, 1, 1, 1)
self.verticalLayout_left.addWidget(self.groupBox_4)
spacerItem5 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout_left.addItem(spacerItem5)
self.groupBox_5 = QtWidgets.QGroupBox(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.groupBox_5.sizePolicy().hasHeightForWidth())
self.groupBox_5.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(10)
self.groupBox_5.setFont(font)
self.groupBox_5.setObjectName("groupBox_5")
self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBox_5)
self.gridLayout_3.setObjectName("gridLayout_3")
self.pushButton_next10s = QtWidgets.QPushButton(self.groupBox_5)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton_next10s.sizePolicy().hasHeightForWidth())
self.pushButton_next10s.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(14)
self.pushButton_next10s.setFont(font)
self.pushButton_next10s.setObjectName("pushButton_next10s")
self.gridLayout_3.addWidget(self.pushButton_next10s, 1, 2, 1, 1)
self.pushButton_previous10s = QtWidgets.QPushButton(self.groupBox_5)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton_previous10s.sizePolicy().hasHeightForWidth())
self.pushButton_previous10s.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(14)
self.pushButton_previous10s.setFont(font)
self.pushButton_previous10s.setObjectName("pushButton_previous10s")
self.gridLayout_3.addWidget(self.pushButton_previous10s, 1, 0, 1, 1)
self.pushButton_next30s = QtWidgets.QPushButton(self.groupBox_5)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton_next30s.sizePolicy().hasHeightForWidth())
self.pushButton_next30s.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(14)
self.pushButton_next30s.setFont(font)
self.pushButton_next30s.setObjectName("pushButton_next30s")
self.gridLayout_3.addWidget(self.pushButton_next30s, 2, 2, 1, 1)
self.pushButton_next60s = QtWidgets.QPushButton(self.groupBox_5)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton_next60s.sizePolicy().hasHeightForWidth())
self.pushButton_next60s.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(14)
self.pushButton_next60s.setFont(font)
self.pushButton_next60s.setObjectName("pushButton_next60s")
self.gridLayout_3.addWidget(self.pushButton_next60s, 3, 2, 1, 1)
self.pushButton_previous60s = QtWidgets.QPushButton(self.groupBox_5)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton_previous60s.sizePolicy().hasHeightForWidth())
self.pushButton_previous60s.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(14)
self.pushButton_previous60s.setFont(font)
self.pushButton_previous60s.setObjectName("pushButton_previous60s")
self.gridLayout_3.addWidget(self.pushButton_previous60s, 3, 0, 1, 1)
self.pushButton_previous30s = QtWidgets.QPushButton(self.groupBox_5)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton_previous30s.sizePolicy().hasHeightForWidth())
self.pushButton_previous30s.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(14)
self.pushButton_previous30s.setFont(font)
self.pushButton_previous30s.setObjectName("pushButton_previous30s")
self.gridLayout_3.addWidget(self.pushButton_previous30s, 2, 0, 1, 1)
spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_3.addItem(spacerItem6, 1, 1, 1, 1)
spacerItem7 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_3.addItem(spacerItem7, 2, 1, 1, 1)
spacerItem8 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_3.addItem(spacerItem8, 3, 1, 1, 1)
self.checkBox_examineBySecond = QtWidgets.QCheckBox(self.groupBox_5)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(14)
self.checkBox_examineBySecond.setFont(font)
self.checkBox_examineBySecond.setObjectName("checkBox_examineBySecond")
self.gridLayout_3.addWidget(self.checkBox_examineBySecond, 0, 0, 1, 2)
self.gridLayout_3.setColumnStretch(0, 2)
self.gridLayout_3.setColumnStretch(1, 1)
self.gridLayout_3.setColumnStretch(2, 2)
self.verticalLayout_left.addWidget(self.groupBox_5)
spacerItem9 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout_left.addItem(spacerItem9)
self.groupBox_6 = QtWidgets.QGroupBox(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.groupBox_6.sizePolicy().hasHeightForWidth())
self.groupBox_6.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(10)
self.groupBox_6.setFont(font)
self.groupBox_6.setObjectName("groupBox_6")
self.gridLayout_6 = QtWidgets.QGridLayout(self.groupBox_6)
self.gridLayout_6.setObjectName("gridLayout_6")
self.textBrowser_infoOutput = QtWidgets.QTextBrowser(self.groupBox_6)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(10)
self.textBrowser_infoOutput.setFont(font)
self.textBrowser_infoOutput.setObjectName("textBrowser_infoOutput")
self.gridLayout_6.addWidget(self.textBrowser_infoOutput, 0, 0, 1, 1)
self.verticalLayout_left.addWidget(self.groupBox_6)
self.verticalLayout_left.setStretch(0, 3)
self.verticalLayout_left.setStretch(1, 1)
self.verticalLayout_left.setStretch(2, 3)
self.verticalLayout_left.setStretch(3, 1)
self.verticalLayout_left.setStretch(4, 8)
self.verticalLayout_left.setStretch(5, 1)
self.verticalLayout_left.setStretch(6, 30)
self.verticalLayout_left.setStretch(7, 1)
self.verticalLayout_left.setStretch(8, 12)
self.verticalLayout_left.setStretch(9, 1)
self.verticalLayout_left.setStretch(10, 12)
self.horizontalLayout.addLayout(self.verticalLayout_left)
self.verticalLayout_canvas = QtWidgets.QVBoxLayout()
self.verticalLayout_canvas.setObjectName("verticalLayout_canvas")
self.horizontalLayout.addLayout(self.verticalLayout_canvas)
self.horizontalLayout.setStretch(0, 3)
self.horizontalLayout.setStretch(1, 20)
self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 3, 2)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1920, 23))
self.menubar.setObjectName("menubar")
self.menu = QtWidgets.QMenu(self.menubar)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(14)
self.menu.setFont(font)
self.menu.setObjectName("menu")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.action_selectPath = QtWidgets.QAction(MainWindow)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(14)
self.action_selectPath.setFont(font)
self.action_selectPath.setObjectName("action_selectPath")
self.action = QtWidgets.QAction(MainWindow)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(14)
self.action.setFont(font)
self.action.setObjectName("action")
self.menu.addAction(self.action_selectPath)
self.menubar.addAction(self.menu.menuAction())
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Main_Quality_Relabel_GUI"))
self.groupBox_1.setTitle(_translate("MainWindow", "样本ID和起始心晓事件"))
self.lineEdit_start_bcg_index.setText(_translate("MainWindow", "0"))
self.lineEdit_start_bcg_index.setPlaceholderText(_translate("MainWindow", "从第几个心晓事件数量开始"))
self.label_start_bcg_index.setText(_translate("MainWindow", "起始心晓事件"))
self.label_sampID.setText(_translate("MainWindow", "样本ID"))
self.groupBox_2.setTitle(_translate("MainWindow", "事件类型选择"))
self.checkBox_OSA.setText(_translate("MainWindow", "OSA"))
self.checkBox_CSA.setText(_translate("MainWindow", "CSA"))
self.checkBox_MSA.setText(_translate("MainWindow", "MSA"))
self.checkBox_HPY.setText(_translate("MainWindow", "HPY"))
self.groupBox_3.setTitle(_translate("MainWindow", "参数设置(一般无需修改)"))
self.label_frequency.setText(_translate("MainWindow", "绘图采样率(Hz)"))
self.lineEdit_frequency.setText(_translate("MainWindow", "100"))
self.lineEdit_frequency.setPlaceholderText(_translate("MainWindow", "绘图时的采样率"))
self.label_bcg_frequency.setText(_translate("MainWindow", "心晓信号采样率(Hz)"))
self.lineEdit_bcg_frequency.setText(_translate("MainWindow", "1000"))
self.lineEdit_bcg_frequency.setPlaceholderText(_translate("MainWindow", "心晓数据采样率"))
self.label_front_add_second.setText(_translate("MainWindow", "信号向前扩展(s)"))
self.lineEdit_front_add_second.setText(_translate("MainWindow", "60"))
self.lineEdit_front_add_second.setPlaceholderText(_translate("MainWindow", "信号显示事件前多少秒"))
self.label_back_add_second.setText(_translate("MainWindow", "信号向后扩展(s)"))
self.lineEdit_back_add_second.setText(_translate("MainWindow", "60"))
self.lineEdit_back_add_second.setPlaceholderText(_translate("MainWindow", "信号显示事件后多少秒"))
self.groupBox_4.setTitle(_translate("MainWindow", "打标操作"))
self.pushButton_left.setText(_translate("MainWindow", "上一个事件(A)"))
self.pushButton_left.setShortcut(_translate("MainWindow", "A"))
self.label_correctStart.setText(_translate("MainWindow", "修正后起始时间(s)"))
self.checkBox_examineLabeled.setText(_translate("MainWindow", "仅检查未确定打标参数的事件"))
self.label_quick_remark_input.setText(_translate("MainWindow", "快速备注输入"))
self.label_correctEnd.setText(_translate("MainWindow", "修正后终止时间(s)"))
self.pushButton_quick_remark_input_waitingForTalk.setText(_translate("MainWindow", "待讨论(J)"))
self.pushButton_quick_remark_input_waitingForTalk.setShortcut(_translate("MainWindow", "J"))
self.label_events.setText(_translate("MainWindow", "事件类型"))
self.radioButton_OSA.setText(_translate("MainWindow", "OSA"))
self.radioButton_OSA.setShortcut(_translate("MainWindow", "1"))
self.radioButton_CSA.setText(_translate("MainWindow", "CSA"))
self.radioButton_CSA.setShortcut(_translate("MainWindow", "2"))
self.radioButton_MSA.setText(_translate("MainWindow", "MSA"))
self.radioButton_MSA.setShortcut(_translate("MainWindow", "3"))
self.radioButton_HPY.setText(_translate("MainWindow", "HPY"))
self.radioButton_HPY.setShortcut(_translate("MainWindow", "4"))
self.label_remark.setText(_translate("MainWindow", "备注"))
self.pushButton_right.setText(_translate("MainWindow", "下一个事件(D)"))
self.pushButton_right.setShortcut(_translate("MainWindow", "D"))
self.label_score.setText(_translate("MainWindow", "标签类型"))
self.radioButton_1_class.setText(_translate("MainWindow", "一类(U)"))
self.radioButton_1_class.setShortcut(_translate("MainWindow", "U"))
self.radioButton_2_class.setText(_translate("MainWindow", "二类(I)"))
self.radioButton_2_class.setShortcut(_translate("MainWindow", "I"))
self.radioButton_3_class.setText(_translate("MainWindow", "删除(O)"))
self.radioButton_3_class.setShortcut(_translate("MainWindow", "O"))
self.pushButton_confirmLabel.setText(_translate("MainWindow", "确定打标参数(S)"))
self.groupBox_5.setTitle(_translate("MainWindow", "逐帧检查"))
self.pushButton_next10s.setText(_translate("MainWindow", "+10s"))
self.pushButton_previous10s.setText(_translate("MainWindow", "-10s"))
self.pushButton_next30s.setText(_translate("MainWindow", "+30s"))
self.pushButton_next60s.setText(_translate("MainWindow", "+60s"))
self.pushButton_previous60s.setText(_translate("MainWindow", "-60s"))
self.pushButton_previous30s.setText(_translate("MainWindow", "-30s"))
self.checkBox_examineBySecond.setText(_translate("MainWindow", "启用逐帧检查模式"))
self.groupBox_6.setTitle(_translate("MainWindow", "信息输出"))
self.menu.setTitle(_translate("MainWindow", "打开"))
self.action_selectPath.setText(_translate("MainWindow", "数据路径选择"))
self.action.setText(_translate("MainWindow", "加载存档"))

1229
MainWindow.ui Normal file

File diff suppressed because it is too large Load Diff

1107
Main_Quality_Relabel_GUI.py Normal file

File diff suppressed because it is too large Load Diff

179
utils/Preprocessing.py Normal file
View File

@ -0,0 +1,179 @@
# encoding:utf-8
"""
@ date: 2020-09-16
@ author: jingxian
@ illustration: Pre-processing
"""
import sys
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pywt
from scipy import signal
from scipy import fftpack
def Dilate(x, N, g, M):
returndata = np.array([])
for num in range(N - M + 1):
returndata = np.append(returndata, np.min(np.array(x[num:num + M]) - np.array(g)))
return returndata
def Eorde(x, N, g, M):
returndata = np.array([])
for num in range(N - M + 1):
returndata = np.append(returndata, np.max(np.array(x[num:num + M]) - np.array(g)))
return returndata
def fin_turn(data, peak):
if len(data) == 0 or len(peak) == 0: return peak
return_peak = []
for p in peak:
minx, maxx = max(0, p - 100), min(len(data), p + 100)
return_peak.append(minx + np.argmax(data[minx: maxx]))
return return_peak
class BCG_Operation():
def __init__(self, sample_rate=1000):
self.sample_rate = sample_rate
def down_sample(self, data=None, down_radio=10):
if data is None:
raise ValueError("data is None, please given an real value!")
data = data[:len(data) // down_radio * down_radio].reshape(-1, down_radio)[:, 0]
self.sample_rate = self.sample_rate / down_radio
return data
def Splitwin(self, data=None, len_win=None, coverage=1.0, calculate_to_end=False):
"""
分窗
:param len_win: length of window
:return: signal windows
"""
if (len_win is None) or (data is None):
raise ValueError("length of window or data is None, please given an real value!")
else:
length = len_win * self.sample_rate # number point of a window
# step of split windows
step = length * coverage
start = 0
Splitdata = []
while (len(data) - start >= length):
Splitdata.append(data[int(start):int(start + length)])
start += step
if calculate_to_end and (len(data) - start > 2000):
remain = len(data) - start
start = start - step
step = int(remain / 2000)
start = start + step * 2000
Splitdata.append(data[int(start):int(start + length)])
return np.array(Splitdata), step
elif calculate_to_end:
return np.array(Splitdata), 0
else:
return np.array(Splitdata)
def Butterworth(self, data, type, low_cut=0.0, high_cut=0.0, order=10):
"""
:param type: Type of Butter. filter, lowpass, bandpass, ...
:param lowcut: Low cutoff frequency
:param highcut: High cutoff frequency
:param order: Order of filter
:return: Signal after filtering
"""
if type == "lowpass": # 低通滤波处理
b, a = signal.butter(order, low_cut / (self.sample_rate * 0.5), btype='lowpass')
return signal.filtfilt(b, a, np.array(data))
elif type == "bandpass": # 带通滤波处理
low = low_cut / (self.sample_rate * 0.5)
high = high_cut / (self.sample_rate * 0.5)
b, a = signal.butter(order, [low, high], btype='bandpass')
return signal.filtfilt(b, a, np.array(data))
elif type == "highpass": # 高通滤波处理
b, a = signal.butter(order, high_cut / (self.sample_rate * 0.5), btype='highpass')
return signal.filtfilt(b, a, np.array(data))
else: # 警告,滤波器类型必须有
raise ValueError("Please choose a type of fliter")
def MorphologicalFilter(self, data=None, M=200, get_bre=False):
"""
:param data: Input signal
:param M: Length of structural element
:return: Signal after filter
"""
if not data.any():
raise ValueError("The input data is None, please given real value data")
g = np.ones(M)
Data_pre = np.insert(data, 0, np.zeros(M))
Data_pre = np.insert(Data_pre, -1, np.zeros(M))
# Opening: 腐蚀 + 膨胀
out1 = Eorde(Data_pre, len(Data_pre), g, M)
out2 = Dilate(out1, len(out1), g, M)
out2 = np.insert(out2, 0, np.zeros(M - 2))
# Closing: 膨胀 + 腐蚀
out5 = Dilate(Data_pre, len(Data_pre), g, M)
out6 = Eorde(out5, len(out5), g, M)
out6 = np.insert(out6, 0, np.zeros(M - 2))
baseline = (out2 + out6) / 2
# -------------------------保留剩余价值------------------------
data_filtered = Data_pre[:len(baseline)] - baseline
data_filtered = data_filtered[M: M + len(data)]
baseline = baseline[M:]
data_filtered[-1] = data_filtered[-2] = data_filtered[-3]
baseline[-1] = baseline[-2] = baseline[-3]
if get_bre:
return data_filtered, baseline
else:
return data_filtered
def Iirnotch(self, data=None, cut_fre=50, quality=3):
"""陷波器"""
b, a = signal.iirnotch(cut_fre / (self.sample_rate * 0.5), quality)
return signal.filtfilt(b, a, np.array(data))
def ChebyFilter(self, data, rp=1, type=None, low_cut=0, high_cut=0, order=10):
"""
切比雪夫滤波器
:param data: Input signal
:param rp: The maximum ripple allowed
:param type: 'lowpass', 'bandpass, 'highpass'
:param low_cut: Low cut-off fre
:param high_cut: High cut-off fre
:param order: The order of filter
:return: Signal after filter
"""
if type == 'lowpass':
b, a = signal.cheby1(order, rp, low_cut, btype='lowpass', fs=self.sample_rate)
return signal.filtfilt(b, a, np.array(data))
elif type == 'bandpass':
b, a = signal.cheby1(order, rp, [low_cut, high_cut], btype='bandpass', fs=self.sample_rate)
return signal.filtfilt(b, a, np.array(data))
elif type == 'highpass':
b, a = signal.cheby1(order, rp, high_cut, btype='highpass', fs=self.sample_rate)
return signal.filtfilt(b, a, np.array(data))
else:
raise ValueError("The type of filter is None, please given the real value!")
def Envelope(self, data):
"""取信号包络"""
if len(data) <= 1: raise ValueError("Wrong input data")
hx = fftpack.hilbert(data)
return np.sqrt(hx ** 2, data ** 2)
def wavelet_trans(self, data, c_level=['aaa', 'aad'], wavelet='db4', mode='symmetric', maxlevel=10):
wp = pywt.WaveletPacket(data=data, wavelet=wavelet, mode=mode, maxlevel=maxlevel)
new_wp = pywt.WaveletPacket(data=None, wavelet=wavelet, mode=mode)
for c in c_level:
new_wp[c] = wp[c]
return new_wp.reconstruct()
# def em_decomposition(self, data):
# from pyhht.emd import EMD
# return EMD(data).decompose()

470
utils/Quality_Relabel.py Normal file
View File

@ -0,0 +1,470 @@
# -*- coding: cp936 -*-
# 使用gbk编码才能读标签
"""
@author:Marques
@file:Prepare_Data.py
@email:admin@marques22.com
@email:2021022362@m.scnu.edu.cn
@time:2022/03/26
"""
import time
from typing import List
import logging
import pyedflib
from pathlib import Path
import numpy as np
import pandas as pd
import matplotlib
from matplotlib import pyplot as plt, gridspec
from utils.Preprocessing import BCG_Operation
from tqdm import tqdm
from datetime import datetime
matplotlib.use("Qt5Agg")
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# ['EEG F3-A2', 'EEG F4-A1', 'EEG C3-A2', 'EEG C4-A1', 'EEG O1-A2',
# 'EEG O2-A1', 'EOG Right', 'EOG Left', 'EMG Chin', 'ECG I', 'RR',
# 'ECG II', 'Effort Tho', 'Flow Patient', 'Flow Patient', 'Effort Abd',
# 'SpO2', 'Pleth', 'Snore', 'Body', 'Pulse', 'Leg LEG1', 'Leg LEG2',
# 'EEG A1-A2', 'Imp']
# 设置日志
logger = logging.getLogger()
logger.setLevel(logging.NOTSET)
realtime = time.strftime('%Y%m%d', time.localtime(time.time()))
fh = logging.FileHandler(Path("history") / (realtime + ".log"), mode='a')
fh.setLevel(logging.NOTSET)
fh.setFormatter(logging.Formatter("%(asctime)s: %(message)s"))
logger.addHandler(fh)
ch = logging.StreamHandler()
ch.setLevel(logging.NOTSET)
ch.setFormatter(logging.Formatter("%(asctime)s: %(message)s"))
logger.addHandler(ch)
logging.getLogger('matplotlib.font_manager').disabled = True
logging.info("------------------------------------")
class Quality_Relabel:
# 可选择的通道
base_channel = ['EEG F3-A2', 'EEG F4-A1', 'EEG C3-A2', 'EEG C4-A1', 'EEG O1-A2', 'EEG O2-A1', 'EOG Right',
'EOG Left', 'EMG Chin', 'ECG I', 'RR', 'ECG II', 'Effort Tho', 'Flow Patient', 'Flow Patient', 'HR',
'Effort Abd', 'SpO2', 'Pleth', 'Snore', 'Body', 'Pulse', 'Leg LEG1', 'Leg LEG2', 'EEG A1-A2', 'Imp']
# 显示事件
base_event = ["Hypopnea", "Central apnea", "Obstructive apnea", "Mixed apnea", "Desaturation"]
# 设定事件和其对应颜色
# event_code color event
# 0 黑色 背景
# 1 粉色 低通气
# 2 蓝色 中枢性
# 3 红色 阻塞型
# 4 灰色 混合型
# 5 绿色 血氧饱和度下降
# 6 橙色 大体动
# 7 橙色 小体动
# 8 橙色 深呼吸
# 9 橙色 脉冲体动
# 10 橙色 无效片段
color_cycle = ["black", "pink", "blue", "red", "silver", "green", "orange", "orange", "orange", "orange", "orange"]
# assert len(color_cycle) == len(base_event) + 1, "基础事件数量与颜色数量不一致"
def __init__(self, all_path: List, sampNo: int, frequency: int = 100, bcg_frequency: int = 1000,
extend_second: int = 0,
channel_list: List[str] = ['Effort Tho', 'Effort Abd', 'SpO2', 'Flow Patient', 'Flow Patient'],
focus_event_list: List[str] = ["Obstructive apnea"]):
"""
:param sampNo: 编号选择
:param frequency: 显示采样率
:param bcg_frequency: BCG信号采样率
:param channel_list: 显示的通道
:param focus_event_list: 关注暂停事件
"""
self.PSG_Data_Path = all_path[0]
self.PSG_Label_Path = all_path[1]
self.BCG_Data_Path = all_path[2]
self.BCG_Label_Path = all_path[3]
self.Artifact_Label_Path = all_path[4]
self.Artifact_Offset_Path = all_path[5]
self.sampNo = sampNo
self.channel_list = channel_list
self.focus_event_list = focus_event_list
self.frequency = frequency
self.bcg_frequency = bcg_frequency
self.extend_second = extend_second
self.ecg_start_time = None
# 用来显示颜色时按点匹配事件
self.ecg_event_label = None
self.bcg_event_label = None
self.spo2_event_label = None
self.artifact_event_label = None
# 仅包含关注暂停事件的列表
self.ecg_event_label_filtered_df = None
self.bcg_event_label_filtered_df = None
# 所有事件列表
self.ecg_event_label_df = None
self.bcg_event_label_df = None
# 各通道信号
self.signal_select = {}
self.check_channel()
self.read_data(frequency, bcg_frequency)
self.read_event()
self.read_artifact_label()
def check_channel(self):
for i in self.channel_list:
if i not in self.base_channel:
logging.debug(f"{i} 不存在于常见通道名中")
print(f"常见通道名:{self.channel_list}")
def read_data(self, frequency: int = 100, bcg_frequency: int = 1000):
bcg_path = self.BCG_Data_Path / f"{self.sampNo}samp.npy"
ecg_path = self.PSG_Data_Path / f"A{str(self.sampNo).rjust(7, '0')}.edf"
if not bcg_path.exists():
logging.error(f"{bcg_path} 不存在!")
raise FileNotFoundError(f"{bcg_path} 不存在!")
if not ecg_path.exists():
logging.error(f"{ecg_path} 不存在!")
raise FileNotFoundError(f"{ecg_path} 不存在!")
with pyedflib.EdfReader(str(ecg_path.resolve())) as file:
signal_num = file.signals_in_file
logging.debug(f"{self.sampNo} EDF file signal number is {signal_num}")
signal_label = file.getSignalLabels()
logging.debug(f"{self.sampNo} EDF file signal label : {signal_label}")
self.ecg_start_time = file.getStartdatetime()
# 根据PSG记录长度生成事件表
self.ecg_event_label = np.zeros(
int(file.getFileDuration()) * self.frequency + self.extend_second * self.frequency)
self.spo2_event_label = np.zeros(
int(file.getFileDuration()) * self.frequency + self.extend_second * self.frequency)
# 打印PSG信息
file.file_info_long()
# sub_index 用于区分两个flow patient
sub_index = 1
logging.info("读取PSG信号····")
for i, index in enumerate(signal_label):
# 仅加载选中的通道
if index in self.channel_list:
# 重命名flow patient通道
if index == 'Flow Patient':
if sub_index == 1:
index = "Flow T"
else:
index = "Flow P"
sub_index += 1
signal = file.readSignal(i)
sample_frequency = file.getSampleFrequency(i)
# 读取采样率 进行重采样
if sample_frequency < frequency:
signal = signal.repeat(frequency / sample_frequency)
elif sample_frequency > frequency:
signal = signal[::int(sample_frequency / frequency)]
self.signal_select[index] = signal
logging.info(f"完成读取PSG: {index}")
# 加载心晓信号
logging.info("读取心晓信号····")
signal = np.load(bcg_path)
preprocessing = BCG_Operation(sample_rate=bcg_frequency)
# 20Hz低通去噪
signal1 = preprocessing.Butterworth(signal, 'lowpass', low_cut=20, order=3)
# 0.7Hz 低通提取呼吸
signal2 = preprocessing.Butterworth(signal, 'lowpass', low_cut=0.7, order=3)
# 进行降采样
signal1 = signal1[::int(bcg_frequency / frequency)]
signal2 = signal2[::int(bcg_frequency / frequency)]
# 根据心晓事件长度生成事件记录
self.bcg_event_label = np.zeros(len(signal) + self.extend_second * self.frequency)
self.signal_select['orgdata'] = signal1
self.signal_select['0.7lowpass_resp'] = signal2
for signal_key in self.signal_select.keys():
self.signal_select[signal_key] = np.append(self.signal_select[signal_key],
self.signal_select[signal_key].mean().astype(int).repeat(
self.extend_second * self.frequency))
def read_event(self):
bcg_label_path = self.BCG_Label_Path / f"export{self.sampNo}_all.csv"
ecg_label_path = self.PSG_Label_Path / f"export{self.sampNo}.csv"
if not bcg_label_path.exists():
logging.error(f"{bcg_label_path} 不存在!")
raise FileNotFoundError(f"{bcg_label_path} 不存在!")
if not ecg_label_path.exists():
logging.error(f"{ecg_label_path} 不存在!")
raise FileNotFoundError(f"{ecg_label_path} 不存在!")
df = pd.read_csv(ecg_label_path, encoding='gbk')
self.ecg_event_label_df = df
# 过滤不关注的事件
df2 = df[df["Event type"].isin(self.focus_event_list)]
# 根据epoch进行排列方便索引
df2 = df2.sort_values(by='Epoch')
self.ecg_event_label_filtered_df = df2
logging.info("遍历PSG事件···")
for one_data in tqdm(df.index, ncols=80):
one_data = df.loc[one_data]
# 通过开始时间推算事件起始点与结束点
event_start_time = datetime.strptime(one_data["Date"] + " " + one_data["Time"], '%Y/%m/%d %H:%M:%S')
SP = (event_start_time - self.ecg_start_time).seconds
# 对括号进行切分避免Duration 20 (20) 这种带括号的问题
EP = int(SP + float(one_data["Duration"].split("(")[0]))
SP *= self.frequency
EP *= self.frequency
# 对事件重新编码并存到事件记录表中
if one_data["Event type"] == "Hypopnea":
self.ecg_event_label[SP:EP] = 1
elif one_data["Event type"] == "Central apnea":
self.ecg_event_label[SP:EP] = 2
elif one_data["Event type"] == "Obstructive apnea":
self.ecg_event_label[SP:EP] = 3
elif one_data["Event type"] == "Mixed apnea":
self.ecg_event_label[SP:EP] = 4
elif one_data["Event type"] == "Desaturation":
self.spo2_event_label[SP:EP] = 5
# 读取心晓事件
df = pd.read_csv(bcg_label_path, encoding='gbk')
df["new_start"] = df["new_start"].astype("int")
df["new_end"] = df["new_end"].astype("int")
self.bcg_event_label_df = df
# 过滤不关注事件
df2 = df[df["Event type"].isin(self.focus_event_list)]
df2 = df2.sort_values(by='Epoch')
self.bcg_event_label_filtered_df = df2
logging.info("遍历心晓事件···")
for one_data in tqdm(df.index):
one_data = df.loc[one_data]
SP = one_data["new_start"] * self.frequency
EP = one_data["new_end"] * self.frequency
if one_data["Event type"] == "Hypopnea":
self.bcg_event_label[SP:EP] = 1
elif one_data["Event type"] == "Central apnea":
self.bcg_event_label[SP:EP] = 2
elif one_data["Event type"] == "Obstructive apnea":
self.bcg_event_label[SP:EP] = 3
elif one_data["Event type"] == "Mixed apnea":
self.bcg_event_label[SP:EP] = 4
def read_artifact_label(self):
all_offset_length = pd.read_excel(self.Artifact_Offset_Path)
offset_length = all_offset_length[all_offset_length['数据编号'] == self.sampNo]['from_code'].values[0]
artifact_label_path = self.Artifact_Label_Path / f"Artifact_{self.sampNo}.txt"
artifact_label = pd.read_csv(artifact_label_path, header=None).to_numpy().reshape(-1, 4)
self.artifact_event_label = np.zeros(len(self.bcg_event_label) + self.extend_second * self.frequency)
for i, artifact_type, SP, EP in artifact_label:
SP = (int(SP) + offset_length) // (1000 // self.frequency)
EP = (int(EP) + offset_length) // (1000 // self.frequency)
artifact_type = int(artifact_type) + 5
SP = 0 if SP < 0 else SP
if EP < 0:
continue
if SP > len(self.bcg_event_label):
continue
self.artifact_event_label[SP:EP] = artifact_type
# assert len(self.ecg_event_label_filtered_df) == len(self.bcg_event_label_filtered_df), \
# f"PSG与心晓事件数量不一致, PSG事件数量{len(self.ecg_event_label_filtered_df)},
# 心晓事件数量{len(self.bcg_event_label_filtered_df)}"
def show_one_event(self, bcg_index: int, ecg_index: int, front_add_second: int = 60,
back_add_second: int = 60):
"""
:param bcg_index: 心晓事件在csv中行号
:param ecg_index: PSG事件在csv中序号
:param front_add_second: 向前延伸时间
:param back_add_second: 向后延伸时间
:return:
"""
# 获取事件实际在csv文件中的序号
bcg_real_index = self.bcg_event_label_filtered_df.index[bcg_index],
ecg_real_index = self.ecg_event_label_filtered_df.index[ecg_index],
one_bcg_data = self.bcg_event_label_df.loc[bcg_real_index]
one_ecg_data = self.ecg_event_label_df.loc[ecg_real_index]
# 获取ECG事件开始与结束时间
event_start_time = datetime.strptime(one_ecg_data["Date"] + " " + one_ecg_data["Time"], '%Y/%m/%d %H:%M:%S')
ecg_SP = (event_start_time - self.ecg_start_time).seconds
ecg_duration = int(float(str(one_ecg_data["Duration"]).split("(")[0]) + 0.5)
ecg_EP = ecg_SP + ecg_duration
# 获取BCG事件开始与结束时间
bcg_SP = one_bcg_data["new_start"]
bcg_EP = one_bcg_data["new_end"]
bcg_duration = bcg_EP - bcg_SP
logging.info(f"sampNo:{self.sampNo} "
f"bcg[index:{bcg_index} epoch:{one_bcg_data['Epoch']} event:{one_bcg_data['Event type']}] "
f"ecg:[index:{ecg_index} epoch:{one_ecg_data['Epoch']} event:{one_ecg_data['Event type']}]")
if one_bcg_data['Event type'] != one_ecg_data['Event type']:
logging.error(f"sampNo:{self.sampNo} PSG事件与心晓时间不一致请排查"
f"bcg[index:{bcg_index} epoch:{one_bcg_data['Epoch']} event:{one_bcg_data['Event type']}] "
f"ecg:[index:{ecg_index} epoch:{one_ecg_data['Epoch']} event:{one_ecg_data['Event type']}]")
raise ValueError()
# 进行向两边延展
ecg_SP = ecg_SP - front_add_second
ecg_EP = ecg_EP + back_add_second
bcg_SP = bcg_SP - front_add_second - (ecg_duration - bcg_duration) // 2
bcg_EP = bcg_EP + back_add_second + (ecg_duration - bcg_duration) // 2
# 绘图
plt.figure(figsize=(12, 6), dpi=150)
# 各个子图之间的比例
gs = gridspec.GridSpec(7, 1, height_ratios=[1, 1, 1, 1, 1, 3, 1])
plt.subplots_adjust(top=1, bottom=0, right=1, left=0, hspace=0, wspace=0)
plt.margins(0, 0)
plt.tight_layout()
# 绘制 Flow1
plt.subplot(gs[0])
self.plt_channel(plt_=plt, SP=ecg_SP, EP=ecg_EP, channel="Flow T")
# 绘制 Flow2
plt.subplot(gs[1])
self.plt_channel(plt_=plt, SP=ecg_SP, EP=ecg_EP, channel="Flow P",
title=f"PSG sampNo:{self.sampNo} Index:{ecg_index + 1}/{len(self.ecg_event_label_filtered_df)} "
f"Epoch:{one_ecg_data['Epoch']} Duration:{ecg_duration}")
plt.subplot(gs[2])
self.plt_channel(plt_=plt, SP=ecg_SP, EP=ecg_EP, channel="Effort Tho")
plt.subplot(gs[3])
self.plt_channel(plt_=plt, SP=ecg_SP, EP=ecg_EP, channel="Effort Abd")
plt.subplot(gs[4])
self.plt_channel(plt_=plt, SP=ecg_SP, EP=ecg_EP, channel="SpO2", event_code=[5])
plt.subplot(gs[5])
self.plt_channel(plt_=plt, SP=bcg_SP, EP=bcg_EP, channel="orgdata",
event_code=[6, 7, 8, 9, 10, 1, 2, 3, 4],
event_show_under=False)
plt.subplot(gs[6])
self.plt_channel(plt_=plt, SP=bcg_SP, EP=bcg_EP, channel="0.7lowpass_resp",
event_code=[6, 7, 8, 9, 10, 1, 2, 3, 4],
event_show_under=False,
ax_bottom=True,
title=f"心晓 sampNo:{self.sampNo} Index:{bcg_index + 1}/{len(self.bcg_event_label_filtered_df)} "
f"Epoch:{one_bcg_data['Epoch']} Duration:{bcg_duration}",
)
figManager = plt.get_current_fig_manager()
figManager.window.showMaximized()
plt.show()
def plt_channel(self, plt_, SP, EP, channel, event_code=[1, 2, 3, 4], event_show_under=False,
ax_top=False, ax_bottom=False, ax_left=True, ax_right=False, title=None):
"""
:param plt_:
:param SP: 显示开始秒数
:param EP: 显示结束秒数
:param channel: 通道名称
:param event_code: 要上色的事件编号
:param event_show_under: 事件颜色显示在信号下面
:param ax_top: 显示上框线
:param ax_bottom: 显示下框线
:param ax_left: 显示左框线
:param ax_right: 显示右框线
:param title: 显示标题
:return:
"""
linestyle = "-"
SP = 0 if SP < 0 else SP
plt_.plot(np.linspace(SP, EP, (EP - SP) * self.frequency),
self.signal_select[channel][SP * self.frequency:EP * self.frequency], label=channel,
color=self.color_cycle[0])
for j in event_code:
if channel == "SpO2":
mask = self.spo2_event_label[SP * self.frequency:EP * self.frequency] == j
elif channel == "orgdata" or channel == "0.7lowpass_resp":
if j <= 5:
mask = self.bcg_event_label[SP * self.frequency:EP * self.frequency] == j
else:
mask = self.artifact_event_label[SP * self.frequency:EP * self.frequency] == j
linestyle = "-"
else:
mask = self.ecg_event_label[SP * self.frequency:EP * self.frequency] == j
if event_show_under:
min_point = self.signal_select[channel][SP * self.frequency:EP * self.frequency].min()
len_segment = EP * self.frequency - SP * self.frequency
y = (min_point.repeat(len_segment) * mask).astype('float')
np.place(y, y == 0, np.nan)
else:
y = (self.signal_select[channel][SP * self.frequency:EP * self.frequency] * mask).astype('float')
np.place(y, y == 0, np.nan)
plt_.plot(np.linspace(SP, EP, (EP - SP) * self.frequency), y, color=self.color_cycle[j],
linestyle=linestyle)
plt_.legend(loc=1)
if title is not None:
plt_.title(title)
ax = plt.gca()
ax.spines["top"].set_visible(ax_top)
ax.spines["right"].set_visible(ax_right)
ax.spines["bottom"].set_visible(ax_bottom)
ax.spines["left"].set_visible(ax_left)
# xticks = [[]] if xticks else [range(SP, EP, 5), [str(i) for i in range(0, (EP - SP), 5)]]
# print(xticks)
# plt_.xticks(*xticks) # 去掉x轴
def show_all_event(self, start_bcg_index: int = 0, front_add_second: int = 60,
back_add_second: int = 60):
for index in range(start_bcg_index, len(self.bcg_event_label_filtered_df)):
self.show_one_event(index,
index,
front_add_second=front_add_second,
back_add_second=back_add_second
)
if __name__ == '__main__':
PSG_Data_Path = "../Data/PSG/"
PSG_Label_Path = "../Data/PSG_label/"
BCG_Data_Path = "../Data/BCG/"
BCG_Label_Path = "../Data/BCG_label/"
all_paths = [PSG_Data_Path, PSG_Label_Path, BCG_Data_Path, BCG_Label_Path]
prepareData = Quality_Relabel(all_paths, 670)
prepareData.show_all_event()