diff --git a/statapp/calculations.py b/statapp/calculations.py
new file mode 100644
index 0000000..08ce6cd
--- /dev/null
+++ b/statapp/calculations.py
@@ -0,0 +1,7 @@
+import numpy as np
+
+
+def variance_analysis(data):
+ return np.array([
+ [np.mean(col), np.std(col), np.min(col), np.max(col)] for col in data.T
+ ])
diff --git a/statapp/main_window.py b/statapp/main_window.py
index c751541..3fadbdc 100644
--- a/statapp/main_window.py
+++ b/statapp/main_window.py
@@ -9,7 +9,8 @@ from statapp.generate_window import GenerateWindow
from statapp.about_window import AboutWindow
from statapp.models.fileslc_model import FileSLCModel
from statapp.ui.ui_main_window import Ui_MainWindow
-from statapp.utils import resource_path
+from statapp.utils import resource_path, buildMessageBox
+from statapp.variance_analysis import VarianceAnalysisWindow
class MainWindow(QMainWindow):
@@ -36,7 +37,7 @@ class MainWindow(QMainWindow):
if self.fileModel.file_name:
file = '\nФайл сохранения:' + self.fileModel.file_name
- msgBox = self.createMessageBox \
+ msgBox = buildMessageBox \
('Сохранение данных',
"Сохранить данные?" + file,
QMessageBox.Question,
@@ -119,16 +120,10 @@ class MainWindow(QMainWindow):
about_window = AboutWindow()
about_window.show()
- def createMessageBox(self, title, text, icon, buttons, defaultButton):
- msgBox = QMessageBox()
-
- msgBox.setIcon(icon)
- msgBox.setWindowTitle(title)
- msgBox.setText(text)
- msgBox.setStandardButtons(buttons)
- msgBox.setDefaultButton(defaultButton)
-
- return msgBox
+ @Slot()
+ def on_varianceAnalysisAction_triggered(self):
+ dw = VarianceAnalysisWindow(self.model.getData())
+ dw.exec()
def closeEvent(self, event):
if self.isDataChanged:
@@ -136,7 +131,7 @@ class MainWindow(QMainWindow):
if self.fileModel.file_name:
file = '\nФайл сохранения:' + self.fileModel.file_name
- msgBox = self.createMessageBox \
+ msgBox = buildMessageBox \
('Завершение работы',
"Сохранить данные?" + file,
QMessageBox.Question,
diff --git a/statapp/models/ro_table_model.py b/statapp/models/ro_table_model.py
new file mode 100644
index 0000000..cb67ee9
--- /dev/null
+++ b/statapp/models/ro_table_model.py
@@ -0,0 +1,53 @@
+import PySide2
+import numpy as np
+from PySide2 import QtCore
+from PySide2.QtCore import Qt
+
+from statapp.utils import safe_list_get
+
+
+class ROTableModel(QtCore.QAbstractTableModel):
+ def __init__(self,
+ data=np.array([[]], dtype=np.float32),
+ ):
+ super().__init__()
+ self._data = data
+ self._headers = {
+ Qt.Vertical: self.getVerticalHeader,
+ Qt.Horizontal: self.getHorizontalHeader,
+ }
+
+ def updateAllData(self, data):
+ self.layoutAboutToBeChanged.emit()
+ self._data = data
+ self.layoutChanged.emit()
+
+ def rowCount(self, index):
+ return self._data.shape[0]
+
+ def columnCount(self, index):
+ return self._data.shape[1]
+
+ def getVerticalHeader(self):
+ return []
+
+ def getHorizontalHeader(self):
+ return []
+
+ def headerData(self, section: int, orientation: Qt.Orientation, role: int = ...):
+ if role == Qt.DisplayRole:
+ return safe_list_get(self._headers[orientation](), section, None)
+
+ return None
+
+ def getData(self):
+ return self._data
+
+ def getY(self):
+ return self._data[:, 0]
+
+
+ def data(self, index, role):
+ if role == Qt.DisplayRole:
+ return float(self._data[index.row(), index.column()])
+ return None
diff --git a/statapp/models/variance_analysis_model.py b/statapp/models/variance_analysis_model.py
new file mode 100644
index 0000000..8a57895
--- /dev/null
+++ b/statapp/models/variance_analysis_model.py
@@ -0,0 +1,14 @@
+from PySide2.QtCore import QModelIndex
+
+from statapp.models.ro_table_model import ROTableModel
+
+
+class VarianceAnalysisModel(ROTableModel):
+ def __init__(self, data):
+ super().__init__(data)
+
+ def getHorizontalHeader(self):
+ return ['Мат. ожидание', 'Среднекв. отклонение', 'Минимум', 'Максимум']
+
+ def getVerticalHeader(self):
+ return ['Y'] + [f'X{i}' for i in range(1, self.rowCount(QModelIndex()))]
diff --git a/statapp/ui/main_window.ui b/statapp/ui/main_window.ui
index 62e034e..850ad4c 100644
--- a/statapp/ui/main_window.ui
+++ b/statapp/ui/main_window.ui
@@ -40,7 +40,7 @@
0
0
800
- 21
+ 27
+
diff --git a/statapp/ui/ui_main_window.py b/statapp/ui/ui_main_window.py
index b7b658d..bfd7bfd 100644
--- a/statapp/ui/ui_main_window.py
+++ b/statapp/ui/ui_main_window.py
@@ -12,6 +12,7 @@ from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
+
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
if not MainWindow.objectName():
@@ -29,6 +30,8 @@ class Ui_MainWindow(object):
self.savefileaction.setObjectName(u"savefileaction")
self.closefileaction = QAction(MainWindow)
self.closefileaction.setObjectName(u"closefileaction")
+ self.varianceAnalysisAction = QAction(MainWindow)
+ self.varianceAnalysisAction.setObjectName(u"varianceAnalysisAction")
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.gridLayout = QGridLayout(self.centralwidget)
@@ -48,7 +51,7 @@ class Ui_MainWindow(object):
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QMenuBar(MainWindow)
self.menubar.setObjectName(u"menubar")
- self.menubar.setGeometry(QRect(0, 0, 800, 21))
+ self.menubar.setGeometry(QRect(0, 0, 800, 27))
self.filemenu = QMenu(self.menubar)
self.filemenu.setObjectName(u"filemenu")
self.generatemenu = QMenu(self.menubar)
@@ -74,6 +77,7 @@ class Ui_MainWindow(object):
self.filemenu.addAction(self.closefileaction)
self.generatemenu.addAction(self.generateYaction)
self.generatemenu.addAction(self.generateXaction)
+ self.analyzemenu.addAction(self.varianceAnalysisAction)
self.helpmenu.addAction(self.aboutmenuaction)
self.retranslateUi(MainWindow)
@@ -89,6 +93,7 @@ class Ui_MainWindow(object):
self.openfileaction.setText(QCoreApplication.translate("MainWindow", u"\u041e\u0442\u043a\u0440\u044b\u0442\u044c", None))
self.savefileaction.setText(QCoreApplication.translate("MainWindow", u"\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c", None))
self.closefileaction.setText(QCoreApplication.translate("MainWindow", u"\u0417\u0430\u043a\u0440\u044b\u0442\u044c", None))
+ self.varianceAnalysisAction.setText(QCoreApplication.translate("MainWindow", u"\u0414\u0438\u0441\u043f\u0435\u0440\u0441\u0438\u043e\u043d\u043d\u044b\u0439 \u0430\u043d\u0430\u043b\u0438\u0437", None))
self.label.setText(QCoreApplication.translate("MainWindow", u"\u0421\u0422\u0410\u0422\u0418\u0421\u0422\u0418\u0427\u0415\u0421\u041a\u0418\u0415 \u0414\u0410\u041d\u041d\u042b\u0415", None))
self.filemenu.setTitle(QCoreApplication.translate("MainWindow", u"\u0424\u0430\u0439\u043b", None))
self.generatemenu.setTitle(QCoreApplication.translate("MainWindow", u"\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439", None))
diff --git a/statapp/ui/ui_variance_analysis_window.py b/statapp/ui/ui_variance_analysis_window.py
new file mode 100644
index 0000000..7cea5c2
--- /dev/null
+++ b/statapp/ui/ui_variance_analysis_window.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'variance_analysis_window.ui'
+##
+## Created by: Qt User Interface Compiler version 5.15.2
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide2.QtCore import *
+from PySide2.QtGui import *
+from PySide2.QtWidgets import *
+
+
+class Ui_VarianceAnalysisWindow(object):
+ def setupUi(self, VarianceAnalysisWindow):
+ if not VarianceAnalysisWindow.objectName():
+ VarianceAnalysisWindow.setObjectName(u"VarianceAnalysisWindow")
+ VarianceAnalysisWindow.resize(942, 606)
+ self.gridLayout_2 = QGridLayout(VarianceAnalysisWindow)
+ self.gridLayout_2.setObjectName(u"gridLayout_2")
+ self.gridLayout = QGridLayout()
+ self.gridLayout.setObjectName(u"gridLayout")
+ self.tableView = QTableView(VarianceAnalysisWindow)
+ self.tableView.setObjectName(u"tableView")
+
+ self.gridLayout.addWidget(self.tableView, 0, 0, 1, 1)
+
+
+ self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
+
+
+ self.retranslateUi(VarianceAnalysisWindow)
+
+ QMetaObject.connectSlotsByName(VarianceAnalysisWindow)
+ # setupUi
+
+ def retranslateUi(self, VarianceAnalysisWindow):
+ VarianceAnalysisWindow.setWindowTitle(QCoreApplication.translate("VarianceAnalysisWindow", u"\u0414\u0438\u0441\u043f\u0435\u0440\u0441\u0438\u043e\u043d\u043d\u044b\u0439 \u0430\u043d\u0430\u043b\u0438\u0437", None))
+ # retranslateUi
diff --git a/statapp/ui/variance_analysis_window.ui b/statapp/ui/variance_analysis_window.ui
new file mode 100644
index 0000000..80de4a0
--- /dev/null
+++ b/statapp/ui/variance_analysis_window.ui
@@ -0,0 +1,28 @@
+
+
+ VarianceAnalysisWindow
+
+
+
+ 0
+ 0
+ 942
+ 606
+
+
+
+ Дисперсионный анализ
+
+
+ -
+
+
-
+
+
+
+
+
+
+
+
+
diff --git a/statapp/utils.py b/statapp/utils.py
index e6e19cb..9dbc210 100644
--- a/statapp/utils.py
+++ b/statapp/utils.py
@@ -1,6 +1,8 @@
import os
import sys
+from PySide2.QtWidgets import QMessageBox
+
def resource_path(relative):
if getattr(sys, 'frozen', False):
@@ -9,3 +11,22 @@ def resource_path(relative):
# we are running in a normal Python environment
bundle_dir = os.path.dirname(os.path.abspath(__file__))
return os.path.join(bundle_dir, relative)
+
+
+def safe_list_get(l, idx, default):
+ try:
+ return l[idx]
+ except IndexError:
+ return default
+
+
+def buildMessageBox(title, text, icon, buttons, defaultButton):
+ msgBox = QMessageBox()
+
+ msgBox.setIcon(icon)
+ msgBox.setWindowTitle(title)
+ msgBox.setText(text)
+ msgBox.setStandardButtons(buttons)
+ msgBox.setDefaultButton(defaultButton)
+
+ return msgBox
diff --git a/statapp/variance_analysis.py b/statapp/variance_analysis.py
new file mode 100644
index 0000000..df8476a
--- /dev/null
+++ b/statapp/variance_analysis.py
@@ -0,0 +1,18 @@
+from PySide2.QtWidgets import QDialog, QHeaderView
+
+from statapp.calculations import variance_analysis
+from statapp.models.variance_analysis_model import VarianceAnalysisModel
+from statapp.ui.ui_variance_analysis_window import Ui_VarianceAnalysisWindow
+
+
+class VarianceAnalysisWindow(QDialog):
+ def __init__(self, data):
+ super().__init__()
+ self.ui = Ui_VarianceAnalysisWindow()
+ self.ui.setupUi(self)
+
+ res = variance_analysis(data)
+ self.model = VarianceAnalysisModel(res.round(2))
+ self.ui.tableView.setModel(self.model)
+ header = self.ui.tableView.horizontalHeader()
+ header.setSectionResizeMode(QHeaderView.ResizeMode.Stretch)