diff --git a/params/system_params.json b/params/system_params.json index 58e2c7e..d0de10c 100644 --- a/params/system_params.json +++ b/params/system_params.json @@ -17,9 +17,5 @@ "position_start_2": 0.08, "k_prop": 0.05, "time_capture": 100000, - "UML_time_scaler": 1000, - "Closure_signal": "Closing", - "Squeeze_signal": "Squeeze", - "Welding_signal": "Welding", - "Release_signal": "Relief" + "UML_time_scaler": 1000 } diff --git a/src/__pycache__/main.cpython-310.pyc b/src/__pycache__/main.cpython-310.pyc index 5c5e522..e3bc480 100644 Binary files a/src/__pycache__/main.cpython-310.pyc and b/src/__pycache__/main.cpython-310.pyc differ diff --git a/src/controller/__pycache__/controller.cpython-310.pyc b/src/controller/__pycache__/controller.cpython-310.pyc index f731778..27d6a3a 100644 Binary files a/src/controller/__pycache__/controller.cpython-310.pyc and b/src/controller/__pycache__/controller.cpython-310.pyc differ diff --git a/src/controller/__pycache__/mediator.cpython-310.pyc b/src/controller/__pycache__/mediator.cpython-310.pyc index 639c4a9..759eebd 100644 Binary files a/src/controller/__pycache__/mediator.cpython-310.pyc and b/src/controller/__pycache__/mediator.cpython-310.pyc differ diff --git a/src/controller/__pycache__/monitor.cpython-310.pyc b/src/controller/__pycache__/monitor.cpython-310.pyc index c3e89e8..61a2a16 100644 Binary files a/src/controller/__pycache__/monitor.cpython-310.pyc and b/src/controller/__pycache__/monitor.cpython-310.pyc differ diff --git a/src/controller/ideal_data_builder.py b/src/controller/ideal_data_builder.py deleted file mode 100644 index 9a25ec0..0000000 --- a/src/controller/ideal_data_builder.py +++ /dev/null @@ -1,8 +0,0 @@ -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 index c564840..95a79bb 100644 --- a/src/controller/mediator.py +++ b/src/controller/mediator.py @@ -19,3 +19,10 @@ class Mediator(BaseMediator): if issubclass(source.__class__, BasePlotWidget): self._controller.send_widgets(data) + + def push_settings(self, data: list[dict]): + self._monitor.update_settings(data) + self._plot.update_settings(data) + self._monitor.force_all_dir() + + diff --git a/src/controller/monitor.py b/src/controller/monitor.py index a5229af..4e24920 100644 --- a/src/controller/monitor.py +++ b/src/controller/monitor.py @@ -26,3 +26,26 @@ class DirectoryMonitor(BaseDirectoryMonitor): if not files: self._files = [] + def update_settings(self, data: list[dict]) -> None: + self.stop() + operator_params, system_params = data + self._directory_path = system_params['trace_storage_path'] + self._update_time = system_params['monitor_update_period'] + self._init_state() + self.start() + + def force_all_dir(self): + files = os.listdir(self._directory_path) + self._files = files + all_files = [] + for x in self._files: + path = os.path.join(self._directory_path, x) + all_files.append(path) + if all_files: + logger.info(f"Plotting all files: {all_files}") + self._mediator.notify(self, all_files) + else: + logger.info(f"Failed pushing {str(all_files)}") + + + diff --git a/src/gui/__pycache__/mainGui.cpython-310.pyc b/src/gui/__pycache__/mainGui.cpython-310.pyc index 913dfe6..216cde6 100644 Binary files a/src/gui/__pycache__/mainGui.cpython-310.pyc and b/src/gui/__pycache__/mainGui.cpython-310.pyc differ diff --git a/src/gui/__pycache__/plotter.cpython-310.pyc b/src/gui/__pycache__/plotter.cpython-310.pyc index 5df53bd..7fb0c8f 100644 Binary files a/src/gui/__pycache__/plotter.cpython-310.pyc and b/src/gui/__pycache__/plotter.cpython-310.pyc differ diff --git a/src/gui/__pycache__/settings_window.cpython-310.pyc b/src/gui/__pycache__/settings_window.cpython-310.pyc index aca61fa..e425957 100644 Binary files a/src/gui/__pycache__/settings_window.cpython-310.pyc and b/src/gui/__pycache__/settings_window.cpython-310.pyc differ diff --git a/src/gui/mainGui.py b/src/gui/mainGui.py index 35c68f2..ca624df 100644 --- a/src/gui/mainGui.py +++ b/src/gui/mainGui.py @@ -2,18 +2,25 @@ from datetime import datetime as dt from PyQt5 import QtWidgets from PyQt5.QtCore import Qt -from src.utils.base.base_widgets import BaseMainWindow +from src.utils.base.base import BaseMainWindow +from src.gui.settings_window import settingsWindow class MainWindow(BaseMainWindow): def __init__(self): super().__init__() self.initUI() self.set_style(self) + self.settings_button.clicked.connect(self._show_settings) + self.operSettings = settingsWindow("params\operator_params.json", 'Operator', self._updater_trigger) + self.sysSettings = settingsWindow("params\system_params.json", 'System', self._updater_trigger) def initUI(self) -> None: self.tabWidget = QtWidgets.QTabWidget() layout = QtWidgets.QVBoxLayout() layout.addWidget(self.tabWidget) + self.settings_button = QtWidgets.QPushButton("Show settings") + self.settings_button.setFixedWidth(160) + layout.addWidget(self.settings_button) self.setLayout(layout) def show_plot_tabs(self, plot_widgets: list[QtWidgets.QWidget]) -> None: @@ -29,4 +36,20 @@ class MainWindow(BaseMainWindow): if a0.key() == Qt.Key_F5: self.clear() + def _show_settings(self): + self.operSettings.show() + self.sysSettings.show() + + def push_settings(self) -> None: + self._updater_trigger() + + def _updater_trigger(self) -> None: + self.tabWidget.clear() + operator_params = self.operSettings.getParams() + system_params = self.sysSettings.getParams() + self._mediator.push_settings(data=[operator_params, system_params]) + + + + diff --git a/src/gui/plotter.py b/src/gui/plotter.py index 4b44628..716a065 100644 --- a/src/gui/plotter.py +++ b/src/gui/plotter.py @@ -6,15 +6,42 @@ from numpy import floating from typing import Optional, Any, NamedTuple from src.utils.base.base import BasePlotWidget +from src.utils.base.base import BaseIdealDataBuilder +class idealDataBuilder(BaseIdealDataBuilder): + 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, end_time: float) -> 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":end_time, "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 + + class ProcessStage(NamedTuple): mean_value: floating[Any] start_index: int finish_index: int -class PlotWidget(BasePlotWidget): +class PlotWidget(BasePlotWidget): def _create_stage_ideal(self, stage: str, signal: str, @@ -23,7 +50,7 @@ class PlotWidget(BasePlotWidget): 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]() + data = self._stage_ideals[stage] if start_index.size: start_timestamp = times[start_index[0]] @@ -32,7 +59,6 @@ class PlotWidget(BasePlotWidget): return plot return None - def _create_stage_region(self, stage: str, times: pd.Series, @@ -50,7 +76,7 @@ class PlotWidget(BasePlotWidget): return None @staticmethod - def _init_plot_widget(title: str) -> (pg.PlotWidget, pg.LegendItem): + def _init_plot_widget(title: str) -> tuple[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)) @@ -155,4 +181,8 @@ class PlotWidget(BasePlotWidget): widgets = [self._build_widget(data_sample) for data_sample in data] self._mediator.notify(self, widgets) + def update_settings(self, data: list[dict]): + self._initIdealBuilder(idealDataBuilder=idealDataBuilder, data=data) + + diff --git a/src/gui/settings_window.py b/src/gui/settings_window.py index 4c052b4..c67ba93 100644 --- a/src/gui/settings_window.py +++ b/src/gui/settings_window.py @@ -17,10 +17,10 @@ class settingsWindow(QtWidgets.QWidget): self._init_ui() self.params.sigTreeStateChanged.connect(upd_func) - def load_settings(self): + def load_settings(self) -> None: self.data = read_json(self.settingsPath) - def write_settings(self): + def write_settings(self) -> None: self.getParams() write_json(self.settingsPath, self.data) @@ -31,7 +31,7 @@ class settingsWindow(QtWidgets.QWidget): params.append({'name': 'Save', 'type': 'action'}) return params - def _init_ui(self): + def _init_ui(self) -> None: temp = self._getTreeStructure() self.params = Parameter.create(name=self.name, type='group', children=temp) self.params.param('Save').sigActivated.connect(self.write_settings) diff --git a/src/main.py b/src/main.py index 02bc55d..1200be0 100644 --- a/src/main.py +++ b/src/main.py @@ -7,7 +7,6 @@ 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 @@ -15,17 +14,13 @@ from src.utils.json_tools import read_json def main(): 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']) + monitor = DirectoryMonitor() data_converter = DataConverter() - ideal_data_builder = idealDataBuilder(operator_params, system_params) - plot_widget_builder = PlotWidget(idealDataBuilder=ideal_data_builder) + plot_widget_builder = PlotWidget() controller = Controller() - mediator = Mediator(monitor, data_converter, plot_widget_builder, controller) - monitor.start() window = MainWindow() - + mediator = Mediator(monitor, data_converter, plot_widget_builder, controller, window) + window.push_settings() window.show() controller.signal_widgets.connect(window.show_plot_tabs) diff --git a/src/utils/base/__pycache__/base.cpython-310.pyc b/src/utils/base/__pycache__/base.cpython-310.pyc index 2766c43..a9ebe22 100644 Binary files a/src/utils/base/__pycache__/base.cpython-310.pyc and b/src/utils/base/__pycache__/base.cpython-310.pyc differ diff --git a/src/utils/base/__pycache__/base_widgets.cpython-310.pyc b/src/utils/base/__pycache__/base_widgets.cpython-310.pyc index 0d4e21d..5ec790b 100644 Binary files a/src/utils/base/__pycache__/base_widgets.cpython-310.pyc and b/src/utils/base/__pycache__/base_widgets.cpython-310.pyc differ diff --git a/src/utils/base/base.py b/src/utils/base/base.py index 1f22ba3..b0e31d0 100644 --- a/src/utils/base/base.py +++ b/src/utils/base/base.py @@ -5,7 +5,7 @@ from typing import Optional, Union import pandas as pd from PyQt5.QtCore import QThread, QObject, QTimer -from PyQt5.QtWidgets import QWidget +from PyQt5.QtWidgets import QWidget, QTabWidget from src.OptAlgorithm import OptAlgorithm import pandas as pd @@ -15,7 +15,8 @@ class BaseMediator: monitor: BaseDirectoryMonitor, converter: BaseDataConverter, plot: BasePlotWidget, - controller: BaseController): + controller: BaseController, + window: BaseMainWindow): self._monitor = monitor self._monitor.mediator = self self._converter = converter @@ -23,30 +24,28 @@ class BaseMediator: self._plot = plot self._plot.mediator = self self._controller = controller + self._window = window + self._window.mediator = self def notify(self, - source: Union[BaseDirectoryMonitor, BaseDataConverter, BasePlotWidget], - data: Union[list[str], list[pd.DataFrame], list[QWidget]]): + source: Union[BaseDirectoryMonitor, BaseDataConverter, BasePlotWidget, BaseMainWindow], + data: Union[list[str], list[pd.DataFrame], list[QWidget], list[dict]]): + ... + def push_settings (self, data: list[dict]): ... - class BaseDirectoryMonitor: update_timer = QTimer() def __init__(self, - directory_path: str, - update_time: int, mediator: Optional[BaseMediator] = None): super().__init__() + self._directory_path = None + self._update_time = None - self._directory_path = directory_path - self._update_time = update_time self._mediator = mediator - - self._files: list[str] = [] - - self._init_state() + @property def directory_path(self) -> str: @@ -75,6 +74,15 @@ class BaseDirectoryMonitor: def start(self): self.update_timer.start(self._update_time) + def stop(self): + self.update_timer.stop() + + def update_settings(self, data: list[dict]) -> None: + ... + + def force_all_dir(self): + ... + class BaseDataConverter: def __init__(self, mediator: Optional[BaseMediator] = None): self._mediator = mediator @@ -93,11 +101,9 @@ class BaseDataConverter: class BasePlotWidget: def __init__(self, - mediator: Optional[BaseMediator] = None, - idealDataBuilder: Optional[BaseIdealDataBuilder] = None): + mediator: Optional[BaseMediator] = None): super().__init__() self._mediator = mediator - self._opt = idealDataBuilder self._stages = [ "Relief", @@ -112,13 +118,6 @@ class BasePlotWidget: "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": { @@ -199,7 +198,17 @@ class BasePlotWidget: ] }, } + def _initIdealBuilder(self, + idealDataBuilder: Optional[BaseIdealDataBuilder] = None, + data: list[dict] = None): + self.opt = idealDataBuilder(data) + self._stage_ideals = { + "Closing": self._opt.get_closingDF(), + "Squeeze": self._opt.get_compressionDF(), + "Welding": self._opt.get_weldingDF(end_time=data[0]['time_wielding']), + "Relief": self._opt.get_openingDF() + } @property def mediator(self) -> BaseMediator: return self._mediator @@ -207,10 +216,20 @@ class BasePlotWidget: @mediator.setter def mediator(self, mediator: BaseMediator) -> None: self._mediator = mediator + + @property + def opt(self) -> BaseIdealDataBuilder: + return self._opt + + @opt.setter + def opt(self, opt: BaseIdealDataBuilder): + self._opt = opt def build(self, data: list[pd.DataFrame]) -> list[QWidget]: ... + def update_settings(self, data: list[dict]) -> None: + ... class BaseController(QObject): @@ -218,8 +237,13 @@ class BaseController(QObject): ... + # FIXME: WeldingDF показывает только 1 секунду class BaseIdealDataBuilder(OptAlgorithm): + def __init__(self, data: list[dict]): + operator_params, system_params = data + self.mul = system_params['time_capture'] + super().__init__(operator_params, system_params) def _get_data(self, end_timestamp:float, func:function) -> pd.DataFrame: data = [] @@ -230,26 +254,74 @@ class BaseIdealDataBuilder(OptAlgorithm): 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_weldingDF(self, end_time: float) -> pd.DataFrame: + ... 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 + ... + + def update_settings(self, data: list[dict]) -> None: + ... +class BaseMainWindow(QWidget): + def __init__(self, + mediator: Optional[BaseMediator] = None): + super().__init__() + self._mediator = mediator + + @property + def mediator(self) -> BaseMediator: + return self._mediator + + @mediator.setter + def mediator(self, mediator: BaseMediator) -> None: + self._mediator = mediator + + 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 diff --git a/src/utils/base/base_widgets.py b/src/utils/base/base_widgets.py deleted file mode 100644 index 5faf97d..0000000 --- a/src/utils/base/base_widgets.py +++ /dev/null @@ -1,47 +0,0 @@ -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