diff --git a/.idea/misc.xml b/.idea/misc.xml
index 19c19b7..2f44f69 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,5 +3,5 @@
-
+
diff --git a/.idea/stat.iml b/.idea/stat.iml
index ceec064..7190cc6 100644
--- a/.idea/stat.iml
+++ b/.idea/stat.iml
@@ -2,7 +2,7 @@
-
+
diff --git a/statapp/combo_delegate.py b/statapp/combo_delegate.py
new file mode 100644
index 0000000..aa7b05e
--- /dev/null
+++ b/statapp/combo_delegate.py
@@ -0,0 +1,63 @@
+#
+# Copyright (c) 2023 Maxim Slipenko, Eugene Lazurenko.
+#
+# This file is part of Statapp
+# (see https://github.com/shizand/statapp).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+from PySide2 import QtCore
+from PySide2.QtWidgets import QComboBox, QItemDelegate
+
+
+class ComboDelegate(QItemDelegate):
+ commitData = QtCore.Signal(object)
+ """
+ A delegate that places a fully functioning QComboBox in every
+ cell of the column to which it's applied
+ """
+ def __init__(self, parent, objects, objectNames):
+ """
+ Constructoe
+ :param parent: QTableView parent object
+ :param objects: List of objects to set. i.e. [True, False]
+ :param objectNames: List of Object names to display. i.e. ['True', 'False']
+ """
+ QItemDelegate.__init__(self, parent)
+
+ # objects to sent to the model associated to the combobox. i.e. [True, False]
+ self.objects = objects
+
+ # object description to display in the combobox. i.e. ['True', 'False']
+ self.objectNames = objectNames
+
+ @QtCore.Slot()
+ def currentIndexChanged(self):
+ self.commitData.emit(self.sender())
+
+ def createEditor(self, parent, option, index):
+ combo = QComboBox(parent)
+ combo.addItems(self.objectNames)
+ combo.currentIndexChanged.connect(self.currentIndexChanged)
+ return combo
+
+ def setEditorData(self, editor, index):
+ editor.blockSignals(True)
+ val = index.model().data(index, role=QtCore.Qt.DisplayRole)
+ idx = self.objects.index(val)
+ editor.setCurrentIndex(idx)
+ editor.blockSignals(False)
+
+ def setModelData(self, editor, model, index):
+ model.setData(index, self.objects[editor.currentIndex()], QtCore.Qt.EditRole)
diff --git a/statapp/main_window.py b/statapp/main_window.py
index 4839fb0..a04dacc 100644
--- a/statapp/main_window.py
+++ b/statapp/main_window.py
@@ -36,6 +36,7 @@ from statapp.ui.ui_main_window import Ui_MainWindow
from statapp.utils import buildMessageBox, addIcon, FloatDelegate
from statapp.variance_analysis import VarianceAnalysisWindow
from statapp.correlation_analysis import CorrelationAnalysisWindow
+from statapp.polynoms.transform_polynom_window import TransformPolynomWindow
class MainWindow(QMainWindow):
@@ -56,6 +57,7 @@ class MainWindow(QMainWindow):
self.ui.correlationAnalisisAction,
self.ui.linearPolynomAction,
self.ui.squaredPolynomAction,
+ self.ui.transformPolynomAction,
]
self.aboutWindow = None
@@ -192,6 +194,11 @@ class MainWindow(QMainWindow):
dw = SquaredPolynomWindow(self.model.getData())
dw.exec()
+ @Slot()
+ def on_transformPolynomAction_triggered(self):
+ dw = TransformPolynomWindow(self.model.getData())
+ dw.exec()
+
def closeEvent(self, event):
if self.isDataChanged:
file = ''
diff --git a/statapp/models/transform_polynom_model.py b/statapp/models/transform_polynom_model.py
new file mode 100644
index 0000000..0568585
--- /dev/null
+++ b/statapp/models/transform_polynom_model.py
@@ -0,0 +1,74 @@
+#
+# Copyright (c) 2023 Maxim Slipenko, Eugene Lazurenko.
+#
+# This file is part of Statapp
+# (see https://github.com/shizand/statapp).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+import numpy as np
+from PySide2.QtCore import Qt
+
+from statapp.models.editable_table_model import EditableTableModel
+from statapp.models.regression_result_model import RegressionResultModel
+
+def defaultX(x):
+ return x
+
+TRANSFORMS = {
+ '-': defaultX,
+ 'sin(x)': np.sin,
+ 'cos(x)': np.cos,
+ 'log(x)': np.log,
+ 'exp(x)': np.exp,
+}
+
+class TransformPolynomModel(RegressionResultModel, EditableTableModel):
+
+ def __init__(self, result):
+ self._monomials = None
+ super().__init__(result)
+ n = result.paramsAndImportance.shape[0]
+
+ self._transforms = ['-'] * n
+
+ def columnCount(self, index):
+ return 3
+
+ def updateAllData(self, data):
+ d = data.paramsAndImportance
+ self._monomials = data.monomials
+ super().updateAllData(d)
+
+ def flags(self, index):
+ if index.column() == 0 and index.row() != 0:
+ return EditableTableModel.flags(self, index)
+ return RegressionResultModel.flags(self, index)
+
+ def data(self, index, role):
+ if role == Qt.DisplayRole and index.column() == 0:
+ return self._transforms[index.row()]
+ return super().data(index, role)
+
+ def setData(self, index, value, role):
+ if role == Qt.EditRole and index.column() == 0:
+ self._transforms[index.row()] = value
+ topLeftIndex = self.createIndex(index.row(), 0)
+ bottomRightIndex = self.createIndex(index.row(), 0)
+ self.dataChanged.emit(topLeftIndex, bottomRightIndex)
+ return True
+ return super().setData(index, value, role)
+
+ def getHorizontalHeader(self):
+ return ['Преобразования'] + super().getHorizontalHeader()
diff --git a/statapp/polynoms/transform_polynom_window.py b/statapp/polynoms/transform_polynom_window.py
new file mode 100644
index 0000000..945f051
--- /dev/null
+++ b/statapp/polynoms/transform_polynom_window.py
@@ -0,0 +1,87 @@
+#
+# Copyright (c) 2023 Maxim Slipenko, Eugene Lazurenko.
+#
+# This file is part of Statapp
+# (see https://github.com/shizand/statapp).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+import numpy as np
+from PySide2.QtCore import Qt
+from PySide2.QtWidgets import QDialog, QHeaderView
+
+from statapp.calculations import linearPolynom
+from statapp.combo_delegate import ComboDelegate
+from statapp.mathtex_header_view import MathTexHeaderView
+from statapp.models.transform_polynom_model import TransformPolynomModel, TRANSFORMS
+from statapp.ui.ui_transform_polynom_window import Ui_PolynomWindow
+from statapp.utils import addIcon
+
+
+class TransformPolynomWindow(QDialog):
+ def __init__(self, data):
+ super().__init__()
+ self.ui = Ui_PolynomWindow()
+ self.ui.setupUi(self)
+ addIcon(self)
+ self.setWindowTitle("Преобразования")
+
+ self.data = data
+ result = linearPolynom(data)
+
+ # Создание столбца из нулей
+ zeroCol = np.zeros((result.paramsAndImportance.shape[0], 1))
+ # Добавление столбца к исходному массиву
+ result.paramsAndImportance = np.column_stack((zeroCol, result.paramsAndImportance))
+
+ # self.ui.tableView.setItemDelegate(FloatDelegate())
+ self.ui.tableView.setItemDelegate(
+ ComboDelegate(
+ self.ui.tableView,
+ list(TRANSFORMS.keys()),
+ list(TRANSFORMS.keys()),
+ )
+ )
+ self.model = TransformPolynomModel(result)
+ self.ui.tableView.setModel(self.model)
+ self.ui.tableView.setVerticalHeader(MathTexHeaderView(self.ui.tableView))
+ header = self.ui.tableView.horizontalHeader()
+ header.setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
+
+ self.ui.residualVarianceValueLabel.setText(str(result.residualVariance))
+ self.ui.scaledResidualVarianceValueLabel.setText(str(result.scaledResidualVariance))
+ self.ui.fStatisticValueLabel.setText(str(result.fStatistic))
+ self.ui.rSquaredValueLabel.setText(str(result.scaledResidualVariance))
+
+ self.model.dataChanged.connect(self.on_data_changed)
+
+ def on_data_changed(self):
+ data = np.copy(self.data)
+ print(len(data[0:]))
+ for i in range(len(data[0:])):
+ for j in range(1, len(data[i])):
+ tr = self.model.data(self.model.createIndex(j, 0), Qt.DisplayRole)
+ data[i][j] = TRANSFORMS[tr](data[i][j])
+
+ self.rebuildData(data)
+
+ def rebuildData(self, data):
+ result = linearPolynom(data)
+ zeroCol = np.zeros((result.paramsAndImportance.shape[0], 1))
+ result.paramsAndImportance = np.column_stack((zeroCol, result.paramsAndImportance))
+ self.model.updateAllData(result)
+ self.ui.residualVarianceValueLabel.setText(str(result.residualVariance))
+ self.ui.scaledResidualVarianceValueLabel.setText(str(result.scaledResidualVariance))
+ self.ui.fStatisticValueLabel.setText(str(result.fStatistic))
+ self.ui.rSquaredValueLabel.setText(str(result.scaledResidualVariance))
diff --git a/statapp/ui/main_window.ui b/statapp/ui/main_window.ui
index a23d2ec..e33b238 100644
--- a/statapp/ui/main_window.ui
+++ b/statapp/ui/main_window.ui
@@ -40,7 +40,7 @@
00800
- 27
+ 21
@@ -71,6 +71,7 @@
+
@@ -135,6 +136,11 @@
Квадратичный полином
+
+
+ Преобразования
+
+
diff --git a/statapp/ui/transform_polynom_window.ui b/statapp/ui/transform_polynom_window.ui
new file mode 100644
index 0000000..a140630
--- /dev/null
+++ b/statapp/ui/transform_polynom_window.ui
@@ -0,0 +1,101 @@
+
+
+ PolynomWindow
+
+
+
+ 0
+ 0
+ 537
+ 444
+
+
+
+ Полином
+
+
+
+
+
+ 10
+
+
+
+
+ undefined
+
+
+
+
+
+
+ undefined
+
+
+
+
+
+
+ F1 - отношение Фишера
+
+
+
+
+
+
+ Остаточная дисперсия:
+
+
+
+
+
+
+ Остаточная дисперсия (масштабированная):
+
+
+
+
+
+
+ Коэффициент множественной дереминизации
+
+
+
+
+
+
+ undefined
+
+
+
+
+
+
+ undefined
+
+
+
+
+
+
+
+
+
+
+ 40
+
+
+ 40
+
+
+ 40
+
+
+
+
+
+
+
+
+
+
diff --git a/statapp/ui/ui_main_window.py b/statapp/ui/ui_main_window.py
index 6049b84..e5692a5 100644
--- a/statapp/ui/ui_main_window.py
+++ b/statapp/ui/ui_main_window.py
@@ -58,6 +58,8 @@ class Ui_MainWindow(object):
self.linearPolynomAction.setObjectName(u"linearPolynomAction")
self.squaredPolynomAction = QAction(MainWindow)
self.squaredPolynomAction.setObjectName(u"squaredPolynomAction")
+ self.transformPolynomAction = QAction(MainWindow)
+ self.transformPolynomAction.setObjectName(u"transformPolynomAction")
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.gridLayout = QGridLayout(self.centralwidget)
@@ -77,7 +79,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, 27))
+ self.menubar.setGeometry(QRect(0, 0, 800, 21))
self.filemenu = QMenu(self.menubar)
self.filemenu.setObjectName(u"filemenu")
self.generatemenu = QMenu(self.menubar)
@@ -107,6 +109,7 @@ class Ui_MainWindow(object):
self.analyzemenu.addAction(self.correlationAnalisisAction)
self.modelmenu.addAction(self.linearPolynomAction)
self.modelmenu.addAction(self.squaredPolynomAction)
+ self.modelmenu.addAction(self.transformPolynomAction)
self.helpmenu.addAction(self.aboutmenuaction)
self.retranslateUi(MainWindow)
@@ -126,6 +129,7 @@ class Ui_MainWindow(object):
self.correlationAnalisisAction.setText(QCoreApplication.translate("MainWindow", u"\u041a\u043e\u0440\u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0430\u043d\u0430\u043b\u0438\u0437", None))
self.linearPolynomAction.setText(QCoreApplication.translate("MainWindow", u"\u041b\u0438\u043d\u0435\u0439\u043d\u044b\u0439 \u043f\u043e\u043b\u0438\u043d\u043e\u043c", None))
self.squaredPolynomAction.setText(QCoreApplication.translate("MainWindow", u"\u041a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u0447\u043d\u044b\u0439 \u043f\u043e\u043b\u0438\u043d\u043e\u043c", None))
+ self.transformPolynomAction.setText(QCoreApplication.translate("MainWindow", u"\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f", 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_transform_polynom_window.py b/statapp/ui/ui_transform_polynom_window.py
new file mode 100644
index 0000000..459e345
--- /dev/null
+++ b/statapp/ui/ui_transform_polynom_window.py
@@ -0,0 +1,118 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2023 Maxim Slipenko, Eugene Lazurenko.
+#
+# This file is part of Statapp
+# (see https://github.com/shizand/statapp).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+
+
+################################################################################
+## Form generated from reading UI file 'transform_polynom_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_PolynomWindow(object):
+ def setupUi(self, PolynomWindow):
+ if not PolynomWindow.objectName():
+ PolynomWindow.setObjectName(u"PolynomWindow")
+ PolynomWindow.resize(537, 444)
+ self.gridLayout_2 = QGridLayout(PolynomWindow)
+ self.gridLayout_2.setObjectName(u"gridLayout_2")
+ self.polynomResult = QGridLayout()
+ self.polynomResult.setObjectName(u"polynomResult")
+ self.polynomResult.setContentsMargins(-1, 10, -1, -1)
+ self.residualVarianceValueLabel = QLabel(PolynomWindow)
+ self.residualVarianceValueLabel.setObjectName(u"residualVarianceValueLabel")
+
+ self.polynomResult.addWidget(self.residualVarianceValueLabel, 0, 1, 1, 1)
+
+ self.scaledResidualVarianceValueLabel = QLabel(PolynomWindow)
+ self.scaledResidualVarianceValueLabel.setObjectName(u"scaledResidualVarianceValueLabel")
+
+ self.polynomResult.addWidget(self.scaledResidualVarianceValueLabel, 1, 1, 1, 1)
+
+ self.fStatisticLabel = QLabel(PolynomWindow)
+ self.fStatisticLabel.setObjectName(u"fStatisticLabel")
+
+ self.polynomResult.addWidget(self.fStatisticLabel, 2, 0, 1, 1)
+
+ self.residualVarianceLabel = QLabel(PolynomWindow)
+ self.residualVarianceLabel.setObjectName(u"residualVarianceLabel")
+
+ self.polynomResult.addWidget(self.residualVarianceLabel, 0, 0, 1, 1)
+
+ self.scaledResidualVarianceLabel = QLabel(PolynomWindow)
+ self.scaledResidualVarianceLabel.setObjectName(u"scaledResidualVarianceLabel")
+
+ self.polynomResult.addWidget(self.scaledResidualVarianceLabel, 1, 0, 1, 1)
+
+ self.rSquaredLabel = QLabel(PolynomWindow)
+ self.rSquaredLabel.setObjectName(u"rSquaredLabel")
+
+ self.polynomResult.addWidget(self.rSquaredLabel, 3, 0, 1, 1)
+
+ self.fStatisticValueLabel = QLabel(PolynomWindow)
+ self.fStatisticValueLabel.setObjectName(u"fStatisticValueLabel")
+
+ self.polynomResult.addWidget(self.fStatisticValueLabel, 2, 1, 1, 1)
+
+ self.rSquaredValueLabel = QLabel(PolynomWindow)
+ self.rSquaredValueLabel.setObjectName(u"rSquaredValueLabel")
+
+ self.polynomResult.addWidget(self.rSquaredValueLabel, 3, 1, 1, 1)
+
+
+ self.gridLayout_2.addLayout(self.polynomResult, 1, 6, 1, 1)
+
+ self.gridLayout = QGridLayout()
+ self.gridLayout.setObjectName(u"gridLayout")
+ self.tableView = QTableView(PolynomWindow)
+ self.tableView.setObjectName(u"tableView")
+ self.tableView.horizontalHeader().setMinimumSectionSize(40)
+ self.tableView.verticalHeader().setMinimumSectionSize(40)
+ self.tableView.verticalHeader().setDefaultSectionSize(40)
+
+ self.gridLayout.addWidget(self.tableView, 1, 3, 1, 1)
+
+
+ self.gridLayout_2.addLayout(self.gridLayout, 0, 6, 1, 1)
+
+
+ self.retranslateUi(PolynomWindow)
+
+ QMetaObject.connectSlotsByName(PolynomWindow)
+ # setupUi
+
+ def retranslateUi(self, PolynomWindow):
+ PolynomWindow.setWindowTitle(QCoreApplication.translate("PolynomWindow", u"\u041f\u043e\u043b\u0438\u043d\u043e\u043c", None))
+ self.residualVarianceValueLabel.setText(QCoreApplication.translate("PolynomWindow", u"undefined", None))
+ self.scaledResidualVarianceValueLabel.setText(QCoreApplication.translate("PolynomWindow", u"undefined", None))
+ self.fStatisticLabel.setText(QCoreApplication.translate("PolynomWindow", u"F1 - \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0424\u0438\u0448\u0435\u0440\u0430", None))
+ self.residualVarianceLabel.setText(QCoreApplication.translate("PolynomWindow", u"\u041e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u0430\u044f \u0434\u0438\u0441\u043f\u0435\u0440\u0441\u0438\u044f:", None))
+ self.scaledResidualVarianceLabel.setText(QCoreApplication.translate("PolynomWindow", u"\u041e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u0430\u044f \u0434\u0438\u0441\u043f\u0435\u0440\u0441\u0438\u044f (\u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f):", None))
+ self.rSquaredLabel.setText(QCoreApplication.translate("PolynomWindow", u"\u041a\u043e\u044d\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0434\u0435\u0440\u0435\u043c\u0438\u043d\u0438\u0437\u0430\u0446\u0438\u0438", None))
+ self.fStatisticValueLabel.setText(QCoreApplication.translate("PolynomWindow", u"undefined", None))
+ self.rSquaredValueLabel.setText(QCoreApplication.translate("PolynomWindow", u"undefined", None))
+ # retranslateUi