79 Commits

Author SHA1 Message Date
github-actions[bot]
4f1f610822 chore(main): release 0.7.0 (#88)
🤖 I have created a release *beep* *boop*
---


## [0.7.0](https://github.com/shizand/statapp/compare/v0.6.0...v0.7.0)
(2023-12-01)


### Новые функции

* добавлена возможность ввода чисел до 5 знаков
([#87](https://github.com/shizand/statapp/issues/87))
([dc7c487](dc7c4875d7)),
closes [#82](https://github.com/shizand/statapp/issues/82)
* Добавлены новые характеристики
([#89](https://github.com/shizand/statapp/issues/89))
([b12db5a](b12db5a300)),
closes [#84](https://github.com/shizand/statapp/issues/84)

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-12-01 14:11:49 +03:00
b12db5a300 feat: Добавлены новые характеристики (#89)
Closes #84
2023-12-01 14:03:20 +03:00
dc7c4875d7 feat: добавлена возможность ввода чисел до 5 знаков (#87)
Closes #82
2023-11-25 14:21:05 +03:00
2f5988a2eb chore: исправляет форматирование 2023-10-25 17:11:09 +03:00
9348138094 chore: исправляет описание в "Установка" 2023-10-25 17:09:30 +03:00
c35b9ca308 chore: исправляет опечатки 2023-10-25 15:58:06 +03:00
e6ba0fc610 ci: Revert "добавил сборку linux x86"
This reverts commit 4be89269b9.
2023-10-20 14:46:57 +03:00
cddacb21b2 Merge remote-tracking branch 'origin/main' 2023-10-20 14:20:27 +03:00
4be89269b9 ci: добавил сборку linux x86 2023-10-20 14:20:12 +03:00
github-actions[bot]
9f7181513b chore(main): release 0.6.0 (#80)
🤖 I have created a release *beep* *boop*
---


## [0.6.0](https://github.com/shizand/statapp/compare/v0.5.0...v0.6.0)
(2023-10-20)


### Новые функции

* добавлен "Квадратичный полином"
([#81](https://github.com/shizand/statapp/issues/81))
([9033770](9033770406))


### Исправления

* исправлен формат сохранения файлов
([#79](https://github.com/shizand/statapp/issues/79))
([044d2b6](044d2b61cf))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-20 13:53:26 +03:00
725289ca06 chore: понизил версию Pillow 2023-10-20 13:47:45 +03:00
a6cda1ab3d chore: удалена отладка 2023-10-20 13:47:15 +03:00
9033770406 feat: добавлен "Квадратичный полином" (#81)
Closes #34.
2023-10-20 13:26:49 +03:00
MisterMLiL
044d2b61cf fix: исправлен формат сохранения файлов (#79) 2023-10-13 22:06:24 +03:00
github-actions[bot]
dd765ae981 chore(main): release 0.5.0 (#75)
🤖 I have created a release *beep* *boop*
---


## [0.5.0](https://github.com/shizand/statapp/compare/v0.4.2...v0.5.0)
(2023-10-06)


### Новые функции

* добавлен "Линейный полином"
([#74](https://github.com/shizand/statapp/issues/74))
([232de9f](232de9f145))


### Исправления

* добавлены переводы для QMessageBox
([#73](https://github.com/shizand/statapp/issues/73))
([e653c3d](e653c3df29))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-06 09:51:47 +03:00
bdb346fd17 ci: try fix ci 2023-10-06 09:44:00 +03:00
79297850df ci: try fix ci 2023-10-06 09:23:03 +03:00
232de9f145 feat: добавлен "Линейный полином" (#74) 2023-10-05 21:28:11 +03:00
e653c3df29 fix: добавлены переводы для QMessageBox (#73) 2023-10-05 21:27:51 +03:00
a89d7896e3 refactor: исправлены ВСЕ замечания pylint (#72) 2023-10-04 14:38:42 +03:00
d387a79d6d ci: fix version 2023-10-04 14:29:32 +03:00
dd3ab2e1cf ci: добавляет permissions для labeler 2023-10-04 14:21:58 +03:00
2115490b2c ci: добавляет labeler 2023-10-04 14:20:28 +03:00
d89837e34a chore: заменил codacy badge 2023-10-04 09:04:23 +03:00
af8d9cbdde chore: добавил too-few-public-methods 2023-10-04 09:02:24 +03:00
18157b9e82 chore: переименовал файл pylint 2023-10-04 08:55:13 +03:00
25bc63ee51 chore: добавлен pylint (#71) 2023-10-04 08:42:16 +03:00
fea99f0985 chore: добавлен файл README.md (#69)
Closes #26.

---------

Co-authored-by: codacy-production[bot] <61871480+codacy-production[bot]@users.noreply.github.com>
2023-10-03 20:49:35 +03:00
github-actions[bot]
390dbdc087 chore(main): release 0.4.2 (#68)
🤖 I have created a release *beep* *boop*
---


## [0.4.2](https://github.com/shizand/statapp/compare/v0.4.1...v0.4.2)
(2023-10-03)


### Исправления

* добавлены иконки во все окна
([#67](https://github.com/shizand/statapp/issues/67))
([9310a5e](9310a5e622))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-03 18:41:46 +03:00
MisterMLiL
9310a5e622 fix: добавлены иконки во все окна (#67)
Closes #65

---------

Co-authored-by: Maxim Slipenko <no-reply@maxim.slipenko.com>
2023-10-03 18:18:32 +03:00
github-actions[bot]
1d76b7cb76 chore(main): release 0.4.1 (#64)
🤖 I have created a release *beep* *boop*
---


## [0.4.1](https://github.com/shizand/statapp/compare/v0.4.0...v0.4.1)
(2023-10-03)


### Исправления

* исправлена ошибка "Все кнопки заблокированы"
([#63](https://github.com/shizand/statapp/issues/63))
([60f479e](60f479ea7d)),
closes [#62](https://github.com/shizand/statapp/issues/62)

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-03 16:10:40 +03:00
MisterMLiL
60f479ea7d fix: исправлена ошибка "Все кнопки заблокированы" (#63)
Closes #62
2023-10-03 16:05:34 +03:00
github-actions[bot]
7497f71665 chore(main): release 0.4.0 (#51)
🤖 I have created a release *beep* *boop*
---


## [0.4.0](https://github.com/shizand/statapp/compare/v0.3.6...v0.4.0)
(2023-10-03)


### Новые функции

* добавлен дисперсионный анализ
([#46](https://github.com/shizand/statapp/issues/46))
([c77ed6a](c77ed6a82f)),
closes [#30](https://github.com/shizand/statapp/issues/30)
* добавлен Корреляционный анализ
([#54](https://github.com/shizand/statapp/issues/54))
([3a65517](3a655178d4)),
closes [#31](https://github.com/shizand/statapp/issues/31)


### Исправления

* добавлена иконка для окна "О программе"
([#55](https://github.com/shizand/statapp/issues/55))
([023a4a5](023a4a5142))
* добавлены заголовки диалоговых окон
([#49](https://github.com/shizand/statapp/issues/49))
([a3f7c1a](a3f7c1ac0b)),
closes [#44](https://github.com/shizand/statapp/issues/44)
* исправлен баг "index 0 is out of bounds"
([#59](https://github.com/shizand/statapp/issues/59))
([15825c2](15825c2200)),
closes [#43](https://github.com/shizand/statapp/issues/43)
* исправлена генерация значений фактора
([#53](https://github.com/shizand/statapp/issues/53))
([4854a14](4854a14e70)),
closes [#50](https://github.com/shizand/statapp/issues/50)
* исправлены баги с отображением и считыванием исходных данных
([#58](https://github.com/shizand/statapp/issues/58))
([fbf359e](fbf359e515))
* ограничена генерация чисел до сотых
([#48](https://github.com/shizand/statapp/issues/48))
([0779941](0779941dc9)),
closes [#32](https://github.com/shizand/statapp/issues/32)

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-03 15:00:50 +03:00
88ceabf019 chore: добавлены заголовки о лицензии (#60) 2023-10-03 14:47:35 +03:00
MisterMLiL
15825c2200 fix: исправлен баг "index 0 is out of bounds" (#59)
Closes #43
2023-10-03 13:54:47 +03:00
fbf359e515 fix: исправлены баги с отображением и считыванием исходных данных (#58)
Сloses #56, #57.
2023-10-03 13:38:33 +03:00
MisterMLiL
023a4a5142 fix: добавлена иконка для окна "О программе" (#55)
Closes #45.
2023-10-03 12:49:10 +03:00
MisterMLiL
3a655178d4 feat: добавлен Корреляционный анализ (#54)
Closes #31
2023-10-03 12:43:00 +03:00
MisterMLiL
4854a14e70 fix: исправлена генерация значений фактора (#53)
Closes #50
2023-10-03 11:00:34 +03:00
86346b9c5b refactor: переписаны модели (#52)
Closes #47
2023-10-02 21:24:28 +03:00
a3f7c1ac0b fix: добавлены заголовки диалоговых окон (#49)
Closes #44
2023-10-02 21:23:22 +03:00
0779941dc9 fix: ограничена генерация чисел до сотых (#48)
В качестве решения выбрано округление до сотых

Closes #32
2023-10-02 21:23:08 +03:00
0a32e4baee chore: удалил ненужную папку 2023-10-02 11:13:28 +03:00
c77ed6a82f feat: добавлен дисперсионный анализ (#46)
Closes #30
2023-10-01 21:53:06 +03:00
github-actions[bot]
7f01052aa5 chore(main): release 0.3.6 (#40)
🤖 I have created a release *beep* *boop*
---


## [0.3.6](https://github.com/shizand/statapp/compare/v0.3.5...v0.3.6)
(2023-09-29)


### Исправления

* добавляет иконку приложения
([#39](https://github.com/shizand/statapp/issues/39))
([d3cd358](d3cd3589a7))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-29 12:23:53 +03:00
d3cd3589a7 fix: добавляет иконку приложения (#39)
Closes #38.

---------

Co-authored-by: MisterMLiL <eugenelazurenko@gmail.com>
2023-09-29 12:13:24 +03:00
github-actions[bot]
d71bd9843f chore(main): release 0.3.5 (#37)
🤖 I have created a release *beep* *boop*
---


## [0.3.5](https://github.com/shizand/statapp/compare/v0.3.4...v0.3.5)
(2023-09-28)


### Исправления

* исправлен выбор файла для загрузки (Linux)
([c1809a0](c1809a0bc7))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Maxim Slipenko <no-reply@maxim.slipenko.com>
2023-09-28 23:01:25 +03:00
c1809a0bc7 fix: исправлена выбор файла для загрузки (Linux) 2023-09-28 22:55:59 +03:00
github-actions[bot]
83d9faeb85 chore(main): release 0.3.4 (#36)
🤖 I have created a release *beep* *boop*
---


## [0.3.4](https://github.com/shizand/statapp/compare/v0.3.3...v0.3.4)
(2023-09-28)


### Исправления

* исправлена ошибка, при СКО = 0 для фактора
([57dec07](57dec07000))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-28 22:50:15 +03:00
57dec07000 fix: исправлена ошибка, при СКО = 0 для фактора 2023-09-28 22:39:20 +03:00
github-actions[bot]
cca57740a2 chore(main): release 0.3.3 (#29)
🤖 I have created a release *beep* *boop*
---


## [0.3.3](https://github.com/shizand/statapp/compare/v0.3.2...v0.3.3)
(2023-09-28)


### Исправления

* удалена упаковка системных библиотек вместе с программой (Linux)
([b6e10c4](b6e10c4209))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-28 17:37:22 +03:00
b6e10c4209 fix: удалена упаковка системных библиотек вместе с программой (Linux) 2023-09-28 17:25:49 +03:00
github-actions[bot]
67958838fc chore(main): release 0.3.2 (#28)
🤖 I have created a release *beep* *boop*
---


## [0.3.2](https://github.com/shizand/statapp/compare/v0.3.1...v0.3.2)
(2023-09-28)


### Исправления

* исправлена загрузка данных из файла
([8b7fabf](8b7fabfa46))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-28 16:17:12 +03:00
8b7fabfa46 fix: исправлена загрузка данных из файла 2023-09-28 16:12:25 +03:00
f603a77130 ci: ubuntu-latest заменена ubuntu-latest 2023-09-28 16:08:20 +03:00
github-actions[bot]
775c0887ab chore(main): release 0.3.1 (#27)
🤖 I have created a release *beep* *boop*
---


## [0.3.1](https://github.com/shizand/statapp/compare/v0.3.0...v0.3.1)
(2023-09-28)


### Исправления

* исправлена локализация стандартных кнопок
([2b061be](2b061bed2f))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-28 15:45:56 +03:00
2b061bed2f fix: исправлена локализация стандартных кнопок 2023-09-28 15:43:01 +03:00
48ae2644e8 ci: исправил шаблон выбора файлов для загрузки 2023-09-28 15:41:06 +03:00
github-actions[bot]
930424dfb9 chore(main): release 0.3.0 (#25)
🤖 I have created a release *beep* *boop*
---


## [0.3.0](https://github.com/shizand/statapp/compare/v0.2.1...v0.3.0)
(2023-09-28)


### Новые функции

* добавлено чтение и запись исходных данных в файлы .txt, .csv
([#24](https://github.com/shizand/statapp/issues/24))
([b73a3f5](b73a3f5d3b))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-28 15:04:59 +03:00
MisterMLiL
b73a3f5d3b feat: добавлено чтение и запись исходных данных в файлы .txt, .csv (#24)
Closes #22

---------

Co-authored-by: Maxim Slipenko <no-reply@maxim.slipenko.com>
2023-09-28 14:57:41 +03:00
2cd82354a1 ci: добавляет checkout для загрузки файлов 2023-09-28 11:22:39 +03:00
github-actions[bot]
16d8481700 chore(main): release 0.2.1 (#23)
🤖 I have created a release *beep* *boop*
---


## [0.2.1](https://github.com/shizand/statapp/compare/v0.2.0...v0.2.1)
(2023-09-28)


### Исправления

* обновлено окно "О программе"
([#21](https://github.com/shizand/statapp/issues/21))
([37ea556](37ea556ad2))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-28 11:14:06 +03:00
37ea556ad2 fix: обновлено окно "О программе" (#21) 2023-09-28 11:08:53 +03:00
c0fbc0fbd9 ci: убрал лишнюю вложенность 2023-09-28 11:05:21 +03:00
cb34931151 ci: добавил архивацию в zip файлов сборки 2023-09-28 10:53:36 +03:00
bdc530b2e0 ci: исправлен workflow с загрузкой бинарников 2023-09-28 10:42:27 +03:00
github-actions[bot]
fb24389d61 chore(main): release 0.2.0 (#19)
🤖 I have created a release *beep* *boop*
---


## [0.2.0](https://github.com/shizand/statapp/compare/v0.1.0...v0.2.0)
(2023-09-28)


### Новые функции

* добавлена генерация данных
([#13](https://github.com/shizand/statapp/issues/13))
([bdcc2cd](bdcc2cdfe2))


### Исправления

* добавлена поддержка Windows 7
([#18](https://github.com/shizand/statapp/issues/18))
([fe37f33](fe37f33d84))
* добавлена поддержка x86
([179e328](179e3286a2))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-28 10:34:37 +03:00
56e967fecc ci: исправлен workflow 2023-09-28 10:14:26 +03:00
5625ec77f7 ci: исправлен workflow 2023-09-28 10:09:49 +03:00
e521cf4a90 ci: удалена сборка под ubuntu-latext x86 2023-09-28 10:08:41 +03:00
179e3286a2 fix: добавлена поддержка x86 2023-09-28 09:58:15 +03:00
bdcc2cdfe2 feat: добавлена генерация данных (#13)
Closes #2

---------

Co-authored-by: MisterMLiL <99662459+MisterMLiL@users.noreply.github.com>
2023-09-27 13:19:20 +03:00
fe37f33d84 fix: добавлена поддержка Windows 7 (#18) 2023-09-27 10:20:56 +03:00
ffd796a11d ci: добавляет сборку statapp-onefile и statapp (#17) 2023-09-27 09:09:42 +03:00
e102eae964 ci: fix release 2023-09-26 21:52:36 +03:00
b353a6a473 ci: update release.yml 2023-09-26 21:42:22 +03:00
31f0759726 ci: update release.yml 2023-09-26 21:36:34 +03:00
3abbdfd531 ci: update release.yml 2023-09-26 21:23:36 +03:00
0fc8c83413 ci: добавлена сборка с помощью pyinstaller (#16) 2023-09-26 21:17:23 +03:00
62 changed files with 4070 additions and 298 deletions

17
.copyright.tmpl Normal file
View File

@@ -0,0 +1,17 @@
Copyright (c) ${years} 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 <http://www.gnu.org/licenses/>.

2
.gitattributes vendored
View File

@@ -1 +1 @@
statapp/ui/ui_*.py linguist-generated=true
statapp/ui/ui_*.py linguist-generated=true

View File

@@ -13,4 +13,4 @@ jobs:
- uses: actions-ecosystem/action-add-assignees@v1
with:
github_token: ${{ secrets.github_token }}
assignees: ${{ github.actor }}
assignees: ${{ github.actor }}

View File

@@ -18,4 +18,4 @@ jobs:
- uses: pixta-dev/repository-mirroring-action@674e65a7d483ca28dafaacba0d07351bdcc8bd75 # v1.1.1
with:
target_repo_url: "git@gitflic.ru:shizand/statapp.git"
ssh_private_key: ${{ secrets.GITFLIC_SSH }}
ssh_private_key: ${{ secrets.GITFLIC_SSH }}

View File

@@ -9,11 +9,77 @@ permissions:
pull-requests: write
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-20.04, windows-latest]
spec: [statapp-onefile, statapp]
arch: [x86, x64]
include:
- os: ubuntu-20.04
target: linux
- os: windows-latest
target: windows
exclude:
- os: ubuntu-20.04
arch: x86
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
- name: Установка python
uses: actions/setup-python@v4
with:
python-version: 3.8
architecture: ${{ matrix.arch }}
- name: Установка poetry
uses: snok/install-poetry@v1
with:
version: 1.6.1
virtualenvs-create: true
virtualenvs-in-project: true
- uses: actions/cache@v3
with:
path: ./.venv
key: venv-${{ runner.os }}-${{ runner.arch }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
- name: Установка зависимостей
run: poetry install
- name: Сборка
run: poetry run pyinstaller statapp.spec -- -- ${{ matrix.spec == 'statapp-onefile' && '--one-file' || '' }}
- name: Архивация
uses: thedoctor0/zip-release@0.7.1
with:
type: 'zip'
directory: 'dist'
filename: "../${{ matrix.target }}-${{ matrix.arch }}-${{ matrix.spec }}.zip"
- name: Загрузка артефактов
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.target }}-${{ matrix.arch }}-${{ matrix.spec }}
path: '${{ matrix.target }}-${{ matrix.arch }}-${{ matrix.spec }}.zip'
release-please:
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: google-github-actions/release-please-action@v3
id: release
with:
release-type: python
package-name: statapp
changelog-types: '[{"type":"feat","section":"Новые функции","hidden":false},{"type":"fix","section":"Исправления","hidden":false},{"type":"chore", "hidden":true}]'
- uses: actions/checkout@v4
if: ${{ steps.release.outputs.release_created }}
- name: Скачивание артефактов
if: ${{ steps.release.outputs.release_created }}
uses: actions/download-artifact@v3
with:
path: dist
- name: Загрузка в релиз
if: ${{ steps.release.outputs.release_created }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run:
gh release upload ${{ steps.release.outputs.tag_name }} ./dist/**/*.zip

31
.github/workflows/size-labeler.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: labeler
on: [pull_request]
jobs:
labeler:
runs-on: ubuntu-latest
name: Label the PR size
permissions:
issues: write
pull-requests: write
steps:
- uses: codelytv/pr-size-labeler@v1.7.0
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
xs_label: 'size/xs'
xs_max_size: '10'
s_label: 'size/s'
s_max_size: '100'
m_label: 'size/m'
m_max_size: '500'
l_label: 'size/l'
l_max_size: '1000'
xl_label: 'size/xl'
fail_if_xl: 'false'
message_if_xl: >
Этот PR превышает рекомендуемый размер в 1000 строк.
Пожалуйста, убедитесь, что вы НЕ решаете несколько проблем с помощью одного PR.
github_api_url: 'api.github.com'
files_to_ignore: |
"ui_*.py"

4
.gitignore vendored
View File

@@ -34,7 +34,7 @@ MANIFEST
# 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
# *.spec
# Installer logs
pip-log.txt
@@ -173,4 +173,4 @@ poetry.toml
# LSP config files
pyrightconfig.json
# End of https://www.toptal.com/developers/gitignore/api/python
# End of https://www.toptal.com/developers/gitignore/api/python

View File

@@ -11,4 +11,4 @@
</option>
</inspection_tool>
</profile>
</component>
</component>

View File

@@ -3,4 +3,4 @@
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
</component>

5
.idea/misc.xml generated
View File

@@ -1,4 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Poetry (statapp)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Poetry (statapp)" project-jdk-type="Python SDK" />
</project>
</project>

2
.idea/modules.xml generated
View File

@@ -5,4 +5,4 @@
<module fileurl="file://$PROJECT_DIR$/.idea/stat.iml" filepath="$PROJECT_DIR$/.idea/stat.iml" />
</modules>
</component>
</project>
</project>

View File

@@ -7,7 +7,7 @@
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="SDK_NAME" value="Poetry (stat)" />
<option name="SDK_NAME" value="Poetry (statapp)" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
@@ -21,4 +21,4 @@
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
</component>
</component>

2
.idea/stat.iml generated
View File

@@ -5,4 +5,4 @@
<orderEntry type="jdk" jdkName="Poetry (statapp)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
</module>

View File

@@ -1,5 +1,9 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
ci:
autofix_commit_msg: 'chore: [pre-commit.ci] auto fixes from pre-commit.com hooks'
autoupdate_commit_msg: 'chore: [pre-commit.ci] pre-commit autoupdate'
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
@@ -8,3 +12,22 @@ repos:
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- repo: https://github.com/johann-petrak/licenseheaders.git
rev: v0.8.8
hooks:
- id: licenseheaders
args: ["-t", ".copyright.tmpl", "-cy", "-f", "-d", "statapp", "-x", "statapp/_vendor/*.py"]
pass_filenames: false
- repo: local
hooks:
- id: pylint
name: pylint
entry: pylint
language: system
types: [python]
args:
[
"-rn", # Only display messages
"-sn", # Don't display the score
"--rcfile=.pylintrc",
]

27
.pylintrc Normal file
View File

@@ -0,0 +1,27 @@
[MAIN]
ignored-modules=PySide2
extension-pkg-whitelist=PySide2
[MASTER]
init-hook="import sys; sys.path.append('./statapp')"
ignore-patterns=ui_.+\.py
[BASIC]
attr-rgx=^_?[a-z][a-zA-Z0-9]+$|^_?[a-z0-9]+$|^_?[a-z0-9]+(_[a-z0-9]+)*$ # camelCase, lowercase, snake_case
class-attribute-rgx=^_?[a-z][a-zA-Z0-9]+$|^_?[a-z0-9]+$|^_?[a-z0-9]+(_[a-z0-9]+)*$ # camelCase, lowercase
variable-rgx=^_?[a-z][a-zA-Z0-9]+$|^_?[a-z0-9]+$ # camelCase, lowercase
argument-rgx=^_?[a-z][a-zA-Z0-9]+$|^_?[a-z0-9]+$ # camelCase, lowercase
function-rgx=^_?[a-z][a-zA-Z0-9]+$ # camelCase
method-rgx=^_?[a-z][a-zA-Z0-9]+$|^_?on_[a-z][a-zA-Z]+_[a-z][a-zA-Z]+|^__init__$ # camelCase, on_camelCaseWidget_camelCaseSignal and __init__
[SIMILARITIES]
min-similarity-lines=8
[MESSAGES CONTROL]
disable=
unused-argument,
fixme,
missing-docstring,
too-many-public-methods,
too-few-public-methods,
too-many-arguments

View File

@@ -1,5 +1,138 @@
# Changelog
## [0.7.0](https://github.com/shizand/statapp/compare/v0.6.0...v0.7.0) (2023-12-01)
### Новые функции
* добавлена возможность ввода чисел до 5 знаков ([#87](https://github.com/shizand/statapp/issues/87)) ([dc7c487](https://github.com/shizand/statapp/commit/dc7c4875d7e15ad8c9ae5fa16b4b589d156632dd)), closes [#82](https://github.com/shizand/statapp/issues/82)
* Добавлены новые характеристики ([#89](https://github.com/shizand/statapp/issues/89)) ([b12db5a](https://github.com/shizand/statapp/commit/b12db5a3003802830784e26a14097ee9d68a0e64)), closes [#84](https://github.com/shizand/statapp/issues/84)
## [0.6.0](https://github.com/shizand/statapp/compare/v0.5.0...v0.6.0) (2023-10-20)
### Новые функции
* добавлен "Квадратичный полином" ([#81](https://github.com/shizand/statapp/issues/81)) ([9033770](https://github.com/shizand/statapp/commit/9033770406a6163bee794be80da9d5eebf0fcb87))
### Исправления
* исправлен формат сохранения файлов ([#79](https://github.com/shizand/statapp/issues/79)) ([044d2b6](https://github.com/shizand/statapp/commit/044d2b61cf068065a0fa0f33c8b0be94753eb84b))
## [0.5.0](https://github.com/shizand/statapp/compare/v0.4.2...v0.5.0) (2023-10-06)
### Новые функции
* добавлен "Линейный полином" ([#74](https://github.com/shizand/statapp/issues/74)) ([232de9f](https://github.com/shizand/statapp/commit/232de9f145862a1a1e493478ba5fe8a6e4866e5a))
### Исправления
* добавлены переводы для QMessageBox ([#73](https://github.com/shizand/statapp/issues/73)) ([e653c3d](https://github.com/shizand/statapp/commit/e653c3df29355e84f5845d428d2265b902f5abeb))
## [0.4.2](https://github.com/shizand/statapp/compare/v0.4.1...v0.4.2) (2023-10-03)
### Исправления
* добавлены иконки во все окна ([#67](https://github.com/shizand/statapp/issues/67)) ([9310a5e](https://github.com/shizand/statapp/commit/9310a5e6226bfaff4a7fe4fb9395d5cd1553fee9))
## [0.4.1](https://github.com/shizand/statapp/compare/v0.4.0...v0.4.1) (2023-10-03)
### Исправления
* исправлена ошибка "Все кнопки заблокированы" ([#63](https://github.com/shizand/statapp/issues/63)) ([60f479e](https://github.com/shizand/statapp/commit/60f479ea7ddd87f2a8b9d0e62442ba9faf45e9d7)), closes [#62](https://github.com/shizand/statapp/issues/62)
## [0.4.0](https://github.com/shizand/statapp/compare/v0.3.6...v0.4.0) (2023-10-03)
### Новые функции
* добавлен дисперсионный анализ ([#46](https://github.com/shizand/statapp/issues/46)) ([c77ed6a](https://github.com/shizand/statapp/commit/c77ed6a82fefbbf8879ba87d62bd895ebfd1e6fa)), closes [#30](https://github.com/shizand/statapp/issues/30)
* добавлен Корреляционный анализ ([#54](https://github.com/shizand/statapp/issues/54)) ([3a65517](https://github.com/shizand/statapp/commit/3a655178d4e262c7df42b9c1567dcaf997c58071)), closes [#31](https://github.com/shizand/statapp/issues/31)
### Исправления
* добавлена иконка для окна "О программе" ([#55](https://github.com/shizand/statapp/issues/55)) ([023a4a5](https://github.com/shizand/statapp/commit/023a4a514221ab22bb29f87aeccd20b5595d1b2e))
* добавлены заголовки диалоговых окон ([#49](https://github.com/shizand/statapp/issues/49)) ([a3f7c1a](https://github.com/shizand/statapp/commit/a3f7c1ac0b1bd16a2954dce83996c2e3677a7164)), closes [#44](https://github.com/shizand/statapp/issues/44)
* исправлен баг "index 0 is out of bounds" ([#59](https://github.com/shizand/statapp/issues/59)) ([15825c2](https://github.com/shizand/statapp/commit/15825c22007baeceebee98d19515ff038c1c2ae4)), closes [#43](https://github.com/shizand/statapp/issues/43)
* исправлена генерация значений фактора ([#53](https://github.com/shizand/statapp/issues/53)) ([4854a14](https://github.com/shizand/statapp/commit/4854a14e709272fe92463ac43d29f9a73a5f9875)), closes [#50](https://github.com/shizand/statapp/issues/50)
* исправлены баги с отображением и считыванием исходных данных ([#58](https://github.com/shizand/statapp/issues/58)) ([fbf359e](https://github.com/shizand/statapp/commit/fbf359e515f962dd5e079d7a13b5b7dc39339764))
* ограничена генерация чисел до сотых ([#48](https://github.com/shizand/statapp/issues/48)) ([0779941](https://github.com/shizand/statapp/commit/0779941dc9d9e83c35aff9f07a563da31e5c62c4)), closes [#32](https://github.com/shizand/statapp/issues/32)
## [0.3.6](https://github.com/shizand/statapp/compare/v0.3.5...v0.3.6) (2023-09-29)
### Исправления
* добавляет иконку приложения ([#39](https://github.com/shizand/statapp/issues/39)) ([d3cd358](https://github.com/shizand/statapp/commit/d3cd3589a781df47e6d0e9d669a376aefd9090fe))
## [0.3.5](https://github.com/shizand/statapp/compare/v0.3.4...v0.3.5) (2023-09-28)
### Исправления
* исправлен выбор файла для загрузки (Linux) ([c1809a0](https://github.com/shizand/statapp/commit/c1809a0bc778fde52aa392fb6656b0fd2ffeabe5))
## [0.3.4](https://github.com/shizand/statapp/compare/v0.3.3...v0.3.4) (2023-09-28)
### Исправления
* исправлена ошибка, при СКО = 0 для фактора ([57dec07](https://github.com/shizand/statapp/commit/57dec07000e78d694986b1b90de42b84db14c1a7))
## [0.3.3](https://github.com/shizand/statapp/compare/v0.3.2...v0.3.3) (2023-09-28)
### Исправления
* удалена упаковка системных библиотек вместе с программой (Linux) ([b6e10c4](https://github.com/shizand/statapp/commit/b6e10c420958cf554c1953f30c4cfd9dcadebd1a))
## [0.3.2](https://github.com/shizand/statapp/compare/v0.3.1...v0.3.2) (2023-09-28)
### Исправления
* исправлена загрузка данных из файла ([8b7fabf](https://github.com/shizand/statapp/commit/8b7fabfa46d546b1969bdf9f4800cb0e06fa186a))
## [0.3.1](https://github.com/shizand/statapp/compare/v0.3.0...v0.3.1) (2023-09-28)
### Исправления
* исправлена локализация стандартных кнопок ([2b061be](https://github.com/shizand/statapp/commit/2b061bed2f6343fc2feb87472afc4c9a051b30a9))
## [0.3.0](https://github.com/shizand/statapp/compare/v0.2.1...v0.3.0) (2023-09-28)
### Новые функции
* добавлено чтение и запись исходных данных в файлы .txt, .csv ([#24](https://github.com/shizand/statapp/issues/24)) ([b73a3f5](https://github.com/shizand/statapp/commit/b73a3f5d3ba5707f0bdb816452ad7f59c0da8290))
## [0.2.1](https://github.com/shizand/statapp/compare/v0.2.0...v0.2.1) (2023-09-28)
### Исправления
* обновлено окно "О программе" ([#21](https://github.com/shizand/statapp/issues/21)) ([37ea556](https://github.com/shizand/statapp/commit/37ea556ad20c7b2d3b346e0eafd583c60121d594))
## [0.2.0](https://github.com/shizand/statapp/compare/v0.1.0...v0.2.0) (2023-09-28)
### Новые функции
* добавлена генерация данных ([#13](https://github.com/shizand/statapp/issues/13)) ([bdcc2cd](https://github.com/shizand/statapp/commit/bdcc2cdfe2001c81b1cbc201d4269e3b3d506b3a))
### Исправления
* добавлена поддержка Windows 7 ([#18](https://github.com/shizand/statapp/issues/18)) ([fe37f33](https://github.com/shizand/statapp/commit/fe37f33d8457ebcdeaa63d4819d3d9814a4bd2f9))
* добавлена поддержка x86 ([179e328](https://github.com/shizand/statapp/commit/179e3286a2fb06064d37bf0d46db78204eaf0b00))
## 0.1.0 (2023-09-26)

View File

@@ -1 +1 @@
* @Maks1mS @MisterMLiL
* @Maks1mS @MisterMLiL

View File

@@ -0,0 +1,60 @@
# Statapp
![Release info](https://img.shields.io/github/v/release/shizand/statapp)
![Python version](https://img.shields.io/badge/python-3.8-blue.svg)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/c4e370d74a8a4575b79afa8b9b74d130)](https://app.codacy.com/gh/shizand/statapp/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
![License info](https://img.shields.io/github/license/shizand/statapp)
Автоматизированное программное средство по статистическому анализу и регрессионному моделированию. Является идейным продолжателем программы STAT.exe (Produced by Reutov V.N., Donetsk University, 1990).
Разработано двумя студентами ФГБОУ ВО «ДонНТУ» для своего университета.
## Поддерживаемые ОС и архитектуры
В теории, должно работать на любой архитектуре и ОС, где запускается Python 3.8 и есть Qt 5.
Работоспособность проверена на x64:
* на Windows 7, 10;
* на ALT Linux 10.2.
## Установка
Программа распространяется с помощью [PyInstaller](https://pyinstaller.org/en/stable/).
Существует две версиии: **statapp** и **statapp-onefile**.
Различия в том, что onefile версия поставляется одним единственным бинарным файлом. На Windows системах с включенным антивирусом это может вызывать [некоторые проблемы](https://qna.habr.com/q/988553).
### Готовые двоичные файлы
[Скачайте архив](https://github.com/shizand/statapp/releases) под вашу платформу и распакуйте в любом месте.
### Сборка из исходников
В этом проекте используется [poetry](https://python-poetry.org/).
```bash
poetry install
pyinstaller statapp.spec # или pyinstaller statapp.spec -- --one-file
```
## Использование
<!-- TODO -->
## Чем я могу помочь проекту?
* [Сообщить об ошибке](https://github.com/shizand/statapp/issues/new?labels=%D0%B1%D0%B0%D0%B3)
## Исходный код
Исходный код доступен на [GitHub](https://github.com/shizand/statapp).
Также есть зеркала:
* [GitFic](https://gitflic.ru/project/shizand/statapp);
* [Gitea сервер](https://git.slipenko.com/shizand/statapp).
## Лицензия
[GPL-3.0 © Maxim Slipenko, Eugene Lazurenko.](https://github.com/shizand/statapp/blob/main/LICENSE)

1152
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "statapp"
version = "0.1.0"
version = "0.7.0"
description = ""
authors = [
"Maxim Slipenko <statapp@maks1ms.addy.io>"
@@ -8,11 +8,18 @@ authors = [
readme = "README.md"
[tool.poetry.dependencies]
python = ">=3.9,<3.12"
pyside6 = "^6.4.0"
pandas = "^2.1.1"
numpy = "^1.26.0"
# windows 7 support
python = ">=3.8,<3.9"
pre-commit = "^3.4.0"
pyinstaller = "^6.0.0"
pyside2 = "^5.15.2.1"
pandas = { version = "^2", markers = "python_version < '3.9'" }
pylint = { version = "^2", markers = "python_version < '3.9'" }
# scipy = { version = "^1", markers = "python_version < '3.9'" }
# openpyxl = "^3.1.2"
sympy = "^1.12"
matplotlib = "^3.7.0"
pillow = "9.5"
[build-system]

View File

@@ -1,3 +0,0 @@
#!/usr/bin/env bash
poetry version "$@"

108
statapp.spec Normal file
View File

@@ -0,0 +1,108 @@
# -*- mode: python ; coding: utf-8 -*-
import argparse
import sys
import typing
from pprint import pprint
if typing.TYPE_CHECKING:
from PyInstaller.building.api import COLLECT, EXE, MERGE, PYZ # noqa: F401
from PyInstaller.building.build_main import Analysis # noqa: F401
from PyInstaller.building.datastruct import TOC, Target, Tree # noqa: F401
from PyInstaller.building.osx import BUNDLE # noqa: F401
from PyInstaller.building.splash import Splash # noqa: F401
from PyInstaller.utils.hooks import copy_metadata
parser = argparse.ArgumentParser()
parser.add_argument("--one-file", action="store_true")
options = parser.parse_args()
datas = [('statapp/ui/images/*', 'ui/images')]
datas += copy_metadata('statapp')
a = Analysis(
['statapp/__main__.py'],
pathex=[],
binaries=[],
datas=datas,
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
)
prev_binaries = set(a.binaries)
if sys.platform in ('linux', 'darwin'):
a.exclude_system_libraries(list_of_exceptions=[]) # glob expression
print('\n\nSTRIPPED SYSTEM LIBS')
pprint(sorted(set(prev_binaries) - set(a.binaries)))
LOCALES = ['ru', 'en']
def remove_unused_translation(item):
dest = str(item[0])
if not dest.startswith('PySide2/Qt/translations'):
return True
for l in LOCALES:
if l in dest:
return True
return False
a.datas = list(filter(remove_unused_translation, a.datas))
pyz = PYZ(a.pure)
if options.one_file:
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='statapp',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon='statapp/ui/images/logo.ico',
)
else:
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='statapp',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon='statapp/ui/images/logo.ico',
)
coll = COLLECT(
exe,
a.binaries,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='statapp',
)

View File

@@ -1,15 +1,43 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
import sys
from PySide6.QtWidgets import QApplication
from PySide2 import QtCore
from PySide2.QtWidgets import QApplication
from statapp.main_window import MainWindow
def main():
app = QApplication(sys.argv)
translator = QtCore.QTranslator(app)
locale = QtCore.QLocale.system().name()
path = QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath)
translator.load(f'qt_{locale}', path)
translator.load(f'qtbase_{locale}', path)
app.installTranslator(translator)
window = MainWindow()
window.show()
return app.exec()
return app.exec_()
if __name__ == "__main__":
sys.exit(main())

View File

@@ -0,0 +1,124 @@
# Copyright (c) 2023 Matthew Rocklin
# All rights reserved.
# This source code is distributed under the terms of the BSD license,
# which allows you to use, modify, and distribute it
# as long as you comply with the license terms.
# In addition, this code has been modified by Maxim Slipenko and
# is now also licensed under the GPL-3.0.
# See the GPL-3.0 license for details.
import itertools
from numpy import linalg, zeros, ones, hstack, asarray
from sympy import symbols, Mul, Add, S
def basisVector(n, i):
""" Return an array like [0, 0, ..., 1, ..., 0, 0]
>>> from statapp._vendor.multipolyfit import basisVector
>>> basis_vector(3, 1)
array([0, 1, 0])
>>> basisVector(5, 4)
array([0, 0, 0, 0, 1])
"""
x = zeros(n, dtype=int)
x[i] = 1
return x
def asTall(x):
""" Turns a row vector into a column vector """
return x.reshape(x.shape + (1,))
def multipolyfit(xs, y, deg, full=False, modelOut=False, powersOut=False):
# pylint: disable-msg=too-many-locals
"""
Least squares multivariate polynomial fit
Fit a polynomial like ``y = a**2 + 3a - 2ab + 4b**2 - 1``
with many covariates a, b, c, ...
Parameters
----------
xs : array_like, shape (M, k)
x-coordinates of the k covariates over the M sample points
y : array_like, shape(M,)
y-coordinates of the sample points.
deg : int
Degree o fthe fitting polynomial
modelOut : bool (defaults to True)
If True return a callable function
If False return an array of coefficients
powersOut : bool (defaults to False)
Returns the meaning of each of the coefficients in the form of an
iterator that gives the powers over the inputs and 1
For example if xs corresponds to the covariates a,b,c then the array
[1, 2, 1, 0] corresponds to 1**1 * a**2 * b**1 * c**0
See Also
--------
numpy.polyfit
"""
# pylin
y = asarray(y).squeeze()
# rows = y.shape[0]
xs = asarray(xs)
numCovariates = xs.shape[1]
xs = hstack((ones((xs.shape[0], 1), dtype=xs.dtype) , xs))
generators = [basisVector(numCovariates + 1, i)
for i in range(numCovariates+1)]
# All combinations of degrees
powers = [sum(x) for x in itertools.combinations_with_replacement(generators, deg)]
# Raise data to specified degree pattern, stack in order
a = hstack(asarray([asTall((xs ** p).prod(1)) for p in powers]))
result = linalg.lstsq(a, y, rcond=None)
beta = result[0]
if modelOut:
return mkModel(beta, powers)
if powersOut:
return beta, powers
if full:
return result, powers, a
return beta
def mkModel(beta, powers):
""" Create a callable python function out of beta/powers from multipolyfit
This function is callable from within multipolyfit using the model_out flag
"""
# Create a function that takes in many x values
# and returns an approximate y value
def model(*args):
numCovariates = len(powers[0]) - 1
if len(args) != numCovariates:
raise ValueError(f"Expected {numCovariates} inputs")
xs = asarray((1,) + args)
return sum(coeff * (xs**p).prod()
for p, coeff in zip(powers, beta))
return model
def mkSympyFunction(beta, powers):
terms = getTerms(powers)
return Add(*[coeff * term for term, coeff in zip(terms, beta)])
def getTerms(powers):
numCovariates = len(powers[0])
xs = (S.One,) + symbols(f'x1:{numCovariates}')
terms = [Mul(*[x ** deg for x, deg in zip(xs, power)]) for power in powers]
return terms

View File

@@ -1,21 +1,52 @@
from PySide6.QtGui import QMovie
from PySide6.QtWidgets import QMainWindow
#
# 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 <http://www.gnu.org/licenses/>.
#
import sys
from PySide2.QtGui import QMovie
from PySide2.QtWidgets import QMainWindow
from statapp.ui.ui_about_window import Ui_AboutWindow
from statapp.utils import resourcePath, addIcon
if sys.version_info < (3, 8):
import importlib_metadata
else:
import importlib.metadata as importlib_metadata
class AboutWindow(QMainWindow):
pixmap = None
movie = None
def __init__(self):
super().__init__()
self.ui = Ui_AboutWindow()
self.ui.setupUi(self)
image_path = 'statapp\\images\\sticker.gif'
movie = QMovie(image_path)
gifPath = resourcePath('ui/images/sticker.gif')
movie = QMovie(gifPath)
self.ui.labelgif.setMovie(movie)
movie.start()
self.pixmap = movie
self.movie = movie
self.setFixedSize(self.size())
version = importlib_metadata.version(__package__ or __name__)
self.ui.versionLabel.setText(f"Версия: {version}")
addIcon(self)

137
statapp/calculations.py Normal file
View File

@@ -0,0 +1,137 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
from dataclasses import dataclass
import numpy as np
import pandas as pd
from statapp._vendor.multipolyfit import multipolyfit, getTerms
DIRECT_LINK = 0
INDIRECT_LINK = 1
def generateYValues(mean, std, count):
return np.random.normal(mean, std, size=(count, 1))
def generateXValues(mean, std, typeConnection, yColumn):
yMean = np.mean(yColumn)
values = []
for y in yColumn:
raz = np.abs(mean - np.random.normal(mean, std))
if typeConnection == INDIRECT_LINK:
raz *= -1
if y > yMean:
x = mean + raz
elif y < yMean:
x = mean - raz
else:
x = mean
values.append(x)
res = np.array(values)
return res.reshape(len(res), 1)
def varianceAnalysis(data):
return np.array([
[np.mean(col), np.std(col), np.min(col), np.max(col)] for col in data.T
])
def correlationAnalysis(data):
return pd.DataFrame(data).corr().to_numpy()
@dataclass()
class RegressionResult:
"""
Attributes:
paramsAndImportance (np.ndarray): Параметры модели. Первая колонка -
residualVariance (np.float64): Остаточная дисперсия
scaledResidualVariance (np.float64): Остаточная дисперсия (масштабированная)
monomials (list): Список одночленов в строковом виде без коэффициентов. Свободный член - c
"""
paramsAndImportance: np.ndarray
residualVariance: np.float64
scaledResidualVariance: np.float64
rSquared: np.float64
fStatistic: np.float64
monomials: list
def commonPolynom(inputData, deg) -> RegressionResult:
x = inputData[:, 1:]
y = inputData[:, 0]
result, powers, data = multipolyfit(x, y, deg, full=True)
(out, mse, scaledResidualVariance,
rSquared, fStatistic) = calculateStats(data, result[0], result[1], y)
return RegressionResult(
out.to_numpy(),
np.float64(mse),
np.float64(scaledResidualVariance),
np.float64(rSquared),
np.float64(fStatistic),
['c' if str(x) == '1' else str(x) for x in getTerms(powers)]
)
def linearPolynom(inputData) -> RegressionResult:
return commonPolynom(inputData, 1)
def squaredPolynom(inputData) -> RegressionResult:
return commonPolynom(inputData, 2)
def calculateStats(data, params, residues, y):
# pylint: disable-msg=too-many-locals
k = len(params) # Количество оцениваемых параметров (коэффициентов)
n = len(data) # Количество наблюдений
# Степень свободы (degrees of freedom) для остатков
dof = n - k # Количество наблюдений минус количество оцениваемых параметров
# Остаточная дисперсия (Mean Squared Error, MSE)
mse = residues / dof
# Среднее значение остатков
meanResiduals = np.sum(residues) / dof
# Масштабированная остаточная дисперсия
scaledResidualVariance = residues / meanResiduals ** 2
# Ковариационная матрица коэффициентов
cov = mse * np.diagonal(np.linalg.inv(data.T @ data))
# Стандартные ошибки коэффициентов
se = np.sqrt(cov)
# T-статистики для каждого коэффициента регрессии
tStatistics = params / se
# R-squared (коэффициент множественной детерминации)
sst = np.sum((y - np.mean(y)) ** 2) # Сумма квадратов отклонений
rSquared = 1 - (mse[0] / sst)
# F-statistic (статистика Фишера)
fStatistic = (rSquared / (k - 1)) / ((1 - rSquared) / (n - k))
out = pd.DataFrame()
out[0] = params
out[1] = tStatistics
return out, mse[0], scaledResidualVariance, rSquared, fStatistic

20
statapp/constants.py Normal file
View File

@@ -0,0 +1,20 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
NUMBERS_PRECISION = 5

View File

@@ -0,0 +1,53 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
from PySide2 import QtCore
from PySide2.QtCore import QSize
from PySide2.QtGui import QIcon
from PySide2.QtWidgets import QDialog, QHeaderView
from statapp.calculations import correlationAnalysis
from statapp.constants import NUMBERS_PRECISION
from statapp.mathtex_header_view import MathTexHeaderView
from statapp.models.correlation_analysis_model import CorrelationAnalysisModel
from statapp.ui.ui_correlation_analysis_window import Ui_CorrelationAnalysisWindow
from statapp.utils import resourcePath
class CorrelationAnalysisWindow(QDialog):
def __init__(self, data):
super().__init__()
self.ui = Ui_CorrelationAnalysisWindow()
self.ui.setupUi(self)
res = correlationAnalysis(data)
self.model = CorrelationAnalysisModel(res.round(NUMBERS_PRECISION))
self.ui.tableView.setModel(self.model)
self.ui.tableView.setVerticalHeader(
MathTexHeaderView(self.ui.tableView)
)
self.ui.tableView.setHorizontalHeader(
MathTexHeaderView(self.ui.tableView,orientation=QtCore.Qt.Horizontal)
)
header = self.ui.tableView.horizontalHeader()
header.setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
icon = QIcon()
icon.addFile(resourcePath("ui/images/logo.ico"), QSize(), QIcon.Normal, QIcon.Off)
self.setWindowIcon(icon)

View File

@@ -0,0 +1,55 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
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
from statapp.utils import addIcon
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)
addIcon(self)
@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()

View File

@@ -0,0 +1,46 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
from PySide2.QtCore import Slot
from PySide2.QtWidgets import QDialog
from statapp.ui.ui_generate_window import Ui_GenerateWindow
from statapp.utils import addIcon
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)
addIcon(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()

View File

@@ -1,18 +1,217 @@
from PySide6.QtCore import Slot
from PySide6.QtWidgets import QMainWindow
#
# 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 <http://www.gnu.org/licenses/>.
#
import numpy as np
from PySide2 import QtCore
from PySide2.QtCore import Slot
from PySide2.QtWidgets import QMainWindow, QMessageBox
from statapp.calculations import generateXValues, generateYValues
from statapp.constants import NUMBERS_PRECISION
from statapp.generate_factor_window import GenerateFactorWindow
from statapp.polynoms.linear_polynom_window import LinearPolynomWindow
from statapp.mathtex_header_view import MathTexHeaderView
from statapp.models.input_values_model import InputValuesModel
from statapp.generate_window import GenerateWindow
from statapp.about_window import AboutWindow
from statapp.models.fileslc_model import FileSLCModel
from statapp.polynoms.squared_polynom_window import SquaredPolynomWindow
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
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
addIcon(self)
self.ui.generateXaction.setEnabled(False)
self.ui.varianceAnalysisAction.setEnabled(False)
self.ui.correlationAnalisisAction.setEnabled(False)
self.mainActions = [
self.ui.varianceAnalysisAction,
self.ui.correlationAnalisisAction,
self.ui.linearPolynomAction,
self.ui.squaredPolynomAction,
]
self.aboutWindow = None
self.isDataChanged = False
self.model = InputValuesModel()
self.fileModel = FileSLCModel()
self.ui.tableView.setItemDelegate(FloatDelegate())
self.ui.tableView.setModel(self.model)
self.ui.tableView.setHorizontalHeader(
MathTexHeaderView(self.ui.tableView, orientation=QtCore.Qt.Horizontal)
)
self.model.layoutChanged.connect(self.updateActionsEnabled)
self.updateActionsEnabled()
#
# Для быстрой отладки
# n = 10
# y = generateYValues(100, 5, n)
# x1 = generateXValues(20, 2, 0, y)
# x2 = generateXValues(10, 1, 0, y)
# self.model.updateAllData(np.concatenate([y, x1, x2], axis=1))
def updateActionsEnabled(self):
data = self.model.getData()
# есть только отклик
if data.shape[1] == 1:
self.ui.generateXaction.setEnabled(True)
self.setEnabledMainActions(False)
# есть отклик и фактор(ы)
elif data.shape[1] > 1:
self.ui.generateXaction.setEnabled(True)
self.setEnabledMainActions(True)
else:
self.ui.generateXaction.setEnabled(False)
self.setEnabledMainActions(False)
def setEnabledMainActions(self, enabled):
for action in self.mainActions:
action.setEnabled(enabled)
@Slot()
def on_openfileaction_triggered(self):
currentData = self.model.getData()
data = np.array([])
if currentData.size > 1:
file = ''
if self.fileModel.fileName:
file = '\nФайл сохранения: ' + self.fileModel.fileName
msgBox = buildMessageBox \
('Сохранение данных',
"Сохранить данные?" + file,
QMessageBox.Question,
QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel,
QMessageBox.Cancel)
reply = msgBox.exec_()
if reply == QMessageBox.StandardButton.Yes:
self.fileModel.saveFile(self.model.getData())
data = self.fileModel.loadFile()
if data is not None and data.shape[0] > 0:
self.model.updateAllData(data)
self.isDataChanged = False
elif reply == QMessageBox.StandardButton.Cancel:
return
else:
data = self.fileModel.loadFile()
if data is not None and data.shape[0] > 0:
self.model.updateAllData(data)
self.isDataChanged = False
else:
data = self.fileModel.loadFile()
if data is not None and data.shape[0] > 0:
self.model.updateAllData(data)
self.isDataChanged = False
@Slot()
def on_savefileaction_triggered(self):
self.isDataChanged = not self.fileModel.saveFile(self.model.getData())
@Slot()
def on_closefileaction_triggered(self):
self.fileModel.closeFile()
self.isDataChanged = False
@Slot()
def on_generateYaction_triggered(self):
gw = GenerateWindow()
if gw.exec():
y = generateYValues(gw.mat, gw.deviation, gw.count)
self.model.updateAllData(y.round(NUMBERS_PRECISION))
self.isDataChanged = True
@Slot()
def on_generateXaction_triggered(self):
gfw = GenerateFactorWindow()
if gfw.exec():
data = self.model.getData()
y = self.model.getY()
xValues = generateXValues(gfw.mat, gfw.deviation, gfw.typeConnection, y)
data = np.concatenate((data, xValues.round(NUMBERS_PRECISION)), axis=1)
self.model.updateAllData(data)
self.isDataChanged = True
@Slot()
def on_aboutmenuaction_triggered(self):
global about_window
about_window = AboutWindow()
about_window.show()
self.aboutWindow = AboutWindow()
self.aboutWindow.show()
@Slot()
def on_varianceAnalysisAction_triggered(self):
dw = VarianceAnalysisWindow(self.model.getData())
dw.exec()
@Slot()
def on_correlationAnalisisAction_triggered(self):
dw = CorrelationAnalysisWindow(self.model.getData())
dw.exec()
@Slot()
def on_linearPolynomAction_triggered(self):
dw = LinearPolynomWindow(self.model.getData())
dw.exec()
@Slot()
def on_squaredPolynomAction_triggered(self):
dw = SquaredPolynomWindow(self.model.getData())
dw.exec()
def closeEvent(self, event):
if self.isDataChanged:
file = ''
if self.fileModel.fileName:
file = '\nФайл сохранения: ' + self.fileModel.fileName
msgBox = buildMessageBox \
('Завершение работы',
"Сохранить данные?" + file,
QMessageBox.Question,
QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel,
QMessageBox.Cancel)
reply = msgBox.exec_()
if reply == QMessageBox.StandardButton.Yes:
self.fileModel.saveFile(self.model.getData())
event.accept()
elif reply == QMessageBox.StandardButton.No:
event.accept()
else:
event.ignore()
else:
event.accept()

View File

@@ -0,0 +1,107 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
import matplotlib.pyplot as plt
import matplotlib as mpl
import sympy
from PySide2 import QtCore, QtGui
from PySide2.QtCore import Qt
from PySide2.QtWidgets import QHeaderView, QStyleOptionHeader, QStyle
from matplotlib.backends.backend_agg import FigureCanvasAgg
# Основано на https://stackoverflow.com/questions/32035251/
plt.rc('mathtext', fontset='cm')
def mathTexToQPixMap(mathTex, fs):
# ---- set up a mpl figure instance ----
fig = mpl.figure.Figure()
fig.patch.set_facecolor('none')
fig.set_canvas(FigureCanvasAgg(fig))
renderer = fig.canvas.get_renderer()
# ---- plot the mathTex expression ----
ax = fig.add_axes([0, 0, 1, 1])
ax.axis('off')
ax.patch.set_facecolor('none')
t = ax.text(0, 0, f'${mathTex}$', ha='left', va='bottom', fontsize=fs)
# ---- fit figure size to text artist ----
fWidth, fHeight = fig.get_size_inches()
figBBox = fig.get_window_extent(renderer)
textBBox = t.get_window_extent(renderer)
tightFWidth = textBBox.width * fWidth / figBBox.width
tightFHeight = textBBox.height * fHeight / figBBox.height
fig.set_size_inches(tightFWidth, tightFHeight)
# ---- convert mpl figure to QPixmap ----
buf, size = fig.canvas.print_to_buffer()
return QtGui.QPixmap(
QtGui.QImage.rgbSwapped(
QtGui.QImage(
buf, size[0], size[1], QtGui.QImage.Format_ARGB32
)
)
)
class CacheQPixMap(dict):
def get(self, __key):
v = super().get(__key)
if v is None:
v = mathTexToQPixMap(sympy.latex(sympy.sympify(__key)), 14)
super().__setitem__(__key, v)
return v
class MathTexHeaderView(QHeaderView):
def __init__(self, view, orientation=QtCore.Qt.Vertical):
super().__init__(orientation, view)
if orientation == QtCore.Qt.Vertical:
self.setStyleSheet(
"QHeaderView::section { padding-left: 15px; padding-right: 15px }"
)
self.converter = CacheQPixMap()
def paintSection(self, painter, rect, logicalIndex):
opt = QStyleOptionHeader()
self.initStyleOption(opt)
opt.rect = rect
opt.section = logicalIndex
opt.text = ""
mousePos = self.mapFromGlobal(QtGui.QCursor.pos())
if rect.contains(mousePos):
opt.state |= QStyle.State_MouseOver
painter.save()
self.style().drawControl(QStyle.CE_Header, opt, painter, self)
painter.restore()
data = self.model().headerData(logicalIndex, self.orientation(), Qt.DisplayRole)
if data:
qPixMap = self.converter.get(data)
xPix = (rect.width() - qPixMap.size().width()) / 2. + rect.x()
yPix = (rect.height() - qPixMap.size().height()) / 2. + rect.y()
rect = QtCore.QRect(xPix, yPix, qPixMap.size().width(),
qPixMap.size().height())
painter.drawPixmap(rect, qPixMap)

View File

@@ -0,0 +1,54 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
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)

View File

@@ -0,0 +1,39 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
from PySide2.QtCore import QModelIndex, Qt
from statapp.models.ro_table_model import ROTableModel
from statapp.models.utils import yxHeader
class CorrelationAnalysisModel(ROTableModel):
def __init__(self, data):
super().__init__(data)
def getHorizontalHeader(self):
return yxHeader(self.columnCount(QModelIndex()))
def getVerticalHeader(self):
return yxHeader(self.rowCount(QModelIndex()))
def data(self, index, role):
if role == Qt.DisplayRole and index.column() <= index.row():
return super().data(index, role)
return None

View File

@@ -0,0 +1,49 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
import numpy as np
from PySide2.QtCore import Qt
from statapp.models.ro_table_model import ROTableModel
class EditableTableModel(ROTableModel):
def __init__(self, data=np.array([[]], dtype=np.float32)):
super().__init__()
self._data = data
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 data(self, index, role):
if role in (Qt.DisplayRole, Qt.EditRole):
return super().data(index, Qt.DisplayRole)
return None

View File

@@ -0,0 +1,85 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
import numpy as np
from PySide2.QtWidgets import QFileDialog, QMessageBox
from statapp.constants import NUMBERS_PRECISION
from statapp.utils import buildMessageBox
class FileSLCModel:
def __init__(self):
super().__init__()
self.fileName = None
def saveFile(self, data):
# pylint: disable=duplicate-code
if self.fileName:
file = '\nФайл сохранения: ' + self.fileName
msgBox = buildMessageBox \
('Сохранение данных',
"Сохранить данные в текущий файл?" + file,
QMessageBox.Question,
QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel,
QMessageBox.Cancel)
reply = msgBox.exec_()
if reply == QMessageBox.StandardButton.Yes:
np.savetxt(self.fileName, data, delimiter=",", fmt='%10.5f')
return True
if reply == QMessageBox.StandardButton.No:
self.fileName, _ = QFileDialog.getSaveFileName(
None, "Сохранить файл", "", "Text Files (*.txt);;CSV Files (*.csv)"
)
if self.fileName:
np.savetxt(self.fileName, data, delimiter=",", fmt='%10.5f')
return True
else:
self.fileName, _ = QFileDialog.getSaveFileName(
None, "Сохранить файл", "", "Text Files (*.txt);;CSV Files (*.csv)"
)
if self.fileName:
np.savetxt(self.fileName, data, delimiter=",", fmt=f"%.{NUMBERS_PRECISION}f")
return True
return False
def loadFile(self):
self.fileName, _ = QFileDialog.getOpenFileName(
None, "Загрузить файл", "", "Files (*.txt *.csv)"
)
if self.fileName:
try:
content = np.genfromtxt(self.fileName, delimiter=',', invalid_raise=True, ndmin=2)
except ValueError:
QMessageBox.warning \
(None,
'Ошибка',
"Ошибка чтения файла!\nФайл нельзя открыть или файл неверного формата")
self.fileName = None
return None
return content
return None
def closeFile(self):
self.fileName = None

View File

@@ -0,0 +1,35 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
import numpy as np
from PySide2.QtCore import QModelIndex
from statapp.models.editable_table_model import EditableTableModel
from statapp.models.utils import yxHeader
class InputValuesModel(EditableTableModel):
def __init__(self, data=np.array([[]], dtype=np.float32)):
super().__init__(data)
def getHorizontalHeader(self):
return yxHeader(self.columnCount(QModelIndex()))
def getY(self):
return self._data[:, 0]

View File

@@ -0,0 +1,34 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
from statapp.calculations import RegressionResult
from statapp.models.ro_table_model import ROTableModel
class RegressionResultModel(ROTableModel):
def __init__(self, result: RegressionResult):
data = result.paramsAndImportance
super().__init__(data)
self._monomials = result.monomials
def getHorizontalHeader(self):
return ['Коэффициент регрессии', 'Коэффициент значимости']
def getVerticalHeader(self):
return self._monomials

View File

@@ -0,0 +1,67 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
import numpy as np
from PySide2 import QtCore
from PySide2.QtCore import Qt
from statapp.utils import safeListGet
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 safeListGet(self._headers[orientation](), section, None)
return None
def getData(self):
return self._data
def data(self, index, role):
if role == Qt.DisplayRole:
return float(self._data[index.row(), index.column()])
return None

21
statapp/models/utils.py Normal file
View File

@@ -0,0 +1,21 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
def yxHeader(count):
return ['y'] + [f'x{i}' for i in range(1, count)]

View File

@@ -0,0 +1,34 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
from PySide2.QtCore import QModelIndex
from statapp.models.ro_table_model import ROTableModel
from statapp.models.utils import yxHeader
class VarianceAnalysisModel(ROTableModel):
def __init__(self, data):
super().__init__(data)
def getHorizontalHeader(self):
return ['Мат. ожидание', 'Среднекв. отклонение', 'Минимум', 'Максимум']
def getVerticalHeader(self):
return yxHeader(self.rowCount(QModelIndex()))

View File

@@ -0,0 +1,27 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
from statapp.calculations import linearPolynom
from statapp.polynoms.polynom_window import PolynomWindow
class LinearPolynomWindow(PolynomWindow):
def __init__(self, data):
result = linearPolynom(data)
super().__init__(result, "Линейный полином")

View File

@@ -0,0 +1,45 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
from PySide2.QtWidgets import QDialog, QHeaderView
from statapp.mathtex_header_view import MathTexHeaderView
from statapp.models.regression_result_model import RegressionResultModel
from statapp.ui.ui_polynom_window import Ui_PolynomWindow
from statapp.utils import addIcon, FloatDelegate
class PolynomWindow(QDialog):
def __init__(self, result, windowTitle):
super().__init__()
self.ui = Ui_PolynomWindow()
self.ui.setupUi(self)
addIcon(self)
self.setWindowTitle(windowTitle)
self.model = RegressionResultModel(result)
self.ui.tableView.setItemDelegate(FloatDelegate())
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))

View File

@@ -0,0 +1,27 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
from statapp.calculations import squaredPolynom
from statapp.polynoms.polynom_window import PolynomWindow
class SquaredPolynomWindow(PolynomWindow):
def __init__(self, data):
result = squaredPolynom(data)
super().__init__(result, "Квадратичный полином")

View File

@@ -9,7 +9,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>476</width>
<width>483</width>
<height>543</height>
</rect>
</property>
@@ -23,70 +23,7 @@
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="4" column="1">
<widget class="QLabel" name="labelowner">
<property name="font">
<font>
<pointsize>14</pointsize>
<italic>false</italic>
<bold>false</bold>
<underline>false</underline>
<strikeout>false</strikeout>
<stylestrategy>PreferDefault</stylestrategy>
<kerning>true</kerning>
</font>
</property>
<property name="text">
<string>Донецкий Национальный Технический Университет</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="labeldevelopers">
<property name="font">
<font>
<pointsize>14</pointsize>
<italic>false</italic>
<bold>false</bold>
<underline>false</underline>
<strikeout>false</strikeout>
<stylestrategy>PreferDefault</stylestrategy>
<kerning>true</kerning>
</font>
</property>
<property name="text">
<string>Разработчики: Слипенко М., Лазуренко Е.</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="labelbasegigamen">
<property name="font">
<font>
<pointsize>14</pointsize>
<italic>false</italic>
<bold>false</bold>
<underline>false</underline>
<strikeout>false</strikeout>
<stylestrategy>PreferDefault</stylestrategy>
<kerning>true</kerning>
</font>
</property>
<property name="text">
<string>Теоретический фундамент: Дмитрюк Т. Г.</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<item row="5" column="1">
<widget class="QLabel" name="labelgif">
<property name="minimumSize">
<size>
@@ -103,6 +40,7 @@
<property name="font">
<font>
<pointsize>14</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>false</underline>
@@ -122,6 +60,102 @@
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="labelowner">
<property name="font">
<font>
<pointsize>12</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>false</underline>
<strikeout>false</strikeout>
<stylestrategy>PreferDefault</stylestrategy>
<kerning>true</kerning>
</font>
</property>
<property name="text">
<string>Донецкий Национальный Технический Университет</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="labeldevelopers">
<property name="font">
<font>
<pointsize>14</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>false</underline>
<strikeout>false</strikeout>
<stylestrategy>PreferDefault</stylestrategy>
<kerning>true</kerning>
</font>
</property>
<property name="text">
<string>Разработчики: Слипенко М., Лазуренко Е.</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="versionLabel">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Версия:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="labelbasegigamen">
<property name="font">
<font>
<pointsize>14</pointsize>
<weight>50</weight>
<italic>false</italic>
<bold>false</bold>
<underline>false</underline>
<strikeout>false</strikeout>
<stylestrategy>PreferDefault</stylestrategy>
<kerning>true</kerning>
</font>
</property>
<property name="text">
<string>Теоретический фундамент: Дмитрюк Т. Г.</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="mainLabel">
<property name="font">
<font>
<pointsize>20</pointsize>
</font>
</property>
<property name="text">
<string>Statapp</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CorrelationAnalysisWindow</class>
<widget class="QDialog" name="CorrelationAnalysisWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>630</width>
<height>400</height>
</rect>
</property>
<property name="windowTitle">
<string>Корреляционный анализ</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QTableView" name="tableView"/>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,121 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GenerateFactorWindow</class>
<widget class="QDialog" name="GenerateFactorWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>503</width>
<height>193</height>
</rect>
</property>
<property name="windowTitle">
<string>Генерация факторов</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Тип связи</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Среднеквадратичное отклонение</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QPushButton" name="generatePushButton">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Сгенерировать</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Математическое ожидание</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="matSpinBox">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="decimals">
<number>5</number>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="deviationSpinBox">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="decimals">
<number>5</number>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="typeComboBox">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="editable">
<bool>false</bool>
</property>
<property name="currentText">
<string/>
</property>
<property name="placeholderText">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GenerateWindow</class>
<widget class="QDialog" name="GenerateWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>503</width>
<height>182</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Генерация откликов</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0" colspan="2">
<widget class="QPushButton" name="generatePushButton">
<property name="text">
<string>Сгенерировать</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Математическое ожидание</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Среднеквадратичное отклонение</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="matSpinBox">
<property name="decimals">
<number>5</number>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Количество наблюдений</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="countSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>500</number>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="deviationSpinBox">
<property name="decimals">
<number>5</number>
</property>
<property name="maximum">
<double>1000000.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<tabstops>
<tabstop>countSpinBox</tabstop>
<tabstop>matSpinBox</tabstop>
<tabstop>deviationSpinBox</tabstop>
<tabstop>generatePushButton</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

BIN
statapp/ui/images/logo.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 MiB

After

Width:  |  Height:  |  Size: 2.9 MiB

View File

@@ -26,7 +26,11 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QTableView" name="tableView"/>
<widget class="QTableView" name="tableView">
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
</layout>
</widget>
@@ -36,28 +40,37 @@
<x>0</x>
<y>0</y>
<width>800</width>
<height>22</height>
<height>27</height>
</rect>
</property>
<widget class="QMenu" name="filemenu">
<property name="title">
<string>Файл</string>
</property>
<addaction name="openfileaction"/>
<addaction name="savefileaction"/>
<addaction name="closefileaction"/>
</widget>
<widget class="QMenu" name="generatemenu">
<property name="title">
<string>Генерация показателей</string>
</property>
<addaction name="generateYaction"/>
<addaction name="generateXaction"/>
</widget>
<widget class="QMenu" name="analyzemenu">
<property name="title">
<string>Анализ данных</string>
</property>
<addaction name="varianceAnalysisAction"/>
<addaction name="correlationAnalisisAction"/>
</widget>
<widget class="QMenu" name="modelmenu">
<property name="title">
<string>Моделирование</string>
</property>
<addaction name="linearPolynomAction"/>
<addaction name="squaredPolynomAction"/>
</widget>
<widget class="QMenu" name="helpmenu">
<property name="title">
@@ -77,6 +90,51 @@
<string>О программе</string>
</property>
</action>
<action name="generateYaction">
<property name="text">
<string>Генерация отклика</string>
</property>
</action>
<action name="generateXaction">
<property name="text">
<string>Генерация фактора</string>
</property>
</action>
<action name="openfileaction">
<property name="text">
<string>Открыть</string>
</property>
</action>
<action name="savefileaction">
<property name="text">
<string>Сохранить</string>
</property>
</action>
<action name="closefileaction">
<property name="text">
<string>Закрыть</string>
</property>
</action>
<action name="varianceAnalysisAction">
<property name="text">
<string>Дисперсионный анализ</string>
</property>
</action>
<action name="correlationAnalisisAction">
<property name="text">
<string>Корреляционный анализ</string>
</property>
</action>
<action name="linearPolynomAction">
<property name="text">
<string>Линейный полином</string>
</property>
</action>
<action name="squaredPolynomAction">
<property name="text">
<string>Квадратичный полином</string>
</property>
</action>
</widget>
<resources/>
<connections/>

View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PolynomWindow</class>
<widget class="QDialog" name="PolynomWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>630</width>
<height>400</height>
</rect>
</property>
<property name="windowTitle">
<string>Полином</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QTableView" name="tableView">
<attribute name="horizontalHeaderMinimumSectionSize">
<number>40</number>
</attribute>
<attribute name="verticalHeaderMinimumSectionSize">
<number>40</number>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>40</number>
</attribute>
</widget>
</item>
<item row="1" column="0">
<layout class="QGridLayout" name="polynomResult">
<property name="topMargin">
<number>10</number>
</property>
<item row="0" column="1">
<widget class="QLabel" name="residualVarianceValueLabel">
<property name="text">
<string>undefined</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="scaledResidualVarianceValueLabel">
<property name="text">
<string>undefined</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="fStatisticLabel">
<property name="text">
<string>F1 - отношение Фишера</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="residualVarianceLabel">
<property name="text">
<string>Остаточная дисперсия:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="scaledResidualVarianceLabel">
<property name="text">
<string>Остаточная дисперсия (масштабированная):</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="rSquaredLabel">
<property name="text">
<string>Коэффициент множественной дереминизации</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="fStatisticValueLabel">
<property name="text">
<string>undefined</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="rSquaredValueLabel">
<property name="text">
<string>undefined</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -1,29 +1,44 @@
# -*- 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 <http://www.gnu.org/licenses/>.
#
################################################################################
## Form generated from reading UI file 'about_window.ui'
##
## Created by: Qt User Interface Compiler version 6.5.2
## 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 PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QFrame, QGridLayout, QLabel,
QMainWindow, QSizePolicy, QWidget)
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
class Ui_AboutWindow(object):
def setupUi(self, AboutWindow):
if not AboutWindow.objectName():
AboutWindow.setObjectName(u"AboutWindow")
AboutWindow.setEnabled(True)
AboutWindow.resize(476, 543)
AboutWindow.resize(483, 543)
AboutWindow.setAutoFillBackground(False)
self.centralwidget = QWidget(AboutWindow)
self.centralwidget.setObjectName(u"centralwidget")
@@ -31,44 +46,72 @@ class Ui_AboutWindow(object):
self.gridLayout_2.setObjectName(u"gridLayout_2")
self.gridLayout = QGridLayout()
self.gridLayout.setObjectName(u"gridLayout")
self.labelowner = QLabel(self.centralwidget)
self.labelowner.setObjectName(u"labelowner")
self.labelgif = QLabel(self.centralwidget)
self.labelgif.setObjectName(u"labelgif")
self.labelgif.setMinimumSize(QSize(50, 50))
self.labelgif.setMaximumSize(QSize(500, 600))
font = QFont()
font.setPointSize(14)
font.setBold(False)
font.setItalic(False)
font.setUnderline(False)
font.setWeight(50)
font.setStrikeOut(False)
font.setKerning(True)
font.setStyleStrategy(QFont.PreferDefault)
self.labelowner.setFont(font)
self.labelgif.setFont(font)
self.labelgif.setFrameShape(QFrame.NoFrame)
self.labelgif.setAlignment(Qt.AlignCenter)
self.gridLayout.addWidget(self.labelgif, 5, 1, 1, 1)
self.labelowner = QLabel(self.centralwidget)
self.labelowner.setObjectName(u"labelowner")
font1 = QFont()
font1.setPointSize(12)
font1.setBold(False)
font1.setItalic(False)
font1.setUnderline(False)
font1.setWeight(50)
font1.setStrikeOut(False)
font1.setKerning(True)
font1.setStyleStrategy(QFont.PreferDefault)
self.labelowner.setFont(font1)
self.labelowner.setAlignment(Qt.AlignCenter)
self.gridLayout.addWidget(self.labelowner, 4, 1, 1, 1)
self.gridLayout.addWidget(self.labelowner, 6, 1, 1, 1)
self.labeldevelopers = QLabel(self.centralwidget)
self.labeldevelopers.setObjectName(u"labeldevelopers")
self.labeldevelopers.setFont(font)
self.labeldevelopers.setAlignment(Qt.AlignCenter)
self.gridLayout.addWidget(self.labeldevelopers, 0, 1, 1, 1)
self.gridLayout.addWidget(self.labeldevelopers, 2, 1, 1, 1)
self.versionLabel = QLabel(self.centralwidget)
self.versionLabel.setObjectName(u"versionLabel")
font2 = QFont()
font2.setPointSize(12)
self.versionLabel.setFont(font2)
self.versionLabel.setAlignment(Qt.AlignCenter)
self.gridLayout.addWidget(self.versionLabel, 1, 1, 1, 1)
self.labelbasegigamen = QLabel(self.centralwidget)
self.labelbasegigamen.setObjectName(u"labelbasegigamen")
self.labelbasegigamen.setFont(font)
self.labelbasegigamen.setAlignment(Qt.AlignCenter)
self.gridLayout.addWidget(self.labelbasegigamen, 1, 1, 1, 1)
self.gridLayout.addWidget(self.labelbasegigamen, 3, 1, 1, 1)
self.labelgif = QLabel(self.centralwidget)
self.labelgif.setObjectName(u"labelgif")
self.labelgif.setMinimumSize(QSize(50, 50))
self.labelgif.setMaximumSize(QSize(500, 600))
self.labelgif.setFont(font)
self.labelgif.setFrameShape(QFrame.NoFrame)
self.labelgif.setAlignment(Qt.AlignCenter)
self.mainLabel = QLabel(self.centralwidget)
self.mainLabel.setObjectName(u"mainLabel")
font3 = QFont()
font3.setPointSize(20)
self.mainLabel.setFont(font3)
self.mainLabel.setAlignment(Qt.AlignCenter)
self.gridLayout.addWidget(self.labelgif, 2, 1, 1, 1)
self.gridLayout.addWidget(self.mainLabel, 0, 1, 1, 1)
self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
@@ -82,9 +125,10 @@ class Ui_AboutWindow(object):
def retranslateUi(self, AboutWindow):
AboutWindow.setWindowTitle(QCoreApplication.translate("AboutWindow", u"\u041e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0435", None))
self.labelgif.setText("")
self.labelowner.setText(QCoreApplication.translate("AboutWindow", u"\u0414\u043e\u043d\u0435\u0446\u043a\u0438\u0439 \u041d\u0430\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442", None))
self.labeldevelopers.setText(QCoreApplication.translate("AboutWindow", u"\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438: \u0421\u043b\u0438\u043f\u0435\u043d\u043a\u043e \u041c., \u041b\u0430\u0437\u0443\u0440\u0435\u043d\u043a\u043e \u0415.", None))
self.versionLabel.setText(QCoreApplication.translate("AboutWindow", u"\u0412\u0435\u0440\u0441\u0438\u044f:", None))
self.labelbasegigamen.setText(QCoreApplication.translate("AboutWindow", u"\u0422\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0444\u0443\u043d\u0434\u0430\u043c\u0435\u043d\u0442: \u0414\u043c\u0438\u0442\u0440\u044e\u043a \u0422. \u0413.", None))
self.labelgif.setText("")
self.mainLabel.setText(QCoreApplication.translate("AboutWindow", u"Statapp", None))
# retranslateUi

View File

@@ -0,0 +1,61 @@
# -*- 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 <http://www.gnu.org/licenses/>.
#
################################################################################
## Form generated from reading UI file 'correlation_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_CorrelationAnalysisWindow(object):
def setupUi(self, CorrelationAnalysisWindow):
if not CorrelationAnalysisWindow.objectName():
CorrelationAnalysisWindow.setObjectName(u"CorrelationAnalysisWindow")
CorrelationAnalysisWindow.resize(630, 400)
self.gridLayout_2 = QGridLayout(CorrelationAnalysisWindow)
self.gridLayout_2.setObjectName(u"gridLayout_2")
self.gridLayout = QGridLayout()
self.gridLayout.setObjectName(u"gridLayout")
self.tableView = QTableView(CorrelationAnalysisWindow)
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(CorrelationAnalysisWindow)
QMetaObject.connectSlotsByName(CorrelationAnalysisWindow)
# setupUi
def retranslateUi(self, CorrelationAnalysisWindow):
CorrelationAnalysisWindow.setWindowTitle(QCoreApplication.translate("CorrelationAnalysisWindow", u"\u041a\u043e\u0440\u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0430\u043d\u0430\u043b\u0438\u0437", None))
# retranslateUi

111
statapp/ui/ui_generate_factor_window.py generated Normal file
View File

@@ -0,0 +1,111 @@
# -*- 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 <http://www.gnu.org/licenses/>.
#
################################################################################
## 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.setDecimals(5)
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.setDecimals(5)
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"\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0444\u0430\u043a\u0442\u043e\u0440\u043e\u0432", 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

107
statapp/ui/ui_generate_window.py generated Normal file
View File

@@ -0,0 +1,107 @@
# -*- 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 <http://www.gnu.org/licenses/>.
#
################################################################################
## 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.setDecimals(5)
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.setDecimals(5)
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"\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432", 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

View File

@@ -1,24 +1,37 @@
# -*- 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 <http://www.gnu.org/licenses/>.
#
################################################################################
## Form generated from reading UI file 'main_window.ui'
##
## Created by: Qt User Interface Compiler version 6.5.2
## 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 PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient,
QCursor, QFont, QFontDatabase, QGradient,
QIcon, QImage, QKeySequence, QLinearGradient,
QPainter, QPalette, QPixmap, QRadialGradient,
QTransform)
from PySide6.QtWidgets import (QApplication, QGridLayout, QHeaderView, QLabel,
QMainWindow, QMenu, QMenuBar, QSizePolicy,
QStatusBar, QTableView, QWidget)
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
@@ -27,6 +40,24 @@ 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.openfileaction = QAction(MainWindow)
self.openfileaction.setObjectName(u"openfileaction")
self.savefileaction = QAction(MainWindow)
self.savefileaction.setObjectName(u"savefileaction")
self.closefileaction = QAction(MainWindow)
self.closefileaction.setObjectName(u"closefileaction")
self.varianceAnalysisAction = QAction(MainWindow)
self.varianceAnalysisAction.setObjectName(u"varianceAnalysisAction")
self.correlationAnalisisAction = QAction(MainWindow)
self.correlationAnalisisAction.setObjectName(u"correlationAnalisisAction")
self.linearPolynomAction = QAction(MainWindow)
self.linearPolynomAction.setObjectName(u"linearPolynomAction")
self.squaredPolynomAction = QAction(MainWindow)
self.squaredPolynomAction.setObjectName(u"squaredPolynomAction")
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.gridLayout = QGridLayout(self.centralwidget)
@@ -39,13 +70,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, 27))
self.filemenu = QMenu(self.menubar)
self.filemenu.setObjectName(u"filemenu")
self.generatemenu = QMenu(self.menubar)
@@ -66,6 +98,15 @@ class Ui_MainWindow(object):
self.menubar.addAction(self.analyzemenu.menuAction())
self.menubar.addAction(self.modelmenu.menuAction())
self.menubar.addAction(self.helpmenu.menuAction())
self.filemenu.addAction(self.openfileaction)
self.filemenu.addAction(self.savefileaction)
self.filemenu.addAction(self.closefileaction)
self.generatemenu.addAction(self.generateYaction)
self.generatemenu.addAction(self.generateXaction)
self.analyzemenu.addAction(self.varianceAnalysisAction)
self.analyzemenu.addAction(self.correlationAnalisisAction)
self.modelmenu.addAction(self.linearPolynomAction)
self.modelmenu.addAction(self.squaredPolynomAction)
self.helpmenu.addAction(self.aboutmenuaction)
self.retranslateUi(MainWindow)
@@ -76,6 +117,15 @@ 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.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.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.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))
@@ -83,4 +133,3 @@ class Ui_MainWindow(object):
self.modelmenu.setTitle(QCoreApplication.translate("MainWindow", u"\u041c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435", None))
self.helpmenu.setTitle(QCoreApplication.translate("MainWindow", u"\u0421\u043f\u0440\u0430\u0432\u043a\u0430", None))
# retranslateUi

118
statapp/ui/ui_polynom_window.py generated Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
#
################################################################################
## Form generated from reading UI file '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(630, 400)
self.gridLayout_2 = QGridLayout(PolynomWindow)
self.gridLayout_2.setObjectName(u"gridLayout_2")
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, 0, 0, 1, 1)
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.addLayout(self.polynomResult, 1, 0, 1, 1)
self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 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

View File

@@ -0,0 +1,61 @@
# -*- 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 <http://www.gnu.org/licenses/>.
#
################################################################################
## 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(630, 400)
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

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>VarianceAnalysisWindow</class>
<widget class="QDialog" name="VarianceAnalysisWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>630</width>
<height>400</height>
</rect>
</property>
<property name="windowTitle">
<string>Дисперсионный анализ</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QTableView" name="tableView"/>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

78
statapp/utils.py Normal file
View File

@@ -0,0 +1,78 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
import os
import sys
from PySide2.QtCore import QSize
from PySide2.QtGui import QIcon
from PySide2.QtWidgets import QMessageBox, QDoubleSpinBox, QStyledItemDelegate
from statapp.constants import NUMBERS_PRECISION
def resourcePath(relative):
if getattr(sys, 'frozen', False):
# pylint: disable=protected-access
bundleDir = sys._MEIPASS
else:
# we are running in a normal Python environment
bundleDir = os.path.dirname(os.path.abspath(__file__))
return os.path.join(bundleDir, relative)
def addIcon(windowOrDialog):
icon = QIcon()
icon.addFile(resourcePath("ui/images/logo.ico"), QSize(), QIcon.Normal, QIcon.Off)
windowOrDialog.setWindowIcon(icon)
def safeListGet(lst, idx, default):
try:
return lst[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
class FloatDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
QStyledItemDelegate.__init__(self, parent=parent)
def createEditor(self, parent, option, index):
editor = QDoubleSpinBox(parent)
editor.setDecimals(NUMBERS_PRECISION)
editor.setMaximum(10**8)
editor.setMinimum(-10**8)
return editor
def displayText(self, value, locale):
# Грязный хак, скорее всего нужно было использовать locale
return f'{value:.{NUMBERS_PRECISION}f}'

View File

@@ -0,0 +1,46 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
from PySide2.QtWidgets import QDialog, QHeaderView
from statapp.calculations import varianceAnalysis
from statapp.constants import NUMBERS_PRECISION
from statapp.mathtex_header_view import MathTexHeaderView
from statapp.models.variance_analysis_model import VarianceAnalysisModel
from statapp.ui.ui_variance_analysis_window import Ui_VarianceAnalysisWindow
from statapp.utils import addIcon, FloatDelegate
class VarianceAnalysisWindow(QDialog):
def __init__(self, data):
super().__init__()
self.ui = Ui_VarianceAnalysisWindow()
self.ui.setupUi(self)
res = varianceAnalysis(data)
self.model = VarianceAnalysisModel(res.round(NUMBERS_PRECISION))
self.ui.tableView.setItemDelegate(FloatDelegate())
self.ui.tableView.setModel(self.model)
self.ui.tableView.setVerticalHeader(
MathTexHeaderView(self.ui.tableView)
)
header = self.ui.tableView.horizontalHeader()
header.setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
addIcon(self)