diff --git a/statapp/generate_factor_window.py b/statapp/generate_factor_window.py new file mode 100644 index 0000000..08dd441 --- /dev/null +++ b/statapp/generate_factor_window.py @@ -0,0 +1,34 @@ +from PySide2.QtCore import Slot +from PySide2.QtWidgets import QDialog + +from statapp.ui.ui_generate_factor_window import Ui_GenerateFactorWindow +from statapp.models.combobox_model import ComboBoxModel + + +DIRECT_LINK = 0 +INDIRECT_LINK = 1 + + +class GenerateFactorWindow(QDialog): + def __init__(self): + super().__init__() + self.deviation = None + self.mat = None + self.typeConnection = None + self._typeComboBox = ComboBoxModel([ + [DIRECT_LINK, "прямая"], + [INDIRECT_LINK, "обратная"] + ]) + + self.ui = Ui_GenerateFactorWindow() + self.ui.setupUi(self) + self.ui.typeComboBox.setModel(self._typeComboBox) + + @Slot() + def on_generatePushButton_clicked(self): + self.typeConnection = self._typeComboBox.rawData(self.ui.typeComboBox.currentIndex())[0] + + self.mat = self.ui.matSpinBox.value() + self.deviation = self.ui.deviationSpinBox.value() + + self.accept() diff --git a/statapp/generate_window.py b/statapp/generate_window.py new file mode 100644 index 0000000..7785bcd --- /dev/null +++ b/statapp/generate_window.py @@ -0,0 +1,23 @@ +from PySide2.QtCore import Slot +from PySide2.QtWidgets import QDialog + +from statapp.ui.ui_generate_window import Ui_GenerateWindow + + +class GenerateWindow(QDialog): + def __init__(self): + super().__init__() + self.deviation = None + self.mat = None + self.count = None + self.ui = Ui_GenerateWindow() + self.ui.setupUi(self) + + @Slot() + def on_generatePushButton_clicked(self): + + self.count = self.ui.countSpinBox.value() + self.mat = self.ui.matSpinBox.value() + self.deviation = self.ui.deviationSpinBox.value() + + self.accept() diff --git a/statapp/main_window.py b/statapp/main_window.py index 56b684b..079c397 100644 --- a/statapp/main_window.py +++ b/statapp/main_window.py @@ -1,15 +1,64 @@ +import numpy as np from PySide2.QtCore import Slot from PySide2.QtWidgets import QMainWindow +from statapp.generate_factor_window import GenerateFactorWindow, INDIRECT_LINK +from statapp.models.data_model import DataModel +from statapp.generate_window import GenerateWindow from statapp.about_window import AboutWindow from statapp.ui.ui_main_window import Ui_MainWindow + class MainWindow(QMainWindow): def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) + self.model = DataModel() + self.ui.tableView.setModel(self.model) + + @Slot() + def on_generateYaction_triggered(self): + gw = GenerateWindow() + if gw.exec(): + y = np.random.normal(gw.mat, gw.deviation, size=(gw.count, 1)) + self.model.updateAllData(y) + + @Slot() + def on_generateXaction_triggered(self): + gfw = GenerateFactorWindow() + + # dd = np.array([]) + + if gfw.exec(): + y = self.model.getY() + yMat = np.mean(y) + + x_arr = np.array([]) + + for cur_y in y: + k = np.abs(cur_y / yMat) + if k > 1: + k = 2 - 1 / k + if gfw.typeConnection == INDIRECT_LINK: + k = 1 / k + + x = np.random.normal(gfw.mat * (k ** 3), gfw.deviation * k, size=1) + x_arr = np.append(x_arr, x) + # if (x > gfw.mat and cur_y > yMat) or (x < gfw.mat and cur_y < yMat): + # dd = np.append(dd, 1) + # else: + # dd = np.append(dd, 0) + + data = self.model.getData() + + x_arr = x_arr.reshape(len(x_arr), 1) + # dd = dd.reshape(len(dd), 1) + data = np.concatenate((data, x_arr), axis=1) + # data = np.concatenate((data, dd), axis=1) + self.model.updateAllData(data) + @Slot() def on_aboutmenuaction_triggered(self): global about_window diff --git a/statapp/models/combobox_model.py b/statapp/models/combobox_model.py new file mode 100644 index 0000000..cc33814 --- /dev/null +++ b/statapp/models/combobox_model.py @@ -0,0 +1,35 @@ +from PySide2.QtCore import QAbstractListModel, Qt + + +class ComboBoxModel(QAbstractListModel): + + def __init__(self, data): + super().__init__() + self._data = data + + def updateAllData(self, data: list): + self.layoutAboutToBeChanged.emit() + self._data = data + self.layoutChanged.emit() + + def rawData(self, index: int): + return self._data[index] + + def findById(self, oid: int): + for i, x in enumerate(self._data): + if x[0] == oid: + return i + + return -1 + + def data(self, index, role): + if role == Qt.DisplayRole: + return self._data[index.row()][1] + + if role == Qt.UserRole: + return self._data[index.row()] + + return None + + def rowCount(self, index): + return len(self._data) diff --git a/statapp/models/data_model.py b/statapp/models/data_model.py new file mode 100644 index 0000000..c9ade7d --- /dev/null +++ b/statapp/models/data_model.py @@ -0,0 +1,59 @@ +import numpy as np +from PySide2 import QtCore +from PySide2.QtCore import Qt + + +class DataModel(QtCore.QAbstractTableModel): + def __init__(self, data=np.array([[]], dtype=np.float32)): + super().__init__() + + self._data = data + + 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 headerData(self, section: int, orientation: Qt.Orientation, role: int = ...): + if role == Qt.DisplayRole: + # if orientation == Qt.Orientation.Horizontal: + + if section == 0: + return 'Y' + + return f'X{section}' + + return None + + def flags(self, index): + return Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable + + def setData(self, index, value, role): + if role == Qt.EditRole: + try: + value = float(value) + except ValueError: + return False + self._data[index.row(), index.column()] = value + return True + return False + + def getData(self): + return self._data + + def getY(self): + return self._data[:, 0] + + + def data(self, index, role): + if role == Qt.DisplayRole or role == Qt.EditRole: + # ? + return float(self._data[index.row(), index.column()]) + + return None \ No newline at end of file diff --git a/statapp/ui/generate_factor_window.ui b/statapp/ui/generate_factor_window.ui new file mode 100644 index 0000000..5bacbcc --- /dev/null +++ b/statapp/ui/generate_factor_window.ui @@ -0,0 +1,115 @@ + + + GenerateFactorWindow + + + + 0 + 0 + 503 + 193 + + + + Dialog + + + + + + + + + 12 + + + + Тип связи + + + + + + + + 12 + + + + Среднеквадратичное отклонение + + + + + + + + 12 + + + + Сгенерировать + + + + + + + + 12 + + + + Математическое ожидание + + + + + + + + 12 + + + + 1000000.000000000000000 + + + + + + + + 12 + + + + 1000000.000000000000000 + + + + + + + + 12 + + + + false + + + + + + + + + + + + + + + + diff --git a/statapp/ui/generate_window.ui b/statapp/ui/generate_window.ui new file mode 100644 index 0000000..203647a --- /dev/null +++ b/statapp/ui/generate_window.ui @@ -0,0 +1,88 @@ + + + GenerateWindow + + + + 0 + 0 + 503 + 182 + + + + + 12 + + + + Dialog + + + + + + + + Сгенерировать + + + + + + + Математическое ожидание + + + + + + + Среднеквадратичное отклонение + + + + + + + 1000000.000000000000000 + + + + + + + Количество наблюдений + + + + + + + 1 + + + 500 + + + + + + + 1000000.000000000000000 + + + + + + + + + countSpinBox + matSpinBox + deviationSpinBox + generatePushButton + + + + diff --git a/statapp/ui/main_window.ui b/statapp/ui/main_window.ui index f00abb1..89a3d15 100644 --- a/statapp/ui/main_window.ui +++ b/statapp/ui/main_window.ui @@ -26,7 +26,11 @@ - + + + false + + @@ -36,7 +40,7 @@ 0 0 800 - 22 + 19 @@ -48,6 +52,8 @@ Генерация показателей + + @@ -77,6 +83,16 @@ О программе + + + Генерация отклика + + + + + Генерация фактора + + diff --git a/statapp/ui/ui_generate_factor_window.py b/statapp/ui/ui_generate_factor_window.py new file mode 100644 index 0000000..e851549 --- /dev/null +++ b/statapp/ui/ui_generate_factor_window.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'generate_factor_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_GenerateFactorWindow(object): + def setupUi(self, GenerateFactorWindow): + if not GenerateFactorWindow.objectName(): + GenerateFactorWindow.setObjectName(u"GenerateFactorWindow") + GenerateFactorWindow.resize(503, 193) + self.gridLayout_2 = QGridLayout(GenerateFactorWindow) + self.gridLayout_2.setObjectName(u"gridLayout_2") + self.gridLayout = QGridLayout() + self.gridLayout.setObjectName(u"gridLayout") + self.label = QLabel(GenerateFactorWindow) + self.label.setObjectName(u"label") + font = QFont() + font.setPointSize(12) + self.label.setFont(font) + + self.gridLayout.addWidget(self.label, 0, 0, 1, 1) + + self.label_3 = QLabel(GenerateFactorWindow) + self.label_3.setObjectName(u"label_3") + self.label_3.setFont(font) + + self.gridLayout.addWidget(self.label_3, 2, 0, 1, 1) + + self.generatePushButton = QPushButton(GenerateFactorWindow) + self.generatePushButton.setObjectName(u"generatePushButton") + self.generatePushButton.setFont(font) + + self.gridLayout.addWidget(self.generatePushButton, 3, 0, 1, 2) + + self.label_2 = QLabel(GenerateFactorWindow) + self.label_2.setObjectName(u"label_2") + self.label_2.setFont(font) + + self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1) + + self.matSpinBox = QDoubleSpinBox(GenerateFactorWindow) + self.matSpinBox.setObjectName(u"matSpinBox") + self.matSpinBox.setFont(font) + self.matSpinBox.setMaximum(1000000.000000000000000) + + self.gridLayout.addWidget(self.matSpinBox, 1, 1, 1, 1) + + self.deviationSpinBox = QDoubleSpinBox(GenerateFactorWindow) + self.deviationSpinBox.setObjectName(u"deviationSpinBox") + self.deviationSpinBox.setFont(font) + self.deviationSpinBox.setMaximum(1000000.000000000000000) + + self.gridLayout.addWidget(self.deviationSpinBox, 2, 1, 1, 1) + + self.typeComboBox = QComboBox(GenerateFactorWindow) + self.typeComboBox.setObjectName(u"typeComboBox") + self.typeComboBox.setFont(font) + self.typeComboBox.setEditable(False) + + self.gridLayout.addWidget(self.typeComboBox, 0, 1, 1, 1) + + + self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1) + + + self.retranslateUi(GenerateFactorWindow) + + QMetaObject.connectSlotsByName(GenerateFactorWindow) + # setupUi + + def retranslateUi(self, GenerateFactorWindow): + GenerateFactorWindow.setWindowTitle(QCoreApplication.translate("GenerateFactorWindow", u"Dialog", None)) + self.label.setText(QCoreApplication.translate("GenerateFactorWindow", u"\u0422\u0438\u043f \u0441\u0432\u044f\u0437\u0438", None)) + self.label_3.setText(QCoreApplication.translate("GenerateFactorWindow", u"\u0421\u0440\u0435\u0434\u043d\u0435\u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u0447\u043d\u043e\u0435 \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u0435", None)) + self.generatePushButton.setText(QCoreApplication.translate("GenerateFactorWindow", u"\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c", None)) + self.label_2.setText(QCoreApplication.translate("GenerateFactorWindow", u"\u041c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435", None)) + self.typeComboBox.setCurrentText("") + self.typeComboBox.setPlaceholderText("") + # retranslateUi diff --git a/statapp/ui/ui_generate_window.py b/statapp/ui/ui_generate_window.py new file mode 100644 index 0000000..f28d09f --- /dev/null +++ b/statapp/ui/ui_generate_window.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'generate_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_GenerateWindow(object): + def setupUi(self, GenerateWindow): + if not GenerateWindow.objectName(): + GenerateWindow.setObjectName(u"GenerateWindow") + GenerateWindow.resize(503, 182) + font = QFont() + font.setPointSize(12) + GenerateWindow.setFont(font) + self.gridLayout_2 = QGridLayout(GenerateWindow) + self.gridLayout_2.setObjectName(u"gridLayout_2") + self.gridLayout = QGridLayout() + self.gridLayout.setObjectName(u"gridLayout") + self.generatePushButton = QPushButton(GenerateWindow) + self.generatePushButton.setObjectName(u"generatePushButton") + + self.gridLayout.addWidget(self.generatePushButton, 3, 0, 1, 2) + + self.label_2 = QLabel(GenerateWindow) + self.label_2.setObjectName(u"label_2") + + self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1) + + self.label_3 = QLabel(GenerateWindow) + self.label_3.setObjectName(u"label_3") + + self.gridLayout.addWidget(self.label_3, 2, 0, 1, 1) + + self.matSpinBox = QDoubleSpinBox(GenerateWindow) + self.matSpinBox.setObjectName(u"matSpinBox") + self.matSpinBox.setMaximum(1000000.000000000000000) + + self.gridLayout.addWidget(self.matSpinBox, 1, 1, 1, 1) + + self.label = QLabel(GenerateWindow) + self.label.setObjectName(u"label") + + self.gridLayout.addWidget(self.label, 0, 0, 1, 1) + + self.countSpinBox = QSpinBox(GenerateWindow) + self.countSpinBox.setObjectName(u"countSpinBox") + self.countSpinBox.setMinimum(1) + self.countSpinBox.setMaximum(500) + + self.gridLayout.addWidget(self.countSpinBox, 0, 1, 1, 1) + + self.deviationSpinBox = QDoubleSpinBox(GenerateWindow) + self.deviationSpinBox.setObjectName(u"deviationSpinBox") + self.deviationSpinBox.setMaximum(1000000.000000000000000) + + self.gridLayout.addWidget(self.deviationSpinBox, 2, 1, 1, 1) + + + self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1) + + QWidget.setTabOrder(self.countSpinBox, self.matSpinBox) + QWidget.setTabOrder(self.matSpinBox, self.deviationSpinBox) + QWidget.setTabOrder(self.deviationSpinBox, self.generatePushButton) + + self.retranslateUi(GenerateWindow) + + QMetaObject.connectSlotsByName(GenerateWindow) + # setupUi + + def retranslateUi(self, GenerateWindow): + GenerateWindow.setWindowTitle(QCoreApplication.translate("GenerateWindow", u"Dialog", None)) + self.generatePushButton.setText(QCoreApplication.translate("GenerateWindow", u"\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c", None)) + self.label_2.setText(QCoreApplication.translate("GenerateWindow", u"\u041c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435", None)) + self.label_3.setText(QCoreApplication.translate("GenerateWindow", u"\u0421\u0440\u0435\u0434\u043d\u0435\u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u0447\u043d\u043e\u0435 \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u0435", None)) + self.label.setText(QCoreApplication.translate("GenerateWindow", u"\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u0439", None)) + # retranslateUi diff --git a/statapp/ui/ui_main_window.py b/statapp/ui/ui_main_window.py index 866c384..dd1a94f 100644 --- a/statapp/ui/ui_main_window.py +++ b/statapp/ui/ui_main_window.py @@ -20,6 +20,10 @@ class Ui_MainWindow(object): MainWindow.resize(800, 600) self.aboutmenuaction = QAction(MainWindow) self.aboutmenuaction.setObjectName(u"aboutmenuaction") + self.generateYaction = QAction(MainWindow) + self.generateYaction.setObjectName(u"generateYaction") + self.generateXaction = QAction(MainWindow) + self.generateXaction.setObjectName(u"generateXaction") self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName(u"centralwidget") self.gridLayout = QGridLayout(self.centralwidget) @@ -32,13 +36,14 @@ class Ui_MainWindow(object): self.tableView = QTableView(self.centralwidget) self.tableView.setObjectName(u"tableView") + self.tableView.verticalHeader().setVisible(False) self.gridLayout.addWidget(self.tableView, 1, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(MainWindow) self.menubar.setObjectName(u"menubar") - self.menubar.setGeometry(QRect(0, 0, 800, 22)) + self.menubar.setGeometry(QRect(0, 0, 800, 19)) self.filemenu = QMenu(self.menubar) self.filemenu.setObjectName(u"filemenu") self.generatemenu = QMenu(self.menubar) @@ -59,6 +64,8 @@ class Ui_MainWindow(object): self.menubar.addAction(self.analyzemenu.menuAction()) self.menubar.addAction(self.modelmenu.menuAction()) self.menubar.addAction(self.helpmenu.menuAction()) + self.generatemenu.addAction(self.generateYaction) + self.generatemenu.addAction(self.generateXaction) self.helpmenu.addAction(self.aboutmenuaction) self.retranslateUi(MainWindow) @@ -69,6 +76,8 @@ class Ui_MainWindow(object): def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435", None)) self.aboutmenuaction.setText(QCoreApplication.translate("MainWindow", u"\u041e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435", None)) + self.generateYaction.setText(QCoreApplication.translate("MainWindow", u"\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043e\u0442\u043a\u043b\u0438\u043a\u0430", None)) + self.generateXaction.setText(QCoreApplication.translate("MainWindow", u"\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0444\u0430\u043a\u0442\u043e\u0440\u0430", 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))