12 Commits

Author SHA1 Message Date
github-actions[bot]
8b09a76b32 chore(main): release 0.11.0 (#107)
🤖 I have created a release *beep* *boop*
---


##
[0.11.0](https://github.com/shizand/statapp/compare/v0.10.2...v0.11.0)
(2024-02-03)


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

* добавлен пункт "Использование"
([#108](https://github.com/shizand/statapp/issues/108))
([aafa5a0](aafa5a0ebb)),
closes [#70](https://github.com/shizand/statapp/issues/70)
* добавлена возможность удалить факторы
([#103](https://github.com/shizand/statapp/issues/103))
([30447a8](30447a801a)),
closes [#102](https://github.com/shizand/statapp/issues/102)


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

* добавлена легенда графика
([#104](https://github.com/shizand/statapp/issues/104))
([240a517](240a517dd6)),
closes [#101](https://github.com/shizand/statapp/issues/101)

---
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>
2024-02-03 18:05:02 +03:00
aafa5a0ebb feat: добавлен пункт "Использование" (#108)
Closes #70
2024-02-03 17:57:49 +03:00
30447a801a feat: добавлена возможность удалить факторы (#103)
Closes #102
2024-02-03 16:20:33 +03:00
240a517dd6 fix: добавлена легенда графика (#104)
Closes #101
2024-02-03 16:20:23 +03:00
27c1455120 docs: Добавлен README.html 2024-02-03 15:33:01 +03:00
63f80819d2 docs: Обновлён README.md 2024-02-03 15:06:35 +03:00
d0053df261 docs: обновлён README.md (#106)
Co-authored-by: MisterMLiL <eugenelazurenko@gmail.com>
2024-02-03 14:49:25 +03:00
fcddf84839 docs: добавлена документация (#105)
Co-authored-by: MisterMLiL <eugenelazurenko@gmail.com>
2024-02-03 14:39:34 +03:00
github-actions[bot]
6b18bb1f82 chore(main): release 0.10.2 (#100)
🤖 I have created a release *beep* *boop*
---


##
[0.10.2](https://github.com/shizand/statapp/compare/v0.10.1...v0.10.2)
(2024-02-01)


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

* исправлена опечатка в характеристиках модели
([871d9ad](871d9ad746))

---
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>
2024-02-01 17:52:03 +03:00
871d9ad746 fix: исправлена опечатка в характеристиках модели 2024-02-01 17:30:10 +03:00
github-actions[bot]
71e68a645d chore(main): release 0.10.1 (#99)
🤖 I have created a release *beep* *boop*
---


##
[0.10.1](https://github.com/shizand/statapp/compare/v0.10.0...v0.10.1)
(2024-01-29)


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

* Добавлена обработка ошибок
([#98](https://github.com/shizand/statapp/issues/98))
([c36e1aa](c36e1aa733))

---
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>
2024-01-29 11:19:48 +03:00
MisterMLiL
c36e1aa733 fix: Добавлена обработка ошибок (#98)
Closes #83
Closes #96
Closes #97 

Добавлена обобщенная обработка на большинство методов.
Один из вариантов временно (а может и постоянно)  решить проблемы.
2024-01-29 11:11:53 +03:00
41 changed files with 1279 additions and 74 deletions

2
.idea/misc.xml generated
View File

@@ -3,5 +3,5 @@
<component name="Black">
<option name="sdkName" value="Poetry (statapp)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="statapp" project-jdk-type="Python SDK" />
<component name="ProjectRootManager" version="2" project-jdk-name="Poetry (statapp) (2)" project-jdk-type="Python SDK" />
</project>

2
.idea/stat.iml generated
View File

@@ -2,7 +2,7 @@
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="statapp" jdkType="Python SDK" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@@ -11,7 +11,7 @@ repos:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
#- id: check-added-large-files
- repo: https://github.com/johann-petrak/licenseheaders.git
rev: v0.8.8
hooks:

View File

@@ -24,4 +24,5 @@ disable=
missing-docstring,
too-many-public-methods,
too-few-public-methods,
too-many-arguments
too-many-arguments,
broad-except

View File

@@ -1,5 +1,32 @@
# Changelog
## [0.11.0](https://github.com/shizand/statapp/compare/v0.10.2...v0.11.0) (2024-02-03)
### Новые функции
* добавлен пункт "Использование" ([#108](https://github.com/shizand/statapp/issues/108)) ([aafa5a0](https://github.com/shizand/statapp/commit/aafa5a0ebbb772b6aa55699d8a50587a8fe6c8e0)), closes [#70](https://github.com/shizand/statapp/issues/70)
* добавлена возможность удалить факторы ([#103](https://github.com/shizand/statapp/issues/103)) ([30447a8](https://github.com/shizand/statapp/commit/30447a801afdac80da948a6f0961ce7b08591f4f)), closes [#102](https://github.com/shizand/statapp/issues/102)
### Исправления
* добавлена легенда графика ([#104](https://github.com/shizand/statapp/issues/104)) ([240a517](https://github.com/shizand/statapp/commit/240a517dd6691d45253b5863b54b4b035aaea8f1)), closes [#101](https://github.com/shizand/statapp/issues/101)
## [0.10.2](https://github.com/shizand/statapp/compare/v0.10.1...v0.10.2) (2024-02-01)
### Исправления
* исправлена опечатка в характеристиках модели ([871d9ad](https://github.com/shizand/statapp/commit/871d9ad746c51351bee9097d9f56903c8e1d1873))
## [0.10.1](https://github.com/shizand/statapp/compare/v0.10.0...v0.10.1) (2024-01-29)
### Исправления
* Добавлена обработка ошибок ([#98](https://github.com/shizand/statapp/issues/98)) ([c36e1aa](https://github.com/shizand/statapp/commit/c36e1aa733269720366c4d7dea48d2bdc966a59a))
## [0.10.0](https://github.com/shizand/statapp/compare/v0.9.0...v0.10.0) (2024-01-08)

View File

@@ -20,9 +20,9 @@
## Установка
Программа распространяется с помощью [PyInstaller](https://pyinstaller.org/en/stable/).
Программа распространяется с помощью [PyInstaller](https://pyinstaller.org/en/stable/).
Существует две версиии: **statapp** и **statapp-onefile**.
Существует две версиии: **statapp** и **statapp-onefile**.
Различия в том, что onefile версия поставляется одним единственным бинарным файлом. На Windows системах с включенным антивирусом это может вызывать [некоторые проблемы](https://qna.habr.com/q/988553).
@@ -39,9 +39,17 @@ poetry install
pyinstaller statapp.spec # или pyinstaller statapp.spec -- --one-file
```
Документация собирается с помощью [grip](https://github.com/joeyespo/grip)
```bash
echo "STYLE_URLS = [\"https://cdn.jsdelivr.net/gh/shizand/statapp@main/docs/grip.css\"]" > ~/.grip/settings.py
cd docs
grip .
```
## Использование
<!-- TODO -->
Использование описано в [Руководстве пользователя](docs/README.md).
## Чем я могу помочь проекту?

156
environment.yml Normal file
View File

@@ -0,0 +1,156 @@
name: statapp
channels:
- conda-forge
- defaults
dependencies:
- _libgcc_mutex=0.1=conda_forge
- _openmp_mutex=4.5=2_gnu
- alsa-lib=1.2.10=hd590300_0
- attr=2.5.1=h166bdaf_1
- bzip2=1.0.8=hd590300_5
- ca-certificates=2024.2.2=hbcca054_0
- cairo=1.16.0=h6cf1ce9_1008
- dbus=1.13.6=h48d8840_2
- expat=2.5.0=hcb278e6_1
- font-ttf-dejavu-sans-mono=2.37=hab24e00_0
- font-ttf-inconsolata=3.000=h77eed37_0
- font-ttf-source-code-pro=2.038=h77eed37_0
- font-ttf-ubuntu=0.83=h77eed37_1
- fontconfig=2.14.2=h14ed4e7_0
- fonts-conda-ecosystem=1=0
- fonts-conda-forge=1=0
- freetype=2.12.1=h267a509_2
- gettext=0.21.1=h27087fc_0
- glib=2.68.4=h9c3ff4c_0
- glib-tools=2.68.4=h9c3ff4c_0
- graphite2=1.3.13=h58526e2_1001
- gst-plugins-base=1.18.4=h29181c9_0
- gstreamer=1.18.5=h76c114f_0
- harfbuzz=3.0.0=h83ec7ef_1
- icu=68.2=h9c3ff4c_0
- jpeg=9e=h166bdaf_2
- keyutils=1.6.1=h166bdaf_0
- krb5=1.19.3=h3790be6_0
- lame=3.100=h166bdaf_1003
- ld_impl_linux-64=2.38=h1181459_1
- libcap=2.69=h0f662aa_0
- libclang=11.1.0=default_ha53f305_1
- libclang13=14.0.6=default_h9986a30_1
- libcups=2.3.3=h3e49a29_2
- libedit=3.1.20191231=he28a2e2_2
- libevent=2.1.10=h9b69904_4
- libexpat=2.5.0=hcb278e6_1
- libffi=3.3=h58526e2_2
- libflac=1.4.3=h59595ed_0
- libgcc-ng=13.2.0=h807b86a_5
- libgcrypt=1.10.3=hd590300_0
- libglib=2.68.4=h3e27bee_0
- libgomp=13.2.0=h807b86a_5
- libgpg-error=1.47=h71f35ed_0
- libiconv=1.17=hd590300_2
- libjpeg-turbo=2.1.4=h166bdaf_0
- libllvm11=11.1.0=he0ac6c6_5
- libllvm14=14.0.6=hcd5def8_4
- libogg=1.3.4=h7f98852_1
- libopus=1.3.1=h7f98852_1
- libpng=1.6.42=h2797004_0
- libpq=13.8=hd77ab85_0
- libsndfile=1.2.2=hc60ed4a_1
- libsqlite=3.44.2=h2797004_0
- libstdcxx-ng=13.2.0=h7e041cc_5
- libsystemd0=255=h3516f8a_0
- libuuid=2.38.1=h0b41bf4_0
- libvorbis=1.3.7=h9c3ff4c_0
- libxcb=1.15=h0b41bf4_0
- libxkbcommon=1.0.3=he3ba5ed_0
- libxml2=2.9.12=h72842e0_0
- libxslt=1.1.33=h15afd5d_2
- libzlib=1.2.13=hd590300_5
- lz4-c=1.9.4=hcb278e6_0
- mpg123=1.32.4=h59595ed_0
- mysql-common=8.0.32=h14678bc_0
- mysql-libs=8.0.32=h54cf53e_0
- ncurses=6.4=h6a678d5_0
- nspr=4.35=h27087fc_0
- nss=3.97=h1d7d5a4_0
- openssl=1.1.1w=hd590300_0
- pcre=8.45=h9c3ff4c_0
- pcre2=10.42=hcad00b1_0
- pip=23.3.1=py38h06a4308_0
- pixman=0.43.2=h59595ed_0
- pthread-stubs=0.4=h36c2ea0_1001
- pyside2=5.13.2=py38h2009f50_7
- python=3.8.10=h49503c6_1_cpython
- python_abi=3.8=2_cp38
- qt=5.12.9=hda022c4_4
- readline=8.2=h5eee18b_0
- setuptools=68.2.2=py38h06a4308_0
- sqlite=3.41.2=h5eee18b_0
- tk=8.6.12=h1ccaba5_0
- wheel=0.41.2=py38h06a4308_0
- xcb-util=0.4.0=hd590300_1
- xcb-util-image=0.4.0=h8ee46fc_1
- xcb-util-keysyms=0.4.0=h8ee46fc_1
- xcb-util-renderutil=0.3.9=hd590300_1
- xcb-util-wm=0.4.1=h8ee46fc_1
- xkeyboard-config=2.40=hd590300_0
- xorg-kbproto=1.0.7=h7f98852_1002
- xorg-libice=1.1.1=hd590300_0
- xorg-libsm=1.2.4=h7391055_0
- xorg-libx11=1.8.7=h8ee46fc_0
- xorg-libxau=1.0.11=hd590300_0
- xorg-libxdmcp=1.1.3=h7f98852_0
- xorg-libxext=1.3.4=h0b41bf4_2
- xorg-libxrender=0.9.11=hd590300_0
- xorg-renderproto=0.11.1=h7f98852_1002
- xorg-xextproto=7.3.0=h0b41bf4_1003
- xorg-xf86vidmodeproto=2.3.1=h7f98852_1002
- xorg-xproto=7.0.31=h7f98852_1007
- xz=5.4.5=h5eee18b_0
- zlib=1.2.13=hd590300_5
- zstd=1.5.5=hfc55251_0
- pip:
- altgraph==0.17.4
- astroid==2.15.8
- cfgv==3.4.0
- contourpy==1.1.1
- cycler==0.12.1
- dill==0.3.7
- distlib==0.3.7
- filelock==3.12.4
- fonttools==4.43.1
- identify==2.5.30
- importlib-metadata==6.8.0
- importlib-resources==6.1.0
- isort==5.12.0
- kiwisolver==1.4.5
- lazy-object-proxy==1.9.0
- matplotlib==3.7.3
- mccabe==0.7.0
- mpmath==1.3.0
- nodeenv==1.8.0
- numpy==1.24.4
- packaging==23.2
- pandas==2.0.3
- pillow==9.5.0
- platformdirs==3.11.0
- pre-commit==3.5.0
- pyinstaller==6.1.0
- pyinstaller-hooks-contrib==2023.10
- pylint==2.17.7
- pyparsing==3.1.1
- python-dateutil==2.8.2
- pytz==2023.3.post1
- pyyaml==6.0.1
- setuptools-scm==8.0.4
- six==1.16.0
- statapp==0.10.2
- sympy==1.12
- tomli==2.0.1
- tomlkit==0.12.1
- typing-extensions==4.8.0
- tzdata==2023.3
- virtualenv==20.24.5
- wrapt==1.15.0
- zipp==3.17.0
prefix: /home/maxim/miniconda3/envs/statapp

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "statapp"
version = "0.10.0"
version = "0.11.0"
description = ""
authors = [
"Maxim Slipenko <statapp@maks1ms.addy.io>"

View File

@@ -17,7 +17,11 @@ parser = argparse.ArgumentParser()
parser.add_argument("--one-file", action="store_true")
options = parser.parse_args()
datas = [('statapp/ui/images/*', 'ui/images')]
datas = [
('statapp/ui/images/*', 'ui/images'),
('statapp/docs/files/*', 'docs/files'),
('statapp/docs/README.html', 'docs')
]
datas += copy_metadata('statapp')

View File

@@ -26,15 +26,14 @@ from statapp.main_window import MainWindow
def main():
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_ShareOpenGLContexts)
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_()

542
statapp/docs/README.html Normal file

File diff suppressed because one or more lines are too long

210
statapp/docs/README.md Normal file
View File

@@ -0,0 +1,210 @@
<!--
Copyright (c) 2024 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/>.
-->
# Руководство пользователя для программы "Statapp"
## Условные обозначения
`Взаимодействие` - так отображается интерфестные части приложения с которыми пользователь может и должен взаимодействовать. к тами относятся кнопки, пункты меню, окна приложения, страницы в моделировании и тд.
*Пример* - так отображаются комментарии или описания. Обычно используются в качестве подписей к картинкам.
***Параметр*** - так отображаются параметры, которые пользователь может получить в результате вычислений в приложении.
## Введение
"Statapp" — это программное решение для статистического анализа и регрессионного моделирования, позволяющее специалистам в области данных проводить глубокий анализ и создавать точные прогностические модели.
## Теоретические сведения
*-- В разработке --*
## Начало работы
### Генерация показателей
<hr>
### Генерация отклика
Перед тем как начать анализ, необходимо сгенерировать отклики, которые будут использоваться как зависимые переменные в моделях:
1. Перейдите в меню `Генерация показателей`.
2. Выберите `Генерация отклика`.
После этого откроется окно `Генерация отклика`:
<image src="files/Генерация показателей - Генерация отклика.PNG">
*Пример пункта меню* `Генерация отклика`
3. Укажите необходимые параметры для генерации данных и нажмите кнопку `Сгенерировать`.
<image src="files/Окно - Генерация отклика.PNG" width=400>
*Пример окна* `Генерация отклика`
После этого окно должно закрыться и на `Белом листе` в `Главном окне` появится колонка со случайно сгенерированными данными отклика по заданным показателям.
<hr>
### Генерация фактора
После генерации откликов следует сгенерировать факторы, которые будут служить независимыми переменными. Для генерации факторов необходимо выполнить следующие шаги:
1. Перейдите в меню `Генерация показателей`.
2. Выберите `Генерация фактора`.
После этого откроется окно `Генерация фактора`:
<image src="files/Генерация показателей - Генерация фактора.PNG">
*Пример пункта меню* `Генерация фактора`
3. Выберите нужный тип связи к отклику (прямая или обратная).
4. Укажите оставшиеся параметры для генерации данных и нажмите кнопку `Сгенерировать`.
<image src="files/Окно - Генерация фактора.PNG" width=400>
*Пример окна* `Генерация отклика`
Можно добавлять несколько факторов.
<hr>
### Анализ данных
После генерации отклика и факторов можно приступать к анализу данных.
<hr>
### Дисперсионный анализ
1. Перейдите в меню `Анализ данных`.
2. Выберите `Дисперсионный анализ`.
<image src="files/Анализ данных - Дисперсионный анализ.PNG">
*Пример пункта меню* `Дисперсионный анализ`
После этого откроется окно `Дисперсионный анализ`:
<image src="files/Окно - Дисперсионный анализ.PNG">
*Пример окна* `Дисперсионный анализ`
<hr>
### Корреляционный анализ
1. Перейдите в меню `Анализ данных`.
2. Выберите `Корреляционный анализ`.
<image src="files/Анализ данных - Корреляционный анализ.PNG">
*Пример пункта меню* `Корреляционный анализ`
После этого откроется окно `Корреляционный анализ`:
<image src="files/Окно - Корреляционный анализ.PNG">
*Пример окна* `Корреляционный анализ`
<hr>
### Моделирование
После генерации отклика и факторов можно перейти к построению регрессионных моделей.
Здесь вы можете увидеть параметры модели, её характеристики, прогноз и отклонения, а также график прогноза и отклонения.
1. Перейдите на вкладку `Моделирование`.
2. Выберите тип модели для построения: `Линейный полином`, `Квадратичный полином` или `Преобразования`.
<image src="files/Моделирование - Линейный полином.PNG">
*Пример список пунктов меню* `Моделирование`
На странице `Модель` любого окна из `Моделирование` можно увидеть данные ***Коэффициент регрессии*** и ***Коэффициент значимости*** в виде таблицы для отклика и каждого из факторов. В нижней части окна располагаются вычисленные значения для параметров: ***Остаточная дисперсия***, ***Остаточная дисперсия (масштабированная)***, ***F1 - отношение Фишера***, ***Коэффициент множественной детерминации***,
<image src="files/Окно - Полином (Линейный полином).PNG">
*Пример страницы* `Модель` *окна* `Линейный полином`
На странице `Прогноз` любого окна из `Моделирование` можно увидеть значения ***Прогноза*** и ***Отклонения*** для каждого ранее сгенерированного значения ***Отклика***.
<image src="files/Окно - Полином - Прогноз.PNG">
*Пример страницы* `Прогноз` *окна* `Линейный полином`
На странице `График` любого окна из `Моделирование` можно увидеть график ***Прогноза*** (график) и ***Отклонения*** (точки).
<image src="files/Окно - Полином - График.PNG">
*Пример страницы* `График` *окна* `Линейный полином`
При необходимости, в окне `Моделирование` - `Преобразования` для каждого фактора вы можете выбрать одно из доступных преобразований.
<image src="files/Окно - Полином (Преобразования).PNG">
*Пример окна* `Преобразования`
Для выбора преобразования для определенного фактора необходимо выполнить следующие шаги:
1. Перейдите на страницу `Модель` в окне `Преобразования`.
2. Дважды нажмите на нужную ячейку в колонке ***Преобразования***.
3. Выберите необходимое преобразование из выпадающего списка.
<image src="files/Преобразования - Выбор преобразования.PNG">
*Пример списка выбора* ***Преобразования*** *фактора в окне* `Преобразования`
*Комментарий: если значения не персчитались попробуйте снять выделение с ячейки, путем нажатия на другую ячейку*
<hr>
### Сохранение и открытие файла
Сгенерированные значения ***Отклика*** и ***Фактора*** из таблицы в `Главном окне` можно сохранить или зугрузить из файла ***.txt*** и ***.csv***.
### Сохранение файла
1. Перейдите в меню `Файл`.
2. Выберите `Сохранить`.
<image src="files/Файл - Сохранить.PNG">
*Пример пункта меню* `Сохранить файл`
3. Выберите путь сохранения и тип файла и нажмите кнопку `Сохранить`.
Теперь файл будет сохранен по указаному вами пути, его можно переместить куда необходимо и при необходимости загрузить обратно в приложение.
### Открытие файла
1. Перейдите в меню `Файл`.
2. Выберите `Открыть`.
<image src="files/Файл - Открыть.PNG">
*Пример пункта меню* `Открыть файл`
3. Выберите путь до открываемого файла и нажмите кнопку `Открыть`.
Приложение загрузит нужный вам файл, и при необходимости спросит нужно ли сохранять ваши текущие данные.

BIN
statapp/docs/README.pdf Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

36
statapp/docs/grip.css Normal file
View File

@@ -0,0 +1,36 @@
/*
Copyright (c) 2024 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/>.
*/
#preview-page {
margin-top: 0px;
margin-bottom: 0px;
}
#readme {
border: none;
}
#readme > .Box-header {
border: none;
display: none !important;
}
#readme > .Box-body {
border: none;
}

View File

@@ -19,8 +19,8 @@
#
import numpy as np
from PySide2 import QtCore
from PySide2.QtCore import Slot
from PySide2.QtWidgets import QMainWindow, QMessageBox
from PySide2.QtCore import Slot, Qt, QPoint
from PySide2.QtWidgets import QMainWindow, QMessageBox, QAction, QMenu
from statapp.calculations import generateXValues, generateYValues
from statapp.constants import NUMBERS_PRECISION
@@ -33,7 +33,8 @@ 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.usage_window import UsageWindow
from statapp.utils import buildMessageBox, addIcon, FloatDelegate, onError
from statapp.variance_analysis import VarianceAnalysisWindow
from statapp.correlation_analysis import CorrelationAnalysisWindow
from statapp.polynoms.transform_polynom_window import TransformPolynomWindow
@@ -61,6 +62,7 @@ class MainWindow(QMainWindow):
]
self.aboutWindow = None
self.usageWindow = None
self.isDataChanged = False
self.model = InputValuesModel()
@@ -79,6 +81,27 @@ class MainWindow(QMainWindow):
# x1 = generateXValues(20, 2, 0, y)
# x2 = generateXValues(10, 1, 0, y)
# self.model.updateAllData(np.concatenate([y, x1, x2], axis=1))
self.ui.tableView.horizontalHeader().setContextMenuPolicy(Qt.CustomContextMenu)
self.ui.tableView.horizontalHeader().customContextMenuRequested.connect(self.removeColumn)
def removeColumn(self, event: QPoint):
menu = QMenu(self)
col = self.ui.tableView.columnAt(event.x())
if col == 0:
return
def fun():
self.model.removeCol(col)
self.isDataChanged = True
selectAction = QAction("Удалить", self)
selectAction.triggered.connect(fun)
menu.addAction(selectAction)
menu.exec_(self.ui.tableView.mapToGlobal(event))
def updateActionsEnabled(self):
@@ -103,101 +126,136 @@ class MainWindow(QMainWindow):
@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
try:
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)
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())
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
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
else:
data = self.fileModel.loadFile()
if data is not None and data.shape[0] > 0:
self.model.updateAllData(data)
self.isDataChanged = False
except Exception as error:
onError(error)
@Slot()
def on_savefileaction_triggered(self):
self.isDataChanged = not self.fileModel.saveFile(self.model.getData())
try:
self.isDataChanged = not self.fileModel.saveFile(self.model.getData())
except Exception as error:
onError(error)
@Slot()
def on_closefileaction_triggered(self):
self.fileModel.closeFile()
self.isDataChanged = False
try:
self.fileModel.closeFile()
self.isDataChanged = False
except Exception as error:
onError(error)
@Slot()
def on_generateYaction_triggered(self):
gw = GenerateWindow()
try:
gw = GenerateWindow()
if gw.exec():
y = generateYValues(gw.mat, gw.deviation, gw.count)
self.model.updateAllData(y.round(NUMBERS_PRECISION))
self.isDataChanged = True
if gw.exec():
y = generateYValues(gw.mat, gw.deviation, gw.count)
self.model.updateAllData(y.round(NUMBERS_PRECISION))
self.isDataChanged = True
except Exception as error:
onError(error)
@Slot()
def on_generateXaction_triggered(self):
gfw = GenerateFactorWindow()
try:
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
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
except Exception as error:
onError(error)
@Slot()
def on_aboutmenuaction_triggered(self):
self.aboutWindow = AboutWindow()
self.aboutWindow.show()
@Slot()
def on_usageaction_triggered(self):
self.usageWindow = UsageWindow()
self.usageWindow.show()
@Slot()
def on_varianceAnalysisAction_triggered(self):
dw = VarianceAnalysisWindow(self.model.getData())
dw.exec()
try:
dw = VarianceAnalysisWindow(self.model.getData())
dw.exec()
except Exception as error:
onError(error)
@Slot()
def on_correlationAnalisisAction_triggered(self):
dw = CorrelationAnalysisWindow(self.model.getData())
dw.exec()
try:
dw = CorrelationAnalysisWindow(self.model.getData())
dw.exec()
except Exception as error:
onError(error)
@Slot()
def on_linearPolynomAction_triggered(self):
dw = LinearPolynomWindow(self.model.getData())
dw.exec()
try:
dw = LinearPolynomWindow(self.model.getData())
dw.exec()
except Exception as error:
onError(error)
@Slot()
def on_squaredPolynomAction_triggered(self):
dw = SquaredPolynomWindow(self.model.getData())
dw.exec()
try:
dw = SquaredPolynomWindow(self.model.getData())
dw.exec()
except Exception as error:
onError(error)
@Slot()
def on_transformPolynomAction_triggered(self):
dw = TransformPolynomWindow(self.model.getData())
dw.exec()
try:
dw = TransformPolynomWindow(self.model.getData())
dw.exec()
except Exception as error:
onError(error)
def closeEvent(self, event):
if self.isDataChanged:

View File

@@ -33,3 +33,6 @@ class InputValuesModel(EditableTableModel):
def getY(self):
return self._data[:, 0]
def removeCol(self, index: int):
self.updateAllData(np.delete(self._data, index, axis=1))

View File

@@ -28,7 +28,7 @@ from statapp.models.prediction_table_model import PreditionTableModel
from statapp.models.transform_polynom_model import TransformPolynomModel, TRANSFORMS
from statapp.polynoms.polynom_window import MplCanvas
from statapp.ui.ui_polynom_window import Ui_PolynomWindow
from statapp.utils import addIcon
from statapp.utils import addIcon, onError
class TransformPolynomWindow(QDialog):
@@ -41,8 +41,11 @@ class TransformPolynomWindow(QDialog):
self.data = data
result = linearPolynom(data)
try:
predictionResult = prediction(data, result)
except Exception as error:
onError(error)
predictionResult = prediction(data, result)
self.predictionModel = PreditionTableModel(predictionResult)
self.ui.predictionTableView.setModel(self.predictionModel)
header = self.ui.predictionTableView.horizontalHeader()
@@ -90,7 +93,10 @@ class TransformPolynomWindow(QDialog):
tr = self.model.data(self.model.createIndex(j, 0), Qt.DisplayRole)
data[i][j] = TRANSFORMS[tr](data[i][j])
self.rebuildData(data)
try:
self.rebuildData(data)
except Exception as error:
onError(error)
def rebuildData(self, data):
result = linearPolynom(data)

View File

@@ -40,7 +40,7 @@
<x>0</x>
<y>0</y>
<width>800</width>
<height>21</height>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="filemenu">
@@ -77,6 +77,7 @@
<property name="title">
<string>Справка</string>
</property>
<addaction name="usageaction"/>
<addaction name="aboutmenuaction"/>
</widget>
<addaction name="filemenu"/>
@@ -141,6 +142,11 @@
<string>Преобразования</string>
</property>
</action>
<action name="usageaction">
<property name="text">
<string>Использование</string>
</property>
</action>
</widget>
<resources/>
<connections/>

View File

@@ -82,7 +82,7 @@
<item row="3" column="0">
<widget class="QLabel" name="rSquaredLabel">
<property name="text">
<string>Коэффициент множественной дереминизации</string>
<string>Коэффициент множественной детерминации</string>
</property>
</widget>
</item>
@@ -124,10 +124,17 @@
<attribute name="title">
<string>График</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<layout class="QGridLayout" name="gridLayout_5" rowstretch="1,0">
<item row="0" column="0">
<layout class="QGridLayout" name="plotContainer"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Точки - отклик. Линия - прогноз</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>

View File

@@ -60,6 +60,8 @@ class Ui_MainWindow(object):
self.squaredPolynomAction.setObjectName(u"squaredPolynomAction")
self.transformPolynomAction = QAction(MainWindow)
self.transformPolynomAction.setObjectName(u"transformPolynomAction")
self.usageaction = QAction(MainWindow)
self.usageaction.setObjectName(u"usageaction")
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.gridLayout = QGridLayout(self.centralwidget)
@@ -79,7 +81,7 @@ class Ui_MainWindow(object):
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QMenuBar(MainWindow)
self.menubar.setObjectName(u"menubar")
self.menubar.setGeometry(QRect(0, 0, 800, 21))
self.menubar.setGeometry(QRect(0, 0, 800, 22))
self.filemenu = QMenu(self.menubar)
self.filemenu.setObjectName(u"filemenu")
self.generatemenu = QMenu(self.menubar)
@@ -110,6 +112,7 @@ class Ui_MainWindow(object):
self.modelmenu.addAction(self.linearPolynomAction)
self.modelmenu.addAction(self.squaredPolynomAction)
self.modelmenu.addAction(self.transformPolynomAction)
self.helpmenu.addAction(self.usageaction)
self.helpmenu.addAction(self.aboutmenuaction)
self.retranslateUi(MainWindow)
@@ -130,6 +133,7 @@ class Ui_MainWindow(object):
self.linearPolynomAction.setText(QCoreApplication.translate("MainWindow", u"\u041b\u0438\u043d\u0435\u0439\u043d\u044b\u0439 \u043f\u043e\u043b\u0438\u043d\u043e\u043c", None))
self.squaredPolynomAction.setText(QCoreApplication.translate("MainWindow", u"\u041a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u0447\u043d\u044b\u0439 \u043f\u043e\u043b\u0438\u043d\u043e\u043c", None))
self.transformPolynomAction.setText(QCoreApplication.translate("MainWindow", u"\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f", None))
self.usageaction.setText(QCoreApplication.translate("MainWindow", u"\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435", 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))

View File

@@ -126,6 +126,12 @@ class Ui_PolynomWindow(object):
self.gridLayout_5.addLayout(self.plotContainer, 0, 0, 1, 1)
self.label = QLabel(self.tab)
self.label.setObjectName(u"label")
self.gridLayout_5.addWidget(self.label, 1, 0, 1, 1)
self.gridLayout_5.setRowStretch(0, 1)
self.tabWidget.addTab(self.tab, "")
self.gridLayout_2.addWidget(self.tabWidget, 0, 6, 1, 1)
@@ -146,10 +152,11 @@ class Ui_PolynomWindow(object):
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.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\u0442\u0435\u0440\u043c\u0438\u043d\u0430\u0446\u0438\u0438", None))
self.fStatisticValueLabel.setText(QCoreApplication.translate("PolynomWindow", u"undefined", None))
self.rSquaredValueLabel.setText(QCoreApplication.translate("PolynomWindow", u"undefined", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.model), QCoreApplication.translate("PolynomWindow", u"\u041c\u043e\u0434\u0435\u043b\u044c", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.prediction), QCoreApplication.translate("PolynomWindow", u"\u041f\u0440\u043e\u0433\u043d\u043e\u0437", None))
self.label.setText(QCoreApplication.translate("PolynomWindow", u"\u0422\u043e\u0447\u043a\u0438 - \u043e\u0442\u043a\u043b\u0438\u043a. \u041b\u0438\u043d\u0438\u044f - \u043f\u0440\u043e\u0433\u043d\u043e\u0437", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QCoreApplication.translate("PolynomWindow", u"\u0413\u0440\u0430\u0444\u0438\u043a", None))
# retranslateUi

56
statapp/ui/ui_usage_window.py generated Normal file
View File

@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2024 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 'usage_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_UsageWindow(object):
def setupUi(self, UsageWindow):
if not UsageWindow.objectName():
UsageWindow.setObjectName(u"UsageWindow")
UsageWindow.resize(400, 300)
self.gridLayout = QGridLayout(UsageWindow)
self.gridLayout.setObjectName(u"gridLayout")
self.browserContainer = QVBoxLayout()
self.browserContainer.setObjectName(u"browserContainer")
self.gridLayout.addLayout(self.browserContainer, 0, 0, 1, 1)
self.retranslateUi(UsageWindow)
QMetaObject.connectSlotsByName(UsageWindow)
# setupUi
def retranslateUi(self, UsageWindow):
UsageWindow.setWindowTitle(QCoreApplication.translate("UsageWindow", u"\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435", None))
# retranslateUi

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UsageWindow</class>
<widget class="QDialog" name="UsageWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Использование</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="browserContainer"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

40
statapp/usage_window.py Normal file
View File

@@ -0,0 +1,40 @@
#
# Copyright (c) 2024 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 QUrl
from PySide2.QtWebEngineWidgets import QWebEngineView
from PySide2.QtWidgets import QMainWindow, QVBoxLayout, QWidget
from statapp.utils import addIcon, resourcePath
class UsageWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Использование")
addIcon(self)
layout = QVBoxLayout()
self.browser = QWebEngineView()
layout.addWidget(self.browser)
self.browser.load(QUrl.fromLocalFile(resourcePath("docs/README.html")))
widget = QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)

View File

@@ -59,8 +59,19 @@ def buildMessageBox(title, text, icon, buttons, defaultButton):
msgBox.setStandardButtons(buttons)
msgBox.setDefaultButton(defaultButton)
addIcon(msgBox)
return msgBox
def onError(errorName: Exception):
msgBox = buildMessageBox \
('Ошибка',
"Упс.. Произошла ошибка:\n" + str(errorName),
QMessageBox.Critical,
QMessageBox.Ok,
QMessageBox.Ok)
msgBox.exec_()
class FloatDelegate(QStyledItemDelegate):
def __init__(self, parent=None):