dev: добавлены настройки, добавлено автоматическое обновление графиков
This commit is contained in:
parent
a04517a15d
commit
72b002dea3
@ -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
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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
|
||||
@ -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()
|
||||
|
||||
|
||||
|
||||
@ -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)}")
|
||||
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
13
src/main.py
13
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)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -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;
|
||||
}
|
||||
""")
|
||||
@ -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;
|
||||
}
|
||||
""")
|
||||
Loading…
Reference in New Issue
Block a user