From a04517a15d9e9e47edcb4d9482aba4ccb78c3f6d Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 25 Nov 2024 14:01:09 +0300 Subject: [PATCH] =?UTF-8?q?chore:=20=D0=B7=D0=B0=20=D0=BE=D1=81=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D1=83=20=D0=B2=D0=B7=D1=8F=D1=82=20TraceDemo,=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=B8?= =?UTF-8?q?=D0=B4=D0=B5=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5=20=D0=B3=D1=80?= =?UTF-8?q?=D0=B0=D1=84=D0=B8=D0=BA=D0=B8=20=D0=BA=20=D1=80=D0=B5=D0=B0?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D1=8B=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- params/system_params.json | 2 + .../AutoConfigClass.cpython-310.pyc | Bin 831 -> 831 bytes .../ConstantCalculator.cpython-310.pyc | Bin 1172 -> 1172 bytes .../__pycache__/OptAlgorithm.cpython-310.pyc | Bin 15481 -> 15481 bytes .../OptTimeCalculator.cpython-310.pyc | Bin 7744 -> 7744 bytes .../__pycache__/PhaseCalc.cpython-310.pyc | Bin 1130 -> 1130 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 192 -> 192 bytes src/__pycache__/__init__.cpython-310.pyc | Bin 146 -> 146 bytes src/__pycache__/main.cpython-310.pyc | Bin 3670 -> 1391 bytes .../__pycache__/controller.cpython-310.pyc | Bin 0 -> 698 bytes .../__pycache__/converter.cpython-310.pyc | Bin 0 -> 1226 bytes .../ideal_data_builder.cpython-310.pyc | Bin 0 -> 675 bytes .../__pycache__/mediator.cpython-310.pyc | Bin 0 -> 993 bytes .../__pycache__/monitor.cpython-310.pyc | Bin 0 -> 1378 bytes .../__pycache__/monitor.cpython-311.pyc | Bin 0 -> 2271 bytes src/controller/controller.py | 12 + src/controller/converter.py | 20 ++ src/controller/ideal_data_builder.py | 8 + src/controller/mediator.py | 21 ++ src/controller/monitor.py | 28 ++ src/gui/__init__.py | 3 +- src/gui/__pycache__/__init__.cpython-310.pyc | Bin 293 -> 246 bytes src/gui/__pycache__/app.cpython-310.pyc | Bin 3209 -> 3117 bytes src/gui/__pycache__/mainGui.cpython-310.pyc | Bin 0 -> 1560 bytes .../__pycache__/plot_window.cpython-310.pyc | Bin 8913 -> 8913 bytes src/gui/__pycache__/plotter.cpython-310.pyc | Bin 0 -> 5388 bytes .../__pycache__/qt_settings.cpython-310.pyc | Bin 5364 -> 5364 bytes .../settings_window.cpython-310.pyc | Bin 2511 -> 2511 bytes src/gui/app.py | 85 ----- src/gui/mainGui.py | 32 ++ src/gui/plot_window.py | 307 ------------------ src/gui/plotter.py | 158 +++++++++ src/main.py | 133 ++------ src/uml/__pycache__/__init__.cpython-310.pyc | Bin 241 -> 241 bytes src/uml/__pycache__/creator.cpython-310.pyc | Bin 3377 -> 3377 bytes .../request_generator.cpython-310.pyc | Bin 4202 -> 4202 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 269 -> 269 bytes src/utils/__pycache__/base.cpython-310.pyc | Bin 0 -> 5392 bytes .../__pycache__/base_widgets.cpython-310.pyc | Bin 0 -> 2061 bytes .../diagram_parser.cpython-310.pyc | Bin 2813 -> 2813 bytes .../__pycache__/json_tools.cpython-310.pyc | Bin 869 -> 869 bytes .../base/__pycache__/base.cpython-310.pyc | Bin 0 -> 7743 bytes .../__pycache__/base_widgets.cpython-310.pyc | Bin 0 -> 2066 bytes src/utils/base/base.py | 255 +++++++++++++++ src/utils/base/base_widgets.py | 47 +++ 45 files changed, 612 insertions(+), 499 deletions(-) create mode 100644 src/controller/__pycache__/controller.cpython-310.pyc create mode 100644 src/controller/__pycache__/converter.cpython-310.pyc create mode 100644 src/controller/__pycache__/ideal_data_builder.cpython-310.pyc create mode 100644 src/controller/__pycache__/mediator.cpython-310.pyc create mode 100644 src/controller/__pycache__/monitor.cpython-310.pyc create mode 100644 src/controller/__pycache__/monitor.cpython-311.pyc create mode 100644 src/controller/controller.py create mode 100644 src/controller/converter.py create mode 100644 src/controller/ideal_data_builder.py create mode 100644 src/controller/mediator.py create mode 100644 src/controller/monitor.py create mode 100644 src/gui/__pycache__/mainGui.cpython-310.pyc create mode 100644 src/gui/__pycache__/plotter.cpython-310.pyc delete mode 100644 src/gui/app.py create mode 100644 src/gui/mainGui.py delete mode 100644 src/gui/plot_window.py create mode 100644 src/gui/plotter.py create mode 100644 src/utils/__pycache__/base.cpython-310.pyc create mode 100644 src/utils/__pycache__/base_widgets.cpython-310.pyc create mode 100644 src/utils/base/__pycache__/base.cpython-310.pyc create mode 100644 src/utils/base/__pycache__/base_widgets.cpython-310.pyc create mode 100644 src/utils/base/base.py create mode 100644 src/utils/base/base_widgets.py diff --git a/params/system_params.json b/params/system_params.json index 017e7fb..58e2c7e 100644 --- a/params/system_params.json +++ b/params/system_params.json @@ -1,4 +1,6 @@ { + "trace_storage_path": "D:/downloads/a22", + "monitor_update_period": 100, "a_max_1": 5.41, "v_max_1": 0.108, "a_max_2": 35.81, diff --git a/src/OptAlgorithm/__pycache__/AutoConfigClass.cpython-310.pyc b/src/OptAlgorithm/__pycache__/AutoConfigClass.cpython-310.pyc index d27e9691bd21b728c702fe26491598ec8e05272b..68246f15dadafb298d85e68a579c2c46103b579b 100644 GIT binary patch delta 39 tcmdnbwx5kVpO=@50SFFAxh&*n;&ZWzamh@KFG?*aj!87yEXkzC2mrk`3FrU- delta 39 tcmdnbwx5kVpO=@50SM|B7%t>y;!ClLamh@KFG?*aj!87!EXkzC2mr)G3ON7( diff --git a/src/OptAlgorithm/__pycache__/ConstantCalculator.cpython-310.pyc b/src/OptAlgorithm/__pycache__/ConstantCalculator.cpython-310.pyc index 3946d0f52edf66c15d650b00e74fd859174c0250..22ef9194d297bc27a5d2f6cd2f44cfc392a59d6e 100644 GIT binary patch delta 27 hcmbQjIfauupO=@50SFFAxoqTaW@I$l+|S6$3;<8_1+@SG delta 27 hcmbQjIfauupO=@50SF3T8*b!oW@I$n+|S6$3;EFJj9_Fuw3*L3n-KuVR2nz{ diff --git a/src/OptAlgorithm/__pycache__/OptTimeCalculator.cpython-310.pyc b/src/OptAlgorithm/__pycache__/OptTimeCalculator.cpython-310.pyc index a50de4f3ce0bd1f273e67f0e67a6964560d06110..05c8dd596347fbfa90edc5910e6d8b3b5387e84e 100644 GIT binary patch delta 27 hcmX?LbHIi>pO=@50SFFAxoqTCVP-ViY``oa4FFzB1>67t delta 27 hcmX?LbHIi>pO=@50SF3T8*b!QVP-VkY``oa4FF@S21)<` diff --git a/src/OptAlgorithm/__pycache__/PhaseCalc.cpython-310.pyc b/src/OptAlgorithm/__pycache__/PhaseCalc.cpython-310.pyc index 137f01740ce4736847a32a6d641e7c167f6dedc1..82239915ca88532e725903ce8668863c0606f92d 100644 GIT binary patch delta 39 tcmaFG@rr{xpO=@50SFFAxlH8#%;#biiR delta 24 ecmbQlIEj%vpO=@50SF3T8&2f*VlW&;2}w*`#= diff --git a/src/__pycache__/main.cpython-310.pyc b/src/__pycache__/main.cpython-310.pyc index 2f36987a004e08b68f2ad6fd500870d8afe3832a..5c5e522fd647df44c95dfc89c5c4f4b997cc2a98 100644 GIT binary patch literal 1391 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 RY}IL4jdR`=uZB?k?7!y|wtD~o diff --git a/src/controller/__pycache__/controller.cpython-310.pyc b/src/controller/__pycache__/controller.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f7317785c0b408d065c8558f4fa3245480eb75db GIT binary patch literal 698 zcmYjPO>5jR5S48CgRM6Wv{0IV;2umVw3Jdp$u9J^WZ6T&F$mY1U0h^)BWWpHa!Y?m zd+cA*wWt1toHEj~i3Kx$GnU?agEUO16N2md?R@ir67tU#%0J$5TuAu7jq^2BPB zA6{MCSb^E8e$fOY5r;#J8HPT^bW6UI-}ILL@$(`ZUF3m1(cUyaaxv&ygMFq!u2qcZ z{u1>JKlc~&Pu0Awxq_{(>UY%@NYVD2)pjtKpw@%x>b`+WtEOrmM<2mrySJH!UL3U? zt9CX|>CabBa~0z~d1_P6`?>?p?S%7g5IgB`#`(>zmWMye4QiQewNWWTf#&Twol4k dtfv}DdIwI|rk@Y?&+%;%?Tlt5qgn7Wd;oRqrj`Hz literal 0 HcmV?d00001 diff --git a/src/controller/__pycache__/converter.cpython-310.pyc b/src/controller/__pycache__/converter.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..05a99387fafeef2721b072c1d73c8874ac54e18b GIT binary patch literal 1226 zcmZ`&&2AGh5VpPE%?}CCQXvYwz+R#XaY9j5XjEe7$@uK$bnfR?4{9S^QR>leL9VExiXF0RVC0%?l5@Hs3%W_JB1EC$?{I>iA>4(m$@pOJ2E$quDLdFpd1&RP zoL99Ayl_PwB3Yk?mesRT<~n5-JCOB08&ita#UI2z0Ozl_qc@XLAqCuZ6ZvZLQI`t1 z+@Bf$LEEXZm8^3;aW^8|TQ(?Lw@$8o{t>yL=gboiY#gx#yI^2Pphs66_*qR7FcgjdN&7y; za!)}V0+F9u=hOrB3wlkzv17KsZjYT{qXM_6%uc#6@8iQeJa#^}I_-s-`NGuU2~6f-?u*h5KEu~+& Pw(%Y0u5R?s6{RW z`_jog`2;%A=?~DU5w}U6YIz0A$zRHbrHIF8DwxmOD7RL@$UZ0>pSGRxs&74(ZByAz%)(9RO}!7xWMtU^ z`^?LGcuvs6E&LK&v6a6i^(VG~QUfu`3w!jM+DYOh3`7uTh_6>F=|n=TaUZSmDOZJW(i*Y=mjSFNvAQ<@_9vLM~PZ=Ex~ z7`sDFbHnT1;8xv@e?;}Cv;wm|5p(hV#ltbI{>xiVS!$zdLsI96b*l%*{sQsapxpi@ z)wb-%!ZF*+E{$`DenA{N;9uf12A&r;ISQD;OEI3%b37yctD(0ptgh+RNAQv|}3yv7ZF*^q6j8z2oe|;n#pu;n9%cKcdxRNTk=EV z(ZAFOFP{7h9*kAJNnCB{>Z(_>)vsRHb{iWRfi-?NIsNVt@&kkQ6+keCt>1&;gi}ch z3a2N%#xHz|m@k7SEJEi8GHT)?ZjvHt(jslLBBSIj;USMM36Dg4;THo=kH|3o2^Gn~ zklOG=TX!uu@!@gJPlXuO0yaI%+&S1Kn41UO=fP!A zqK88zO8r}A@h=3fQp-d9R*@euGG zz@w}9A3Op4Dd6cZAl!b1hoVKD)QkL*E8k$hk`4JB8Epji_xnevKzDW|O*P zO7wbGKARm2$?Nv?sPD{FsClQFvaQ5St7`VQ_^i2kdTgwT0Mchjm)wK z2^@oBYq~r%&qs$h!>Qd(_5tWIT9{hu(FqK%GYbE9|1oy;*Vs66NXaHISAD;t5NUjo LgrI6W-nRb-9}4&} literal 0 HcmV?d00001 diff --git a/src/controller/__pycache__/monitor.cpython-310.pyc b/src/controller/__pycache__/monitor.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c3e89e85a01971174e87209d3e3099d4ac95c0a6 GIT binary patch literal 1378 zcmZ`(&2HQ_5GE<=XV~}o zy--dL(7Z!YV14u}@tRX#p_g=qvQf8gDQIRWa)#f0GgP;~KPE8B$0w^FBSJpl%9QA&I1#G_<4?ZKhetKu0=ic*(;zuHz;t6H2}#GM33ZA`_KdL}e=3DJjxFAPOm{ zkF8c}Jp(Jz-D;%_Scl(KR-M#FEnH{LUv_N`dVvnN2ZPBAc zl7r?lhQks+xf6|o)6Kw0kTUreUi%n?BRkrYGj>Ve(jF`k!Hl29y99K42}!$bHS&TjFtWR}qove+&CqNEKiFM_E@`+g1T3MfO))G8~s~cr} zimKZ!7`TwJA&e6J-uM?&B``CUBQaj!*Ya@#It|EL1@^*4-n2Iz&WEk2Em}V zm(Y?|bXIVaz>4RgIQ*=uTZ1WFQBQxlqUIjhfn{?aw`I?D)x46`@gdACHqnG^zq(7% z4Y|*Cx2Uu|p5FM~0f;dIK)i}QW=ejhr^Mg^1vMj3=5rJeQDD6T67vOEpTZkJjLG(J zrrsQdwm6c?K?f=M?5M~?b|ytPOv@*>GqB`2HmHx9YV8y7a>|50GY7b7BpM~5pF87| zwsZCJJm4szfexgy9JT7r(8>d-01r7b`ykM;pMl8f1fJ|8XA^n=9mVOG@{ikx|4Z4d zh@tmITQy1uKNfHe0!knXW^*f_(06x?8LB&)LATUMlzPC2EP@V=i$a7 z?SY#T|3MqG8Lrs_xFpk!tF@iJf*(>4274%Y|JPB_5(C0xY&VNl%t=Obmb1g?FT{L9 Aga7~l literal 0 HcmV?d00001 diff --git a/src/controller/__pycache__/monitor.cpython-311.pyc b/src/controller/__pycache__/monitor.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..529ca51cbb8430de68dc7243505a7afee3237c02 GIT binary patch literal 2271 zcmb7FO=ufO6rR~#$t!yutFGeKKW$~up=(n$7zZ3X_z(;wgsQkoF2b;twQG0Pl~$cy zHMLPd2Sa7>vBiZp;7eV*PH9gihn{-saTNp+0|rAc?ajtHl$`ozq+M&{rqJ2hH*emX zdHdd*Z{B`CIM|P%ef#J9dPYR(4>s{zq|2OVfZ0Vl(y@g~IEOLg1xv^YFp8E~l5!H4 zNmis3%|$U1(0fRaY#}{rMEAk&5xkw2>(hlSQv3d5Qx(&QV;M#z16m&|cJ+^^UN%&!2~_V&uN! zYY-~Nd|t;duG103C}cK=yE#glkSa6p8v3N#PX*hdeU|CCx=HAe2DFn?rcrIp zveMkTYnW~%~~9K%|p5pKg_=}9J^ z-_Yk*mdw0HjEb{zm*fk^l2NjIIENHgz^+Sd%QDDH*KoSBK?gMEy5_jx%I3t2XO`~K z4#2k@hR8ZPjt_s?|MhHZ{M}~!S}T675owQ%H>90`6Ip4=qb+&zsjNPc)q~Wdcbf8C zOP=%Oxnudt&VZMAyD6(JS@ryW4i-@%I9Zsm4{>bV0_hhoMaTAkpu-JL7$G+}N8p+5 zZfl@547iouL0^IpmkC>P4evv0k1o&`o`tX&#>NAoCXgHM(1p#S?DM)<6TU$Yh42oH zAd0!Xj3?V(j7UccPcd2K_iS+=U2K%h63g_g45DGO~SzLR;XOg>R2_fiM3rZUq~W;|u4J@!^( zY3ELR2=?RH8||?PHf_LjD#Dx#IV3V_1WKz`&X){Lqx~9GS-om8UeUBqt9h%VA?)mU zZVo$8>LiQR6~YJuxibT#9z3T~Br+zoC-m8rzbKRb}lyF9gWQuVN!u}2F1h7cbAY*mZ*#H7jW86j~UbweWtj?bkH0p)>37Yc4 X{WLm^A%e@qdu{rRiJ$$8j=S~`8Ib&6 literal 0 HcmV?d00001 diff --git a/src/controller/controller.py b/src/controller/controller.py new file mode 100644 index 0000000..bafe0ff --- /dev/null +++ b/src/controller/controller.py @@ -0,0 +1,12 @@ +from PyQt5.QtWidgets import QWidget +from PyQt5.QtCore import pyqtSignal + +from src.utils.base.base import BaseController + + +class Controller(BaseController): + + signal_widgets = pyqtSignal(list) + + def send_widgets(self, widgets: list[QWidget]) -> None: + self.signal_widgets.emit(widgets) diff --git a/src/controller/converter.py b/src/controller/converter.py new file mode 100644 index 0000000..f281298 --- /dev/null +++ b/src/controller/converter.py @@ -0,0 +1,20 @@ +import pandas as pd + +#FIXME: костыль для выключения предупреждения "replace deprecated". Потом надо поправить. +pd.set_option('future.no_silent_downcasting', True) + +from src.utils.base.base import BaseDataConverter + + +class DataConverter(BaseDataConverter): + + @staticmethod + def _replace_bool(dataframe: pd.DataFrame) -> pd.DataFrame: + bool_columns = dataframe.columns[dataframe.isin([True, False]).any()] + dataframe[bool_columns] = dataframe[bool_columns].replace({True: 1, False: 0}) + return dataframe + + def convert_data(self, files: list[str]) -> None: + dataframes = [pd.read_csv(file) for file in files] + converted_dataframes = list(map(self._replace_bool, dataframes)) + self._mediator.notify(self, converted_dataframes) diff --git a/src/controller/ideal_data_builder.py b/src/controller/ideal_data_builder.py new file mode 100644 index 0000000..9a25ec0 --- /dev/null +++ b/src/controller/ideal_data_builder.py @@ -0,0 +1,8 @@ +from src.utils.base.base import BaseIdealDataBuilder +import pandas as pd + + +class idealDataBuilder(BaseIdealDataBuilder): + def __init__(self,operator_config: dict, system_config: dict): + super().__init__(operator_config, system_config) + self.mul = 10000 diff --git a/src/controller/mediator.py b/src/controller/mediator.py new file mode 100644 index 0000000..c564840 --- /dev/null +++ b/src/controller/mediator.py @@ -0,0 +1,21 @@ +import pandas as pd + +from typing import Union +from PyQt5.QtWidgets import QWidget + +from src.utils.base.base import BaseMediator, BaseDirectoryMonitor, BaseDataConverter, BasePlotWidget + + +class Mediator(BaseMediator): + + def notify(self, + source: Union[BaseDirectoryMonitor, BaseDataConverter, BasePlotWidget], + data: Union[list[str], list[pd.DataFrame], list[QWidget]]): + if issubclass(source.__class__, BaseDirectoryMonitor): + self._converter.convert_data(data) + + if issubclass(source.__class__, BaseDataConverter): + self._plot.build(data) + + if issubclass(source.__class__, BasePlotWidget): + self._controller.send_widgets(data) diff --git a/src/controller/monitor.py b/src/controller/monitor.py new file mode 100644 index 0000000..a5229af --- /dev/null +++ b/src/controller/monitor.py @@ -0,0 +1,28 @@ +from time import sleep +import os + +from loguru import logger + +from src.utils.base.base import BaseDirectoryMonitor + + +class DirectoryMonitor(BaseDirectoryMonitor): + + def _init_state(self): + files = os.listdir(self._directory_path) + self._files = files + + self.update_timer.timeout.connect(self._monitor) + logger.info("Monitor initiated!") + + def _monitor(self): + files = os.listdir(self._directory_path) + new_files = sorted(list(map(lambda x: os.path.join(self._directory_path, x), + filter(lambda x: x not in self._files, files)))) + if new_files: + logger.info(f"New files detected: {new_files}") + self._mediator.notify(self, new_files) + self._files = files + if not files: + self._files = [] + diff --git a/src/gui/__init__.py b/src/gui/__init__.py index 58fa804..03363c8 100644 --- a/src/gui/__init__.py +++ b/src/gui/__init__.py @@ -1,3 +1,2 @@ -from .plot_window import Plotter +from .plotter import PlotWidget from .settings_window import settingsWindow -from .app import tabWidgetGenerator diff --git a/src/gui/__pycache__/__init__.cpython-310.pyc b/src/gui/__pycache__/__init__.cpython-310.pyc index ccbb522b5b1ca8de813d923f506b3f978f2fdbef..4d2a80231dae29a24aa945a59b19a4be71e68f62 100644 GIT binary patch delta 125 zcmZ3=^o@}>pO=@50SGR7xTO0{$ovbzLlIAc;Mt2;^BV;3_Mq?0mR4&ZUuM4d&71GNyw}6;huqk89Sxr^x0~%d zZ{7W}v)qZZhhfkbnXIvQY(suxwke+zA80JAM{M;`rIRPlpfVVYi)*$rbC{&PmGAASh5GH+`9ABJvXsJWBIo zDzYY~hJFf`F~_Yq?li--4C=&GkXh`+JX6#OqWX}!k2Y4qh;D%aB8y1gjRWBoRDCc? zq=lCZr2>w5h0_>3|6#8i$Gxq-gzIW7t delta 1051 zcmZWoOHb5L6mC16PTP4hpbX%HS0*U|q7e|?7;vI7#stO0#7t-^y$r>fX>)oJHAEJy z+@R*J+_=|-g)wgZ4eH8t>CTN?6A96C?hp}e(=Yda=l$qzr-l5@)9vsN9| zFvFx6MhrY2!hvFvKVm0-XgfW9sQ7cLcClUyJQr9L*S)jiWoo+6kAj?9Qf+)os`!%H z8B5CXYPjLXjPsz~h~1U-_VTx1_&6qXQ9#3sBG&eyES~GmbU{)Zf!|=<(V#+CJ@WV} zP|yxgl*C2_x1-lDzU%KVkt&Qzec$6=Vh29+nl2Ao>|fimOU8fXl-H2>n*O-eOFm8! zqzLllErY4o&>?iwEsK`(Vc4t%%N%-$$su#48G2k&$A~H*bqj;v4qD_Jj!QpC-Uxl> zq-0evOr(L+h#4FtNW}wH2ZIRJch@rK)Zs}yVy~u&rgNu8>mDZI`jo}Ecx6_%4&~#d zG(&KnV3yzlLZY|57IVr_q>F{=EXehM9BGsYs9-P%CJ>S|c>j<`55KEcf;*s@&IU($^I|C?(5dtbE(VIcclk^HrNmeHNE5l2lf9;2i zC`VwSC4DhvX)2~_mPAkX?d)apXteI%oQtAF$3H6SL>fXK=1Hithiv&jpJG2dlD}%J M2L2nSnp5??--Xcz5&!@I diff --git a/src/gui/__pycache__/mainGui.cpython-310.pyc b/src/gui/__pycache__/mainGui.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..913dfe6c9ef3a8f2c0a07be43e70aab75e796fad GIT binary patch literal 1560 zcmZ8hU60#D6rJ%`?0m7MMct|uf`=d?K~y1CLI@$$4Z9#{v?0(HR?x`JOoF#goX$*G zvhqH4rT&fNasSf1^2A@*7r1x4q27))*LUoD$M>8$*LkZ|Coq0~+@D>$g#3+*>hNIk zElkx1!wIJunUk1O^qtI^yRmD1H}mFx>|5WZ&Se<8ylKDg#U8H-Uj(PM2ZX!an|eIt(WM9V)Oq8Q#L*k#k+=@EwM@P8MQZmi z4f?>3o$4cSGnc>I8s70 zrPmpv_ms${SHJ>elPpn+u`6=@W&f*jKTVhvOEpfu7@vrYr;FKWnd@UAr@5Rbi-{O3 zIT_DZ>39xI9j(&daxEh$FNCQAFm)QzHa)-l7FX|WF;eK2Tnr{vqz)t@(gWP#GcelX zEC_SJbGPJz7Ifnk38p410j!o|2(4ksWgcMwOTL#Aai5$ya<=Qq}wvkw2f^F8Z4W1UgAQPNc#-Vo6k9?6uK zRLFZ!ocsXI`(R7}d;zP*;o7*1{LF+(%PDqIya)UptfUl+n_lYrmPUCW6B`vSj0>k> zycvAu9d1oq{gIzB8w)Y&E~KhGFd@(!(mGs^fNbyj{6U58+c~$0M$&OwqCW%&v_rN; z(^KcABU_*zP!#?(Ms}9^@r?UYtR;5134Ro7cKF2jlT0LXrwk`~{BGqfNI8~5sqg*- z1|C7K)qfk*;r)BQUn%!iAnb_v2HggB=^~j6=+Zi4^PI0T^qY*mS|wTe#`cyKpz*R4 zs7Im8eKa4V`2>t<-L&yUWEo?XI-3|`C5)Ykt)fuNA!*XOzaQ*H5}yyckwnVmLomia zUJvz?QXx(2_lEi)m%`E$KZO48t#q2H-V69&TC-EUM3vhuD>c|&!WvBYb&2sC?0#EF MlQf+s@O97m5BIG4I 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 literal 0 HcmV?d00001 diff --git a/src/gui/__pycache__/qt_settings.cpython-310.pyc b/src/gui/__pycache__/qt_settings.cpython-310.pyc index 0a6353d4b8c694d7a200b2e36b2a4aa1992e7134..c37cdc555af06dafece7a0bb5a8607b0891d1591 100644 GIT binary patch delta 90 zcmeyO`9+gEpO=@50SFd&xNPKpFU)vr@^9gE>nMJw%=F;W1nr!5LFU%M<`L}So^(}s<%=F;Wj@kOZx#W9J7ljn+r0|0N!9#H@Q diff --git a/src/gui/__pycache__/settings_window.cpython-310.pyc b/src/gui/__pycache__/settings_window.cpython-310.pyc index 15e1b4b7e8afd2289525da6e88fab8f87d4d9fd7..aca61fa8473ec56fcfd91b6c45c8eeddef523c11 100644 GIT binary patch delta 33 ncmX>vd|sG4pO=@50SFFAxoqTK%*1H4c|Fr2HpW|%gE(seld1`4 delta 33 ncmX>vd|sG4pO=@50SF3T8*b!Y%*1H8c|Fr2HpZyQL7cS!nI8#N diff --git a/src/gui/app.py b/src/gui/app.py deleted file mode 100644 index d29b0ed..0000000 --- a/src/gui/app.py +++ /dev/null @@ -1,85 +0,0 @@ -import pyqtgraph as pg - -from src.utils import read_json, DiagramParser -from src.uml import Request, UMLCreator -from src.OptAlgorithm import OptAlgorithm -from src.gui import Plotter, settingsWindow - - -class tabWidgetGenerator: - def __init__(self, directory_to_save): - self.UMLgenerator = Request(server_url='http://www.plantuml.com/plantuml/svg/') - self.uml_creator = UMLCreator(request_generator=self.UMLgenerator, path_to_save=directory_to_save) - self.operator_params = read_json("params/operator_params.json") - self.system_params = read_json("params/system_params.json") - self.operSettings = settingsWindow("params\operator_params.json", 'Operator', self._update) - self.sysSettings = settingsWindow("params\system_params.json", 'System', self._update) - - self.paths = [] - self.plotters = [] - self.bool_dicts = [] - self.float_dicts = [] - self.timings_dicts = [] - self.modes = [] - self.names = [] - - def get_widget(self, path): - self.paths.append(path) - self.plotters.append(Plotter(show_settings_func=self._show_settings)) - self._getParsedData(path) - self._update() - return self.plotters[-1].widget - - def _get_ideal_timings(self, opt: OptAlgorithm) -> list[float]: - data = opt.Ts - ideal_time = [data['tclose'], data['tgrow'], opt.getMarkOpen(), data["tmovement"]] - return ideal_time - - def _getParsedData(self, path): - self.names.append(path) - parser = DiagramParser(system_config=self.system_params) - parser.setData(path) - self.bool_dicts.append(parser.getBoolDict()) - self.float_dicts.append(parser.getFloatDict()) - self.timings_dicts.append(parser.getRealTimings()) - self.modes.append(parser.getMode()) - - - def _update(self, _ = None): - self.operator_params = self.operSettings.getParams() - self.system_params = self.sysSettings.getParams() - - opt_algorithm = OptAlgorithm(operator_config=self.operator_params, system_config=self.system_params) - ideal_times = self._get_ideal_timings(opt_algorithm) - - for i in range (len(self.plotters)): - self.plotters[i].update_data(operator_config=self.operator_params, - system_config=self.system_params, - opt=opt_algorithm, - bool_dict=self.bool_dicts[i], - ideal_time=ideal_times, - float_dict=self.float_dicts[i], - mode = self.modes[i], - timings_dict=self.timings_dicts[i]) - - self.uml_creator.update_uml(operator_config=self.operator_params, - system_config=self.system_params, - ideal_time=ideal_times, - bool_dict=self.bool_dicts[i], - float_dict=self.float_dicts[i], - mode = self.modes[i], - timings_dict=self.timings_dicts[i], - name = self.names[i]) - - - def _show_settings(self): - self.operSettings.show() - self.sysSettings.show() - - -if __name__ == '__main__': - pg.mkQApp("Plotting") - temp = tabWidgetGenerator() - widget = temp.get_widget("trace_samples/2024_11_08-19_30_49.csv") - widget.show() - pg.exec() \ No newline at end of file diff --git a/src/gui/mainGui.py b/src/gui/mainGui.py new file mode 100644 index 0000000..35c68f2 --- /dev/null +++ b/src/gui/mainGui.py @@ -0,0 +1,32 @@ +from datetime import datetime as dt + +from PyQt5 import QtWidgets +from PyQt5.QtCore import Qt +from src.utils.base.base_widgets import BaseMainWindow + +class MainWindow(BaseMainWindow): + def __init__(self): + super().__init__() + self.initUI() + self.set_style(self) + + def initUI(self) -> None: + self.tabWidget = QtWidgets.QTabWidget() + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.tabWidget) + self.setLayout(layout) + + def show_plot_tabs(self, plot_widgets: list[QtWidgets.QWidget]) -> None: + for plot_widget in plot_widgets: + tab = QtWidgets.QWidget() + grid = QtWidgets.QGridLayout() + grid.addWidget(plot_widget) + tab.setLayout(grid) + self.tabWidget.addTab(tab, "SF_trace_" + dt.now().strftime('%Y_%m_%d-%H_%M_%S')) + self.tabWidget.setCurrentWidget(tab) + + def keyPressEvent(self, a0): + if a0.key() == Qt.Key_F5: + self.clear() + + diff --git a/src/gui/plot_window.py b/src/gui/plot_window.py deleted file mode 100644 index 3d5c0dc..0000000 --- a/src/gui/plot_window.py +++ /dev/null @@ -1,307 +0,0 @@ -import pyqtgraph as pg -from pyqtgraph.Qt import QtWidgets -from PyQt5.QtCore import Qt -import numpy as np - -from src.gui import qt_settings as qts - -from src.OptAlgorithm import OptAlgorithm - - -class Plotter: - def __init__(self, show_settings_func): - pg.setConfigOptions(antialias=True) - self.alpha = 100 #[0-255 прозрачность фона] - self._init_ui() - self.settings_button.clicked.connect(show_settings_func) - - - def update_data(self, - system_config : dict, - operator_config: dict, - opt: OptAlgorithm, - ideal_time: list[float], - bool_dict: dict, - float_dict: dict, - timings_dict: dict, - mode: bool): - self.opt = opt - self.bool_dict = bool_dict - self.float_dict = float_dict - self.timings_dict = timings_dict - self.idealTime = ideal_time - self.theor_mode = mode - self.scaler = int(system_config['UML_time_scaler']) - self.WeldTime = operator_config['time_wielding'] #[sec] - self.WeldData = self.opt.calcPhaseGrow(self.idealTime[1]) - self._updatePlots() - - - def _init_ui(self): - self.widget = QtWidgets.QWidget() - layout = QtWidgets.QVBoxLayout() - self.widget.setLayout(layout) - - self.win = pg.GraphicsLayoutWidget(show=True, title="") - self.win.resize(1000,600) - self.win.setWindowTitle('') - - layout.addWidget(self.win) - self.settings_button = QtWidgets.QPushButton("Show settings") - self.settings_button.setFixedWidth(160) - info_layout = QtWidgets.QHBoxLayout() - layout.addLayout(info_layout) - info_layout.addWidget(self.settings_button, alignment = Qt.AlignLeft) - info_layout.setSpacing(20) - self.efficiency = QtWidgets.QLabel() - info_layout.addWidget(self.efficiency, alignment = Qt.AlignRight) - - - - - self.p11, self.l11 = self._init_graph('Electrode force, closure', 'Force', 'N', 'Time', 'ms') - #self.p21, _ = self._init_graph('Electrode force, compression', 'Force', 'N', 'Time', 'ms') - #self.p31, _ = self._init_graph('Electrode force, compression', 'Force', 'N', 'Time', 'ms') - self.win.nextRow() - self.p12, self.l12 = self._init_graph('Rotor Position, closure', 'Posicion', 'mm', 'Time', 'ms') - #self.p22, _ = self._init_graph('Rotor Position, compression', 'Posicion', 'mm', 'Time', 'ms') - #self.p32, _ = self._init_graph('Rotor Position, compression', 'Posicion', 'mm', 'Time', 'ms') - self.win.nextRow() - self.p13, self.l13 = self._init_graph('Rotor Speed, closure', 'Speed', 'mm/s', 'Time', 'ms') - #self.p23, _ = self._init_graph('Rotor Speed, compression', 'Speed', 'mm/s', 'Time', 'ms') - #self.p33, _ = self._init_graph('Rotor Speed, compression', 'Speed', 'mm/s', 'Time', 'ms') - self.win.nextRow() - - self.p12.setXLink(self.p11) - self.p13.setXLink(self.p11) - - self.p11.setAutoVisible(x=False, y=True) - self.p12.setAutoVisible(x=False, y=True) - self.p13.setAutoVisible(x=False, y=True) - self.widget.setStyleSheet(qts.dark_style) - - def _init_graph(self, title, Yname, Yunits, Xname, Xunits): - plot = self.win.addPlot(title = title) - plot.showGrid(x=True, y=True) - plot.setLabel('left', Yname, units=Yunits) - plot.setLabel('bottom', Xname, units=Xunits) - legend1 = pg.LegendItem((80,60), offset=(70,20)) - legend1.setParentItem(plot) - return plot, legend1 - - def _updatePlots(self): - self.p11.clear() - self.l11.clear() - self.p12.clear() - self.l12.clear() - self.p13.clear() - self.l13.clear() - - if not self.theor_mode: - self._plotRealData() - self._form_idealdatGraph() - self._calcOurScore() - - def _calcOurScore (self): - success = [] - start = np.array(self.timings_dict["closure"])[:, 0] - end = np.array(self.timings_dict["opening"])[:, 1] - points_timings = end-start - - ideal_time = sum(self.idealTime[:3])+self.WeldTime - for point in points_timings: - success.append(int(ideal_time/point * 100)) - if len(success) > 1: - maxS = max(success) - minS = min(success) - average = int(sum(success[:])/len(success)) - self.efficiency.setText(f'Efficiency Maximum: {maxS}%, Average: {average}%, Minimum: {minS}%' ) - else: - self.efficiency.setText(f'Efficiency Maximum: {success[0]}' ) - self.efficiency.setStyleSheet(qts.BigSuccessLabel) - - - def _form_idealdatGraph(self): - - if self.theor_mode: - self.timings_dict["closure"] = [[0, self.idealTime[0]]] - self.timings_dict["compression"] = [[self.idealTime[0], sum(self.idealTime[:2])]] - self.timings_dict["welding"] = [[sum(self.idealTime[:2]), sum(self.idealTime[:2])+self.WeldTime]] - self.timings_dict["opening"] = [[sum(self.idealTime[:2])+self.WeldTime, sum(self.idealTime[:3])+self.WeldTime]] - - delta = 10 #points_per_ms - for key, items in self.timings_dict.items(): - for item in items: - item_data = [] - time_data = [] - - if key == 'closure': - ideal_time = self.idealTime[0] - calc = self.opt.calcPhaseClose - color = qts.RGBA[0] - for i in range(0, int(ideal_time*self.scaler)*delta): - time = i/delta - item_data.append(calc(time/self.scaler)) - time_data.append(time+item[0]*self.scaler) - #print (item_data[-1], time_data[-1]) - self._plotIdealData(np.array(time_data), np.array(item_data).T) - self._addBackgroundSplitter([item[0]*self.scaler,item[0]*self.scaler + time], color) - - elif key == 'compression': - ideal_time = self.idealTime[1] - calc = self.opt.calcPhaseGrow - color = qts.RGBA[1] - - for i in range(int(ideal_time*self.scaler)*delta, 0, -1): - time = i/delta - item_data.append(calc(time/self.scaler)) - time_data.append(item[1]*self.scaler-(ideal_time*self.scaler-time)) - #print (item_data[-1], time_data[-1]) - self._plotIdealData(np.array(time_data), np.array(item_data).T) - self._addBackgroundSplitter([(item[1]-ideal_time)*self.scaler, item[1]*self.scaler], color) - - temp = item_data[0][4] - x = [time_data[0], time_data[-1], time_data[-1]-0.0001] - y = [temp, temp, temp] - a1, b1, c1 = self._calculate_equidistant(x, y, 2.5, 3) - self.p11.addItem(a1) - self.p11.addItem(b1) - self.p11.addItem(c1) - - elif key == 'welding': - ideal_time = self.WeldTime - calc = self._returnWeldData - color = qts.RGBA[2] - - for i in range(0, int(ideal_time*self.scaler)*delta): - time = i/delta - item_data.append(calc(time/self.scaler)) - time_data.append(time+item[0]*self.scaler) - #print (item_data[-1], time_data[-1]) - self._plotIdealData(np.array(time_data), np.array(item_data).T) - self._addBackgroundSplitter([item[0]*self.scaler,item[0]*self.scaler + time], color) - - x = [time_data[0], time_data[-1], time_data[-1]+0.0001] - y = [item_data[0][4], item_data[0][4], item_data[0][4]] - a1, b1, c1 = self._calculate_equidistant(x, y, 0.75, 3) - self.p11.addItem(a1) - self.p11.addItem(b1) - self.p11.addItem(c1) - - elif key == 'opening': - calc = self.opt.calcPhaseOpen - ideal_time = self.idealTime[2] - ideal_closure = self.idealTime[3] - color = qts.RGBA[3] - color_closure = qts.RGBA[4] - - for i in range(0, int(ideal_time*self.scaler)*delta): - time = i/delta - item_data.append(calc(time/self.scaler)) - time_data.append(time+item[0]*self.scaler) - #print (item_data[-1], time_data[-1]) - self._plotIdealData(np.array(time_data), np.array(item_data).T) - self._addBackgroundSplitter([item[0]*self.scaler,item[0]*self.scaler + time], color) - - item_data = [] - time_data = [] - for i in range(0, int(ideal_closure*self.scaler)*delta): - time = i/delta - item_data.append(self.opt.calcPhaseMovement(time/self.scaler)) - time_data.append(time+item[1]*self.scaler) - self._plotIdealData(np.array(time_data), np.array(item_data).T) - self._addBackgroundSplitter([item[1]*self.scaler,item[1]*self.scaler + time], color_closure) - - def _returnWeldData(self, _): - return self.WeldData - - - - def _plotRealData(self): - for i, (key, dat) in enumerate(self.float_dict.items()): - dat = np.array(dat).T - dat[0] = dat[0]*self.scaler - curve = pg.PlotDataItem(dat[0], dat[1], pen=pg.mkPen(color=qts.colors[i], width=2), name=key, autoDownsample=True, downsample=True) - if 'Electrode Force' in key: - self.p11.addItem(curve) - self.l11.addItem(curve, key) - elif 'Rotor Position' in key: - self.p12.addItem(curve) - self.l12.addItem(curve, key) - elif 'Rotor Speed' in key: - self.p13.addItem(curve) - self.l13.addItem(curve, key) - return dat[0] - - def _plotIdealData(self, time, data): - x_fe = pg.PlotDataItem(time, data[0]*1000, pen=pg.mkPen(color=qts.colors[8], width=2), name='x_fe', autoDownsample=True, downsample=True) - x_me = pg.PlotDataItem(time, data[1]*1000, pen=pg.mkPen(color=qts.colors[9], width=2), name='x_me', autoDownsample=True, downsample=True) - v_fe = pg.PlotDataItem(time, data[2]*1000, pen=pg.mkPen(color=qts.colors[8], width=2), name='v_fe', autoDownsample=True, downsample=True) - v_me = pg.PlotDataItem(time, data[3]*1000, pen=pg.mkPen(color=qts.colors[9], width=2), name='v_me', autoDownsample=True, downsample=True) - f = pg.PlotDataItem(time, data[4], pen=pg.mkPen(color=qts.colors[8], width=2), name='f', autoDownsample=True, downsample=True) - - self.p11.addItem(f) - #self.l11.addItem(f, 'Ideal force') - - self.p12.addItem(x_fe) - #self.l12.addItem(x_fe, 'FE POS') - self.p12.addItem(x_me) - #self.l12.addItem(x_me, 'ME POS') - - self.p13.addItem(v_fe) - #self.l13.addItem(v_fe, 'FE VEL') - self.p13.addItem(v_me) - #self.l13.addItem(v_me, 'ME VEL') - #self._addBackgroundSplitter() - #self._addEquidistances(time, data) - - def _addBackgroundSplitter(self, x, color): - alpha = self.alpha - y01 = np.array([10000, 10000]) - y0_1 = np.array([-10000, -10000]) - a01 = pg.PlotDataItem(x, y01, pen=pg.mkPen(color=qts.colors[8], width=2), name=' ') - a0_1 = pg.PlotDataItem(x, y0_1, pen=pg.mkPen(color=qts.colors[8], width=2), name=' ') - bg1 = pg.FillBetweenItem(a01, a0_1, color+(alpha,)) - bg2 = pg.FillBetweenItem(a01, a0_1, color+(alpha,)) - bg3 = pg.FillBetweenItem(a01, a0_1, color+(alpha,)) - self.p11.addItem(bg1) - self.p12.addItem(bg2) - self.p13.addItem(bg3) - - self.p11.setYRange(-1000, 5000) - self.p12.setYRange(-50, 250) - self.p13.setYRange(-400, 400) - - - def _makeFiller(self, x1, y1, x2, y2, color): - alpha = self.alpha - eq1 = pg.PlotDataItem(x1, y1, pen=pg.mkPen(color='#000000', width=1)) - eq2 = pg.PlotDataItem(x2, y2, pen=pg.mkPen(color='#000000', width=1)) - bg = pg.FillBetweenItem(eq1, eq2, qts.RGBA[color]+(alpha,)) - return eq1, eq2, bg - - - def _calculate_equidistant(self, x, y, percent, color): - if len(x) != len(y): - raise ValueError("x и y должны быть одного размера") - distance = max(y)/100*percent - x_eq1 = [] - y_eq1 = [] - x_eq2 = [] - y_eq2 = [] - - for i in range(0, len(x) - 1): - dx = x[i + 1] - x[i] - dy = y[i + 1] - y[i] - length = np.sqrt(dx ** 2 + dy ** 2) - sinA = dy/length - sinB = dx/length - - nx = -sinA*distance - ny = sinB*distance - x_eq1.append(x[i] + nx) - y_eq1.append(y[i] + ny) - x_eq2.append(x[i] - nx) - y_eq2.append(y[i] - ny) - - return self._makeFiller(np.array(x_eq1), np.array(y_eq1), np.array(x_eq2), np.array(y_eq2), color) \ No newline at end of file diff --git a/src/gui/plotter.py b/src/gui/plotter.py new file mode 100644 index 0000000..4b44628 --- /dev/null +++ b/src/gui/plotter.py @@ -0,0 +1,158 @@ +import pandas as pd +from PyQt5.QtWidgets import QWidget, QVBoxLayout +import pyqtgraph as pg +import numpy as np +from numpy import floating +from typing import Optional, Any, NamedTuple + +from src.utils.base.base import BasePlotWidget + + +class ProcessStage(NamedTuple): + mean_value: floating[Any] + start_index: int + finish_index: int + +class PlotWidget(BasePlotWidget): + + def _create_stage_ideal(self, + stage: str, + signal: str, + times: pd.Series, + dataframe: pd.DataFrame) -> Optional[pg.LinearRegionItem]: + stage_diff = np.diff(dataframe[stage]) + start_index = np.where(stage_diff == 1)[0] + finish_index = np.where(stage_diff == -1)[0] + data = self._stage_ideals[stage]() + + if start_index.size: + start_timestamp = times[start_index[0]] + finish_timestamp = times[finish_index[0]] if finish_index.size else times[len(times) - 1] + plot = pg.PlotDataItem(x=start_timestamp+data["time"], y=data[signal["name"]], pen=signal["pen"]) + return plot + return None + + + def _create_stage_region(self, + stage: str, + times: pd.Series, + dataframe: pd.DataFrame) -> Optional[pg.LinearRegionItem]: + stage_diff = np.diff(dataframe[stage]) + start_index = np.where(stage_diff == 1)[0] + finish_index = np.where(stage_diff == -1)[0] + + if start_index.size: + start_timestamp = times[start_index[0]] + finish_timestamp = times[finish_index[0]] if finish_index.size else times[len(times) - 1] + region = pg.LinearRegionItem([start_timestamp, finish_timestamp], movable=False) + region.setBrush(pg.mkBrush(self._stage_colors[stage])) + return region + return None + + @staticmethod + def _init_plot_widget(title: str) -> (pg.PlotWidget, pg.LegendItem): + plot_widget = pg.PlotWidget(title=title) + plot_widget.showGrid(x=True, y=True) + legend = pg.LegendItem((80, 60), offset=(70, 20)) + legend.setParentItem(plot_widget.graphicsItem()) + return plot_widget, legend + + def get_stage_info(self, + stage: str, + dataframe: pd.DataFrame, + signal_name: str) -> Optional[ProcessStage]: + if stage in self._stages: + stage_diff = np.diff(dataframe[stage]) + start_index = np.where(stage_diff == 1)[0] + finish_index = np.where(stage_diff == -1)[0] + + data = dataframe[signal_name] if signal_name in dataframe.columns.tolist() else [] + + if data.size and start_index.size: + start = start_index[0] + finish = finish_index[0] if finish_index.size else (len(data) - 1) + data_slice = data[start:finish] + mean = np.mean(data_slice) + return ProcessStage(mean_value=mean, start_index=int(start), finish_index=int(finish)) + return None + + def _build_widget(self, dataframe: pd.DataFrame) -> QWidget: + widget = QWidget() + layout = QVBoxLayout() + + time_axis = dataframe["time"] + dataframe_headers = dataframe.columns.tolist() + + for channel, description in self._plt_channels.items(): + plot_widget, legend = self._init_plot_widget(title=channel) + + settings = description["Settings"] + if settings["stages"] and all([stage in dataframe_headers for stage in self._stages]): + for stage in self._stages: + region = self._create_stage_region(stage, time_axis, dataframe) + for signal in description["Ideal_signals"]: + ideal_plot = self._create_stage_ideal(stage, signal ,time_axis, dataframe) + if ideal_plot: + plot_widget.addItem(ideal_plot) + + if region: + plot_widget.addItem(region) + + + if settings["zoom"]: + if max(time_axis) < 5.0: + stages = [self.get_stage_info("Welding", + dataframe, + signal["name"]) for signal in description["Real_signals"]] + if stages: + means_raw = [stage.mean_value for stage in stages] + mean = max(means_raw) + start = time_axis[stages[0].start_index] + finish = time_axis[stages[0].finish_index] + + overshoot = pg.BarGraphItem(x0=0, + y0=mean - mean * 0.05, + height=mean * 0.05 * 2, + width=start, + brush=pg.mkBrush([0, 250, 0, 100])) + plot_widget.addItem(overshoot) + + stable = pg.BarGraphItem(x0=start, + y0=mean - mean * 0.015, + height=mean * 0.015 * 2, + width=finish - start, + brush=pg.mkBrush([0, 250, 0, 100])) + plot_widget.addItem(stable) + + plot_widget.setYRange(mean - 260, mean + 260) + plot_widget.setInteractive(False) + else: + max_value = min([max(dataframe[signal["name"]]) for signal in description["Real_signals"]]) + region = pg.LinearRegionItem([max_value - max_value * 0.015, + max_value + max_value * 0.015], + movable=False, + orientation="horizontal") + + region.setBrush(pg.mkBrush([0, 250, 0, 100])) + plot_widget.setYRange(max_value - 200, max_value + 200) + plot_widget.setXRange(3.5, 4.5) + plot_widget.addItem(region) + plot_widget.setInteractive(False) + + for signal in description["Real_signals"]: + if signal["name"] in dataframe_headers: + plot = plot_widget.plot(time_axis, dataframe[signal["name"]], pen=signal["pen"]) + legend.addItem(plot, signal["name"]) + + + + layout.addWidget(plot_widget) + + widget.setLayout(layout) + return widget + + def build(self, data: list[pd.DataFrame]) -> None: + widgets = [self._build_widget(data_sample) for data_sample in data] + self._mediator.notify(self, widgets) + + diff --git a/src/main.py b/src/main.py index a0ae44a..02bc55d 100644 --- a/src/main.py +++ b/src/main.py @@ -1,115 +1,38 @@ import sys -import os -import time -from PyQt5.QtWidgets import ( - QApplication, - QMainWindow, - QTabWidget, - QWidget, - QVBoxLayout, - QLabel, -) -from PyQt5.QtCore import Qt, QThread, pyqtSignal, QObject, QFileSystemWatcher -from PyQt5.QtGui import QIcon -from src.gui import qt_settings as qts +from PyQt5 import QtWidgets +import json +from os import path -# Импортируйте ваш класс `app` здесь -# Предполагается, что класс `app` предоставляет интерфейс для отображения данных -# Если `app` не предоставляет виджет, возможно, потребуется его модифицировать -from src.gui.app import tabWidgetGenerator - - -class DirectoryWatcher(QObject): - - file_created = pyqtSignal(str) - - def __init__(self, directory_path): - super().__init__() - self.directory_path = directory_path - self.watcher = QFileSystemWatcher() - self.watcher.addPath(self.directory_path) - self.existing_files = set(os.listdir(self.directory_path)) - self.watcher.directoryChanged.connect(self.on_directory_changed) - - - def on_directory_changed(self, _): - try: - current_files = set(os.listdir(self.directory_path)) - new_files = current_files - self.existing_files - self.existing_files = current_files - for file in new_files: - if file.lower().endswith(".csv"): - full_path = os.path.join(self.directory_path, file) - self.file_created.emit(full_path) - except Exception as e: - print(f"Ошибка при обработке изменений директории: {e}") - - -class MainWindow(QMainWindow): - def __init__(self, directory_to_watch): - super().__init__() - self.setWindowTitle("Мониторинг CSV-файлов") - self.setGeometry(100, 100, 800, 600) - - self.tabs = QTabWidget() - self.tabs.setStyleSheet(qts.dark_style) - self.tabGen = tabWidgetGenerator(directory_to_watch) - self.handle_new_file() - self.setCentralWidget(self.tabs) - - # self.setWindowIcon(QIcon("path_to_icon.png")) - self.start_directory_watcher(directory_to_watch) - - - def start_directory_watcher(self, directory_path): - self.watcher_thread = QThread() - self.watcher = DirectoryWatcher(directory_path) - self.watcher.moveToThread(self.watcher_thread) - - self.watcher.file_created.connect(self.handle_new_file) - self.watcher_thread.started.connect(self.watcher.on_directory_changed) - - self.watcher_thread.start() - - def handle_new_file(self, file_path = None): - time.sleep(0.2) - if file_path: - file_name = os.path.basename(file_path) - else: - file_path = None - file_name = 'Ideal' - - tab_widget = self.tabGen.get_widget(path=file_path) - - tab = QWidget() - layout = QVBoxLayout() - layout.addWidget(tab_widget) - - label = QLabel(f"{file_name}") - label.setAlignment(Qt.AlignCenter) - layout.addWidget(label) - tab.setLayout(layout) - - self.tabs.addTab(tab, file_name) - - def closeEvent(self, event): - self.watcher_thread.quit() - self.watcher_thread.wait() - event.accept() +from src.gui.mainGui import MainWindow +from src.controller.monitor import DirectoryMonitor +from src.controller.mediator import Mediator +from src.controller.converter import DataConverter +from src.controller.ideal_data_builder import idealDataBuilder +from src.gui.plotter import PlotWidget +from src.controller.controller import Controller +from src.utils.json_tools import read_json def main(): - directory_to_watch = "D:/downloads/a22" + app = QtWidgets.QApplication(sys.argv) + operator_params = read_json("params/operator_params.json") + system_params = read_json("params/system_params.json") + monitor = DirectoryMonitor(system_params['trace_storage_path'], system_params['monitor_update_period']) + data_converter = DataConverter() + ideal_data_builder = idealDataBuilder(operator_params, system_params) + plot_widget_builder = PlotWidget(idealDataBuilder=ideal_data_builder) + controller = Controller() + mediator = Mediator(monitor, data_converter, plot_widget_builder, controller) + monitor.start() + window = MainWindow() - if not os.path.isdir(directory_to_watch): - print(f"Директория не найдена: {directory_to_watch}") - sys.exit(1) - - app_instance = QApplication(sys.argv) - window = MainWindow(directory_to_watch) window.show() - sys.exit(app_instance.exec_()) + + controller.signal_widgets.connect(window.show_plot_tabs) -if __name__ == "__main__": + sys.exit(app.exec_()) + + +if __name__ == '__main__': main() diff --git a/src/uml/__pycache__/__init__.cpython-310.pyc b/src/uml/__pycache__/__init__.cpython-310.pyc index d8643a537f96910b494dde168309414b2e6e3708..8a313df85224227d92e95fa74b7f79f0fb1fb420 100644 GIT binary patch delta 37 rcmey!_>qx2pO=@50SFFAxlH7q#^+)cqx2pO=@50SM|B7*6D##+PChSf~2=jG*M0D=QjE)%);G8#=h=>h;ghXw@z delta 24 ecmeBW>Sf~2=jG*M0D{8Th7-B>G8#@i=>h;kod$CN diff --git a/src/utils/__pycache__/base.cpython-310.pyc b/src/utils/__pycache__/base.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e6fe4f40d24c6de82b04e9bf4d42201debd9f8b1 GIT binary patch literal 5392 zcmcIo-ESMm5x;L9KP6EgPVCsBoi+_yMQM|!NsZLCBU|a06+3c~l$Ls+xht9Ok;m+v z8i;U#0ydiepy-1i5}`TC8loc-1Qr`m23)P-o154wi4}KztQeUMW5%czuy)+GHGGB@y90NBFs=DMj8!M z7_{`N$cw^#r(uhEF(YP)bHp5}v!F|FH)DBKigq)Jl+JacZX3)3sxP+{%^In_tApBn zE9(AIszfS1#~qqUb9Gqd^uj376*OEUE>%z$=$k}EVMrfw8+|a4TQ2FCJ>V@Wt5E*i z#N0LS8i8?_es_$(ylas}g(Qn4nFx&5 zv{6LWK$W_yomht33LsM@kP65wk$pog(d+Py%jY*Qx0`{Iy?C?v>gM}06z%TLMlVXP zNwpoRPP5yRo3Uzb?k4Rp-n>PYSn2I)KM2}n)*!&RF~;>=-}KD16wLl2Y?e7;CF`xd zINDV$d3b>lag!}R;gaPV*N*!ktr~e?OFM$v4_`}13EOdUGfvdja*f%ZSh-BiYpU6i zS=|6!TU#x_DSN=1RN$dU2sc<u;LwgKQJ9dBm z$imb1^}3&Wp@=cq6=iVjj~Q@qikc%*chcETqJpP<4z(^U-lg>ffi46D2C*B0F9pGe zyUj3dQP1F`Ga&Hp7=f}XPXr3Y9ueOtn3XcuwMabj3@~iQzozOe;G})eXgGOOoD$D{ zY;2pHGs+EDdg8Pwiqd`Op4rHebVig#g(aV)=f$j;V<}Hkje>Q7rGhNnDT=dVDU-zs z@yvarQ4-IJlk_fsY&b@vLIHhFLFsi}5gAZ|UNgC^ZSuG-?)C@?GDs+iXuD0=r$lNT zE@i2Q5thMls|6Ql4|w>DFkr?j#3aT&;}i2!0tCmY#qnu#Tsk`xmw|iN_{2l|5GD1T zcH`ZiRBU=Z6HMq>3dZ%z2U+ZDFW7E}GSxuYh1J`=-tZK`U&= zaS)84#}mFl?J?j~a6HSS@bj#a)jvHgs>VW4$z)e`TflwxfFH&I;DHP^h=jVSUZR?P zGu3W{ECv;n{T7u+Fr{bpUzj@iQL{X8YV}PTgu{;}t%JwVlQ@QHUPt|_MEYsA$e=Mu z>nmesKgtRu$5z!W&?)&@u<6gt?* zJ~e-3@$nyme2VqnARgrcwP>aBT1w z(Qc_%vi6KekBonfcrq0CK?dJ<(r>}1wckPS8TC9WY9MDpav%&J>4ohMMQB@=2_1nHtgf&^T^{6|mJGuz?{Mh9j4mAdNXwWst`YGm_$_z#ORG{cEqhcP z;(dG8;UwOojz=Ci_agEyk>O5*9YZ+6z3(<`>CizBr&H`Mu5|Bsw1X5gSuF5*)S(lv zNjt@&!mheLvh5S&LA^m8(|w*Z$(s--G8@cxl?pqW@RvGz{8%!~sUzapI#HrGozM79*CxDoY%xc*zQ|4MwPSH>Hb#}k$cgy}Hpd=wgC2_yaD#D?_UlXQ zl=Qv#WZ0J5I=31|G2JS3ZsWsUDf?3A2KS7*bMQGW?EpvI1Ei7zL4<0NWDWqxgP(!? zHm&^v{AVES?{%(Kfat+*K!7PTZXfllgO$`)ca@UegumXy<#&TJDlMA! zy^Zz`U4rBO!g~?jJZl?0DaCTF(|IMP-gL#d2?aMnuz+dZ)~H+mr760;SeuxCx%P`o z{p#_a<4YJ*fHtSEVPdu?4k9`iq^6+_fEl__hLMU%?1f3tx=nX{8OG{Oe8pSAD6TNb z7M1wtL<)2oEm)q)v7Y_!aiB%yron_Gyzeognx=G40~&-r8-4 z;*Xdbr>s8zIWlHXZcg+48aj<3;|F_-|l)m#%m8-+;pItIiYAUb5GtT%=$zg)^7-dd;qA#@gx$UAne+J$ZfQ zda@cRsa*8&Kyv6flQpLQeZ>l!65nq4M8_K@yN5NHrmXhgO8>67fJ_}@5hcU7W=-E( QFtO=Y7Ah}SW*0vA7grQzX#fBK literal 0 HcmV?d00001 diff --git a/src/utils/__pycache__/base_widgets.cpython-310.pyc b/src/utils/__pycache__/base_widgets.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7cad539658bfac7f050f71b905450d32f2798dbc GIT binary patch literal 2061 zcmcgt!EW0|5M5G~L`k-j0znb<#3m;Jv0(|d6DUOz$ZCoLiEBYg4X`TMm3AewUGB2G z%h*cWQ~M$9v8VnIuRZk_a_S7NBx%gg#3k@ zRqQf0yyOKADPw3=0 zW^-=y`f#bVhF|s7*(178nVq7qRjI({0rLM46iz~i5#a0>JiM^N>cF6pZ}q9+k7+EA zW69KMUQ?6r_|(4mr~v-@HR`QkiTX`m)7)lS=H8)_eCn=%qK>!+h`R;KPtI?Ux!;Sd z0iJtEohl*C;0;;24t^}XLBk21em~bLlWcpcgwnm>=I)@=>D<1%)_kU<-Ja1T7K>hR zW5nl*2T#AaaVs!Xnr*{%JiFkciJ$Xc(D@`iD;xb>!W%y3#?U#3GQ2za&VHxg?UvnR ztnZclQD#p1nYBv3JNbtX4-R&B?*^q*Ap1AUv)(ABjKy*eN$#d+L3eLmrqS6%X~v=0 zXl0a$S#a~S{r(*QUyFTizO5;XGt&$1yv^~_Lg!?(DOG9wZGU_=H%THw!M zciwWIU;lT@-+5(p*!Bv1je}9+6}4jGouNISfJVbKAsWUv(REx9YX!fcgCuhQ({tMQ9M~BQYlHaiRmXR)IoI5O0Ho~Q A`Tzg` literal 0 HcmV?d00001 diff --git a/src/utils/__pycache__/diagram_parser.cpython-310.pyc b/src/utils/__pycache__/diagram_parser.cpython-310.pyc index 6ee7ca1d5602a90ff6bf674c25093913290babd6..098b2f8e6bf4cb7052119da6a19dfba5ca9cfc10 100644 GIT binary patch delta 27 hcmew>`d5@YpO=@50SFFAxoqT?Vq!Gftj2Vm0{~`d5@YpO=@50SLYYm~7;hVq!Ghtj2Vm0|0312LS*8 diff --git a/src/utils/__pycache__/json_tools.cpython-310.pyc b/src/utils/__pycache__/json_tools.cpython-310.pyc index 6def11015fb2fce733811c9c49c3cec40c262f09..45c90a34260158c49616d82f9ed124d9b52f497d 100644 GIT binary patch delta 27 hcmaFL_LPk~pO=@50SFFAxoqSvV`Mbi+{E~p5ddJ~2NM7Q delta 27 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 literal 0 HcmV?d00001 diff --git a/src/utils/base/__pycache__/base_widgets.cpython-310.pyc b/src/utils/base/__pycache__/base_widgets.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0d4e21d165387499500cee27b8a26ea44e9bb152 GIT binary patch literal 2066 zcmcgt!EW0|5M5G~L`k-j0znbv#3m;Jv0(|d6DUOy$ZCoLiEBYg4X`TMm3AdFA$Qr` zWo#wwsr``l*i-*!uRZk_a_S7NBx7(jR@idL zmxNVW?H9soy!mq_++gmAwCjH%UfZ!PDuguD#8T+Pwrl;bGt_Bft4{JiM^N>cF63xB67`M>H14 zv0(Dl*5u?VpPE-U3gB!yEPBDs z5uZyQJo)P8?LbqZw>4Ms?1GCre!+V|=hN)0Z1htJZ}^C7P3IiS@Zsb;`<;HbTXv7J z{;%YZa(&XzjgjKR$v=2-aIm|3FDRt~*}qes^+p+GEEaP}ayL5*x_j#~jm{=gF%HE> zD=m|l1-HJ~@81RRwbf+q3H0(}iB5}2p?9){Z2(ZD5vc`E zHMZz2=f(AZ_WhkVMu%;$Afa$ND!igLU}<~Sk0L=+9!0hpMX6+Yg8D`j{gBh-{Ehku z?UDS-auv5eEEt={vFej8w>W8UqOVyF;{<#u str: + return self._directory_path + + @property + def update_time(self) -> int: + return self._update_time + + @property + def files(self) -> list[str]: + return self._files + + @property + def mediator(self) -> BaseMediator: + return self._mediator + + @mediator.setter + def mediator(self, mediator: BaseMediator) -> None: + self._mediator = mediator + + def _init_state(self): + files = os.listdir(self._directory_path) + self._files = files + + def start(self): + self.update_timer.start(self._update_time) + +class BaseDataConverter: + def __init__(self, mediator: Optional[BaseMediator] = None): + self._mediator = mediator + + @property + def mediator(self) -> BaseMediator: + return self._mediator + + @mediator.setter + def mediator(self, mediator: BaseMediator) -> None: + self._mediator = mediator + + def convert_data(self, files: list[str]) -> None: + ... + + +class BasePlotWidget: + def __init__(self, + mediator: Optional[BaseMediator] = None, + idealDataBuilder: Optional[BaseIdealDataBuilder] = None): + super().__init__() + self._mediator = mediator + self._opt = idealDataBuilder + + self._stages = [ + "Relief", + "Closing", + "Squeeze", + "Welding" + ] + + self._stage_colors = { + "Closing": [208, 28, 31, 100], + "Squeeze": [45, 51, 89, 150], + "Welding": [247, 183, 24, 100], + "Relief": [0, 134, 88, 100] + } + self._stage_ideals = { + "Closing": self._opt.get_closingDF, + "Squeeze": self._opt.get_compressionDF, + "Welding": self._opt.get_weldingDF, + "Relief": self._opt.get_openingDF + } + + self._plt_channels = { + "Electrode Force, N & Welding Current, kA": { + "Settings": { + "zoom": False, + "stages": True + }, + "Real_signals": [ + { + "name": "Electrode Force, N ME", + "pen": 'r', + }, + { + "name": "Electrode Force, N FE", + "pen": 'w', + }, + { + "name": "Welding Current ME", + "pen": "y", + } + ], + "Ideal_signals": [ + { + "name": "Force", + "pen": {'color': 'g', 'width':3}, + } + ] + }, + "Electrode Force, N": { + "Settings": { + "zoom": True, + "stages": False + }, + "Real_signals": [ + { + "name": "Electrode Force, N ME", + "pen": 'r', + }, + { + "name": "Electrode Force, N FE", + "pen": 'w', + } + ], + "Ideal_signals": [ + { + "name": "Force", + "pen": {'color': 'r', 'width':3}, + } + ] + }, + "Electrode Speed, mm/s": { + "Settings": { + "zoom": False, + "stages": True + }, + "Real_signals": [ + { + "name": "Rotor Speed, mm/s ME", + "pen": 'r', + "zoom": False + }, + { + "name": "Rotor Speed, mm/s FE", + "pen": 'w', + "zoom": False + } + ], + "Ideal_signals": [ + { + "name": "Rotor Speed ME", + "pen": {'color': 'y', 'width':3}, + "zoom": False + }, + { + "name": "Rotor Speed FE", + "pen": {'color': 'g', 'width':3}, + "zoom": False + } + ] + }, + } + + @property + def mediator(self) -> BaseMediator: + return self._mediator + + @mediator.setter + def mediator(self, mediator: BaseMediator) -> None: + self._mediator = mediator + + def build(self, data: list[pd.DataFrame]) -> list[QWidget]: + ... + + +class BaseController(QObject): + + def send_widgets(self, widgets: list[QWidget]) -> None: + ... + + +# FIXME: WeldingDF показывает только 1 секунду +class BaseIdealDataBuilder(OptAlgorithm): + + def _get_data(self, end_timestamp:float, func:function) -> pd.DataFrame: + data = [] + for i in range (0, int(end_timestamp*self.mul)): + time = i/self.mul + X1, X2, V1, V2, F = func(time) + data.append({"time":time, "Posicion FE":X1*1000,"Posicion ME":X2*1000, "Rotor Speed FE":V1*1000, "Rotor Speed ME":V2*1000, "Force":F}) + return pd.DataFrame(data) + + def get_closingDF(self) -> pd.DataFrame: + return self._get_data(self.Ts['tclose'], self.calcPhaseClose) + + def get_compressionDF(self) -> pd.DataFrame: + return self._get_data(self.Ts['tgrow'], self.calcPhaseGrow) + + def get_openingDF(self) -> pd.DataFrame: + return self._get_data(self.getMarkOpen(), self.calcPhaseOpen) + + def get_tmovementDF(self) -> pd.DataFrame: + return self._get_data(self.Ts['tmovement'], self.calcPhaseMovement) + + def get_weldingDF(self) -> pd.DataFrame: + data = [] + X1, X2, V1, V2, F = self.calcPhaseGrow(self.Ts['tgrow']) + data.append({"time":0, "Posicion FE":X1,"Posicion ME":X2, "Rotor Speed FE":V1, "Rotor Speed ME":V2, "Force":F}) + data.append({"time":1, "Posicion FE":X1,"Posicion ME":X2, "Rotor Speed FE":V1, "Rotor Speed ME":V2, "Force":F}) + return pd.DataFrame(data) + + def get_ideal_timings(self) -> list[float, float, float, float]: + data = self.Ts + ideal_timings = [data['tclose'], data['tgrow'], self.getMarkOpen(), data["tmovement"]] + return ideal_timings + diff --git a/src/utils/base/base_widgets.py b/src/utils/base/base_widgets.py new file mode 100644 index 0000000..5faf97d --- /dev/null +++ b/src/utils/base/base_widgets.py @@ -0,0 +1,47 @@ +from __future__ import annotations + +import os +from typing import Optional, Union + +import pandas as pd +from PyQt5.QtWidgets import QTabWidget, QWidget, QVBoxLayout + +class BaseMainWindow(QWidget): + + def set_style(self, object: Union[QTabWidget, QWidget]) -> None: + object.setStyleSheet(""" + QWidget { + background-color: #0D1117; + font-family: "Segoe UI", sans-serif; + font-size: 14px; + } + QMessageBox { + background-color: #161B22; + font-family: "Segoe UI", sans-serif; + font-size: 14px; + } + QPushButton { + background-color: #FFCC00; + color: #0D1117; + padding: 12px 25px; + border: 2px solid #E6B800; + border-radius: 8px; + font-family: "Segoe UI", sans-serif; + font-size: 16px; + font-weight: bold; + } + QPushButton:hover:!disabled { + background-color: #FFD700; + } + QPushButton:disabled { + background-color: #555555; + color: #cccccc; + border: none; + } + QLabel { + color: #ffffff; + font-size: 16px; + font-weight: bold; + font-family: "Segoe UI", sans-serif; + } + """) \ No newline at end of file