dev: добавлена возможность задавать параметры оператора для каждой точки

This commit is contained in:
Andrew 2024-12-04 20:01:30 +03:00
parent a0d6cba386
commit 0a9b1c50b8
18 changed files with 526 additions and 207 deletions

View File

@ -1,16 +1,226 @@
{ {
"dist_open_start_1": 0.005, "dist_open_start_1": [
"dist_open_start_2": 0.005, 0.005,
"dist_open_after_1": 0.006, 0.005,
"dist_open_after_2": 0.006, 0.005,
"dist_open_end_1": 0.01, 0.005,
"dist_open_end_2": 0.05, 0.005,
"dist_close_end_1": 0.005, 0.005,
"dist_close_end_2": 0.005, 0.005,
"time_wielding": 1, 0.005,
"time_command": 0.0, 0.005,
"time_robot_movement": 0.2, 0.005,
"object_thickness": 0.0045, 0.005,
"force_target": 5000, 0.005,
"force_capture": 500 0.005,
0.005
],
"dist_open_start_2": [
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005
],
"dist_open_after_1": [
0.006,
0.006,
0.006,
0.006,
0.006,
0.006,
0.006,
0.006,
0.006,
0.006,
0.006,
0.006,
0.006,
0.006
],
"dist_open_after_2": [
0.006,
0.006,
0.006,
0.006,
0.006,
0.006,
0.006,
0.006,
0.006,
0.006,
0.006,
0.006,
0.006,
0.006
],
"dist_open_end_1": [
0.01,
0.01,
0.01,
0.01,
0.01,
0.01,
0.01,
0.01,
0.01,
0.01,
0.01,
0.01,
0.01,
0.01
],
"dist_open_end_2": [
0.05,
0.05,
0.05,
0.05,
0.05,
0.05,
0.05,
0.05,
0.05,
0.05,
0.05,
0.05,
0.05,
0.05
],
"dist_close_end_1": [
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005
],
"dist_close_end_2": [
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005,
0.005
],
"time_wielding": [
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0
],
"time_command": [
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0
],
"time_robot_movement": [
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2,
0.2
],
"object_thickness": [
0.0045,
0.0045,
0.0045,
0.0045,
0.0045,
0.0045,
0.0045,
0.0045,
0.0045,
0.0045,
0.0045,
0.0045,
0.0045,
0.0045
],
"force_target": [
4000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0,
5000.0
],
"force_capture": [
500.0,
500.0,
500.0,
500.0,
500.0,
500.0,
500.0,
500.0,
500.0,
500.0,
500.0,
500.0,
500.0,
500.0
]
} }

View File

@ -1,22 +1,22 @@
{ {
"trace_storage_path": "D:/downloads/a22", "trace_storage_path": ["D:/downloads/a22"],
"monitor_update_period": 100, "monitor_update_period": [100],
"a_max_1": 5.41, "a_max_1": [5.41],
"v_max_1": 0.278, "v_max_1": [0.278],
"a_max_2": 35.81, "a_max_2": [35.81],
"v_max_2": 0.7, "v_max_2": [0.7],
"mass_1": 270, "mass_1": [270],
"mass_2": 1, "mass_2": [1],
"k_hardness_1": 2148570, "k_hardness_1": [2148570],
"k_hardness_2": 0, "k_hardness_2": [0],
"torque_max_1": 20, "torque_max_1": [20],
"torque_max_2": 0, "torque_max_2": [0],
"transmission_ratio_1": 0.00125, "transmission_ratio_1": [0.00125],
"transmission_ratio_2": 1, "transmission_ratio_2": [1],
"position_start_1": 0.08, "position_start_1": [0.08],
"position_start_2": 0.08, "position_start_2": [0.08],
"k_prop": 0.05, "k_prop": [0.05],
"time_capture": 100000, "time_capture": [100000],
"UML_time_scaler": 1000 "UML_time_scaler": [1000]
} }

Binary file not shown.

View File

@ -3,18 +3,21 @@ import pandas as pd
from typing import Union from typing import Union
from PyQt5.QtWidgets import QWidget from PyQt5.QtWidgets import QWidget
from src.utils.base.base import BaseMediator, BaseDirectoryMonitor, BaseDataConverter, BasePlotWidget from src.utils.base.base import BaseMediator, BaseDirectoryMonitor, BaseDataConverter, BasePlotWidget, BasePointPassportFormer
class Mediator(BaseMediator): class Mediator(BaseMediator):
def notify(self, def notify(self,
source: Union[BaseDirectoryMonitor, BaseDataConverter, BasePlotWidget], source: Union[BaseDirectoryMonitor, BaseDataConverter, BasePointPassportFormer, BasePlotWidget],
data: Union[list[str], list[pd.DataFrame], list[QWidget]]): data: Union[list[str], list[pd.DataFrame], list[list], list[QWidget]]):
if issubclass(source.__class__, BaseDirectoryMonitor): if issubclass(source.__class__, BaseDirectoryMonitor):
self._converter.convert_data(data) self._converter.convert_data(data)
if issubclass(source.__class__, BaseDataConverter): if issubclass(source.__class__, BaseDataConverter):
self._passportFormer.form_passports(data)
if issubclass(source.__class__, BasePointPassportFormer):
self._plot.build(data) self._plot.build(data)
if issubclass(source.__class__, BasePlotWidget): if issubclass(source.__class__, BasePlotWidget):
@ -22,7 +25,7 @@ class Mediator(BaseMediator):
def push_settings(self, settings: list[dict]): def push_settings(self, settings: list[dict]):
self._monitor.update_settings(settings) self._monitor.update_settings(settings)
self._plot.update_settings(settings) self._passportFormer.update_settings(settings)
self._monitor.force_all_dir() self._monitor.force_all_dir()

View File

@ -29,8 +29,8 @@ class DirectoryMonitor(BaseDirectoryMonitor):
def update_settings(self, data: list[dict]) -> None: def update_settings(self, data: list[dict]) -> None:
self.stop() self.stop()
operator_params, system_params = data operator_params, system_params = data
self._directory_path = system_params['trace_storage_path'] self._directory_path = system_params['trace_storage_path'][0]
self._update_time = system_params['monitor_update_period'] self._update_time = system_params['monitor_update_period'][0]
self._init_state() self._init_state()
self.start() self.start()

View File

@ -0,0 +1,63 @@
from src.utils.base.base import BasePointPassportFormer, BaseIdealDataBuilder
import pandas as pd
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_oncomingDF(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":self.welding_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]:
data = self.Ts
ideal_timings = [data['tclose'], data['tgrow'], self.welding_time, self.getMarkOpen()] # TODO: add data['tmovement'], Oncoming не учитывается в производительности
return ideal_timings
class PassportFormer(BasePointPassportFormer):
def form_passports(self, data: list[pd.DataFrame]) -> list[list[pd.DataFrame, dict, list]]:
return_data = [self._build_passports_pocket(dataframe) for dataframe in data]
self._mediator.notify(self, return_data)
def _build_passports_pocket(self, dataframe: pd.DataFrame) -> list[pd.DataFrame, dict, list]:
passports_pocket = []
events, point_quantity = self._filter_events(dataframe["time"], dataframe)
system_settings = {key: value[0] for key, value in self._params[1].items()}
for i in range(0, point_quantity):
if not dataframe["time"].isna().all():
operator_settings = {}
for key, value in self._params[0].items():
if len(value) > i:
operator_settings[key] = value[i]
else:
operator_settings[key] = value[0]
params_list = [operator_settings, system_settings]
ideal_data = self._build_ideal_data(idealDataBuilder=idealDataBuilder, params=params_list)
if i < point_quantity-1:
cut_time = events[self._stages[0]][0][i+1]
frame = dataframe[dataframe["time"] < cut_time]
dataframe = dataframe[dataframe["time"] >= cut_time]
else:
frame = dataframe
point_events = {key: [value[0][i], value[1][i]] for key, value in events.items()}
passports_pocket.append([frame, ideal_data, point_events])
return passports_pocket
def update_settings(self, params: list[dict, dict]):
self._params = params

View File

@ -45,7 +45,7 @@ class MainWindow(BaseMainWindow):
def keyPressEvent(self, a0): def keyPressEvent(self, a0):
if a0.key() == Qt.Key_F5: if a0.key() == Qt.Key_F5:
self.clear() pass
def _show_settings(self): def _show_settings(self):
self.operSettings.show() self.operSettings.show()

View File

@ -5,34 +5,7 @@ import numpy as np
from numpy import floating from numpy import floating
from typing import Optional, Any, NamedTuple from typing import Optional, Any, NamedTuple
from src.utils.base.base import BasePlotWidget, BasePointPassportFormer, BaseIdealDataBuilder from src.utils.base.base import BasePlotWidget
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_oncomingDF(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":self.welding_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.welding_time, self.getMarkOpen()] # TODO: add data['tmovement'], Oncoming не учитывается в производительности
return ideal_timings
class ProcessStage(NamedTuple): class ProcessStage(NamedTuple):
mean_value: floating[Any] mean_value: floating[Any]
@ -40,16 +13,15 @@ class ProcessStage(NamedTuple):
finish_index: int finish_index: int
class PlotWidget(BasePlotWidget, BasePointPassportFormer): class PlotWidget(BasePlotWidget):
def _create_curve_ideal(self, def _create_curve_ideal(self,
stage: str,
signal: str, signal: str,
ideal_data: pd.DataFrame,
start_timestamp: float, start_timestamp: float,
finish_timestamp: float) -> Optional[pg.PlotDataItem]: finish_timestamp: float) -> Optional[pg.PlotDataItem]:
data = self._stage_ideals[stage]
if start_timestamp and finish_timestamp: if start_timestamp and finish_timestamp:
plot = pg.PlotDataItem(x=start_timestamp+data["time"], y=data[signal["name"]], pen=signal["pen"]) plot = pg.PlotDataItem(x=start_timestamp+ideal_data["time"], y=ideal_data[signal["name"]], pen=signal["pen"])
return plot return plot
return None return None
@ -76,104 +48,109 @@ class PlotWidget(BasePlotWidget, BasePointPassportFormer):
stage: str, stage: str,
dataframe: pd.DataFrame, dataframe: pd.DataFrame,
signal_name: str) -> Optional[ProcessStage]: 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 [] stage_diff = np.diff(dataframe[stage])
start_index = np.where(stage_diff == 1)[0]
finish_index = np.where(stage_diff == -1)[0]
if data.size and start_index.size: data = dataframe[signal_name] if signal_name in dataframe.columns.tolist() else []
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: 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, data: list[pd.DataFrame, dict, list]) -> QWidget:
widget = QWidget() widget = QWidget()
layout = QVBoxLayout() layout = QVBoxLayout()
time_axis = dataframe["time"]
dataframe_headers = dataframe.columns.tolist()
for channel, description in self._plt_channels.items(): for channel, description in self._plt_channels.items():
performance_list = []
df_continuous = pd.DataFrame({})
plot_widget, legend = self._init_plot_widget(title=channel) plot_widget, legend = self._init_plot_widget(title=channel)
settings = description["Settings"] settings = description["Settings"]
if (settings["stages"] or settings["performance"]) and all([stage in dataframe_headers for stage in self._stages]):
events = self._filter_events(time_axis, dataframe) for dataframe, ideal_data, events in data:
point_quantity = len(events[self._clear_stage][0]) df_continuous = pd.concat([df_continuous, dataframe], axis=0)
if settings["stages"]: dataframe_headers = dataframe.columns.tolist()
for stage in self._stages: stages = events.keys()
if settings["stages"] and all([stage in dataframe_headers for stage in stages]):
for stage in stages:
start_t, end_t = events[stage] start_t, end_t = events[stage]
for i in range(len(start_t)): region = self._create_stage_region(stage, start_t, end_t)
region = self._create_stage_region(stage, start_t[i], end_t[i]) if region:
if region: plot_widget.addItem(region)
plot_widget.addItem(region)
for signal in description["Ideal_signals"]: if settings["ideals"]:
ideal_plot = self._create_curve_ideal(stage, signal, start_t[i], end_t[i]) for stage in stages:
if ideal_plot: for signal in description["Ideal_signals"]:
plot_widget.addItem(ideal_plot) curve = self._create_curve_ideal(signal, ideal_data[stage], events[stage][0], events[stage][1])
if curve:
plot_widget.addItem(curve)
if settings["performance"]: if settings["performance"]:
ideal_delta = self._opt.get_cycle_time() ideal_delta = ideal_data["Ideal cycle"]
delta = np.zeros(point_quantity) delta = 0
for stage in self._stages: for stage in stages:
try: delta += events[stage][1] - events[stage][0]
start_stage, stop_stage = events[stage] performance = ideal_delta/delta*100
delta += np.array(stop_stage)-np.array(start_stage) performance_list.append(performance)
except: print("Signal ", stage, " is abnormal..." )
performance_list = ideal_delta/delta*100
performance_label = QLabel(f"Performance: best = {performance_list.max()} %, worse = {performance_list.min()} %, average = {performance_list.mean()}")
layout.addWidget(performance_label)
if settings["zoom"]: if settings["zoom"]:
if max(time_axis) < 5.0: pass
stages = [self.get_stage_info("Welding", """if max(time_axis) < 5.0:
dataframe, stages = [self.get_stage_info("Welding",
signal["name"]) for signal in description["Real_signals"]] dataframe,
if stages: signal["name"]) for signal in description["Real_signals"]]
means_raw = [stage.mean_value for stage in stages] if stages:
mean = max(means_raw) means_raw = [stage.mean_value for stage in stages]
start = time_axis[stages[0].start_index] mean = max(means_raw)
finish = time_axis[stages[0].finish_index] start = time_axis[stages[0].start_index]
finish = time_axis[stages[0].finish_index]
overshoot = pg.BarGraphItem(x0=0, overshoot = pg.BarGraphItem(x0=0,
y0=mean - mean * 0.05, y0=mean - mean * 0.05,
height=mean * 0.05 * 2, height=mean * 0.05 * 2,
width=start, 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])) brush=pg.mkBrush([0, 250, 0, 100]))
plot_widget.addItem(overshoot) plot_widget.addItem(stable)
stable = pg.BarGraphItem(x0=start, plot_widget.setYRange(mean - 260, mean + 260)
y0=mean - mean * 0.015, plot_widget.setInteractive(False)
height=mean * 0.015 * 2, else:
width=finish - start, max_value = min([max(dataframe[signal["name"]]) for signal in description["Real_signals"]])
brush=pg.mkBrush([0, 250, 0, 100])) region = pg.LinearRegionItem([max_value - max_value * 0.015,
plot_widget.addItem(stable) max_value + max_value * 0.015],
movable=False,
orientation="horizontal")
plot_widget.setYRange(mean - 260, mean + 260) region.setBrush(pg.mkBrush([0, 250, 0, 100]))
plot_widget.setInteractive(False) plot_widget.setYRange(max_value - 200, max_value + 200)
else: plot_widget.setXRange(3.5, 4.5)
max_value = min([max(dataframe[signal["name"]]) for signal in description["Real_signals"]]) plot_widget.addItem(region)
region = pg.LinearRegionItem([max_value - max_value * 0.015, plot_widget.setInteractive(False)"""
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"]: for signal in description["Real_signals"]:
if signal["name"] in dataframe_headers: if signal["name"] in dataframe_headers:
plot = plot_widget.plot(time_axis, dataframe[signal["name"]], pen=signal["pen"]) plot = plot_widget.plot(df_continuous["time"], df_continuous[signal["name"]], pen=signal["pen"])
legend.addItem(plot, signal["name"]) legend.addItem(plot, signal["name"])
if settings["performance"]:
performance_list = np.array(performance_list)
performance_label = QLabel(f"""Performance: best = {round(performance_list.max(),2)} %, worse = {round(performance_list.min(),2)} %, average = {round(performance_list.mean(),2)}%""")
layout.addWidget(performance_label)
layout.addWidget(plot_widget) layout.addWidget(plot_widget)
widget.setLayout(layout) widget.setLayout(layout)
@ -183,8 +160,5 @@ class PlotWidget(BasePlotWidget, BasePointPassportFormer):
widgets = [self._build_widget(data_sample) for data_sample in data] widgets = [self._build_widget(data_sample) for data_sample in data]
self._mediator.notify(self, widgets) self._mediator.notify(self, widgets)
def update_settings(self, params: list[dict]):
self._initIdealBuilder(idealDataBuilder=idealDataBuilder, params=params)

View File

@ -1,55 +1,103 @@
import pyqtgraph as pg import pyqtgraph as pg
from pyqtgraph.Qt import QtWidgets from PyQt5.QtWidgets import QWidget, QTableWidget, QVBoxLayout, QTableWidgetItem, QLabel, QPushButton, QLineEdit, QHBoxLayout
from pyqtgraph.parametertree import Parameter, ParameterTree from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIntValidator
from src.utils.json_tools import read_json, write_json from src.utils.json_tools import read_json, write_json
from src.gui import qt_settings as qts from src.gui import qt_settings as qts
class settingsWindow(QtWidgets.QWidget): class settingsWindow(QWidget):
def __init__(self, path: str, name: str, upd_func): def __init__(self, path: str, name: str, upd_func):
super(settingsWindow, self).__init__() super(settingsWindow, self).__init__()
self.settingsPath = path self._settingsPath = path
self.name = name self._name = name
self._data = {}
self._upd_func = upd_func
self.data = {}
self.params = None
self.load_settings() self.load_settings()
self._init_ui() self._init_ui()
self.params.sigTreeStateChanged.connect(upd_func)
def load_settings(self) -> None: def load_settings(self) -> None:
self.data = read_json(self.settingsPath) self._data = read_json(self._settingsPath)
def write_settings(self) -> None: def write_settings(self) -> None:
self.getParams() write_json(self._settingsPath, self._data)
write_json(self.settingsPath, self.data)
def _getTreeStructure(self) -> list:
params = []
for key, value in self.data.items():
params.append({'name': str(key), 'type': type(value).__name__, 'value': value})
params.append({'name': 'Save', 'type': 'action'})
return params
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)
ParamsTree = ParameterTree()
ParamsTree.setParameters(self.params, showTop=True)
layout = QtWidgets.QGridLayout()
layout.addWidget(ParamsTree, 0,0)
self.setLayout(layout)
self.setStyleSheet(qts.white_style)
# self.show()
def getParams(self) -> dict: def getParams(self) -> dict:
self.data = {} return self._data
for p in self.params:
if p.name() != 'Save':
self.data[p.name()] = p.value() def _init_ui(self) -> None:
return self.data save_button = QPushButton()
restore_button = QPushButton()
save_button.setText("Save")
restore_button.setText("Restore")
self._num_points = QLineEdit()
self._num_points.setPlaceholderText("Enter the number of welding points")
self._num_points.setValidator(QIntValidator())
control_layout = QHBoxLayout()
control_layout.addWidget(save_button)
control_layout.addWidget(restore_button)
control_layout.addWidget(self._num_points)
save_button.pressed.connect(self._save)
restore_button.pressed.connect(self._restore)
self._num_points.editingFinished.connect(self._expand)
self._param_table = QTableWidget()
self._param_table.setColumnCount(2)
self._param_table.setRowCount(len(self._data))
for i, (key, items) in enumerate(self._data.items()):
self._param_table.setItem(i, 0, QTableWidgetItem(key))
self._param_table.setItem(i, 1, QTableWidgetItem(str(items[0])))
layout = QVBoxLayout()
header = QLabel(self._name)
layout.addWidget(header)
layout.addLayout(control_layout)
layout.addWidget(self._param_table)
self.setLayout(layout)
self.setStyleSheet(qts.white_style)
#self.show()
def _save(self) -> dict:
self._data = {}
for i in range(self._param_table.rowCount()):
key = self._param_table.item(i, 0).text()
data = []
for j in range(1, self._param_table.columnCount()):
param = self._param_table.item(i, j).text()
if key != "trace_storage_path":
param = float(param)
data.append(param)
self._data[key] = data
self.write_settings()
self._upd_func()
def _restore(self) -> None:
self._param_table.setRowCount(len(self._data))
self._param_table.setColumnCount(len(self._data[self._data.keys()[0]]))
for i, (key, items) in enumerate(self._data.items()):
self._param_table.setItem(i, 0, QTableWidgetItem(key))
for j, item in enumerate(items):
self._param_table.setItem(i, j+1, QTableWidgetItem(str(item)))
def _expand(self) -> None:
param=int(self._num_points.text())
prev_columns = self._param_table.columnCount()
self._param_table.setColumnCount(param+1)
if prev_columns < param+1:
for i in range(prev_columns, param+1):
for j, (key, items) in enumerate(self._data.items()):
self._param_table.setItem(j, i, QTableWidgetItem(str(items[-1])))
if __name__ == '__main__': if __name__ == '__main__':
app = pg.mkQApp("Parameter Tree Example") app = pg.mkQApp("Parameter Tree Example")

View File

@ -7,6 +7,7 @@ from src.controller.mediator import Mediator
from src.controller.converter import DataConverter from src.controller.converter import DataConverter
from src.gui.plotter import PlotWidget from src.gui.plotter import PlotWidget
from src.controller.controller import Controller from src.controller.controller import Controller
from src.controller.passportFormer import PassportFormer
def main(): def main():
@ -15,8 +16,9 @@ def main():
data_converter = DataConverter() data_converter = DataConverter()
plot_widget_builder = PlotWidget() plot_widget_builder = PlotWidget()
controller = Controller() controller = Controller()
passport_former = PassportFormer()
window = MainWindow(controller) window = MainWindow(controller)
mediator = Mediator(monitor, data_converter, plot_widget_builder, controller) mediator = Mediator(monitor, data_converter, passport_former, plot_widget_builder, controller)
window.show() window.show()
controller.signal_widgets.connect(window.show_plot_tabs) controller.signal_widgets.connect(window.show_plot_tabs)

View File

@ -18,20 +18,23 @@ class BaseMediator:
def __init__(self, def __init__(self,
monitor: BaseDirectoryMonitor, monitor: BaseDirectoryMonitor,
converter: BaseDataConverter, converter: BaseDataConverter,
passportFormer: BasePointPassportFormer,
plot: BasePlotWidget, plot: BasePlotWidget,
controller: BaseController): controller: BaseController):
self._monitor = monitor self._monitor = monitor
self._monitor.mediator = self self._monitor.mediator = self
self._converter = converter self._converter = converter
self._converter.mediator = self self._converter.mediator = self
self._passportFormer = passportFormer
self._passportFormer.mediator = self
self._plot = plot self._plot = plot
self._plot.mediator = self self._plot.mediator = self
self._controller = controller self._controller = controller
self._controller.mediator = self self._controller.mediator = self
def notify(self, def notify(self,
source: Union[BaseDirectoryMonitor, BaseDataConverter, BasePlotWidget, BaseMainWindow], source: Union[BaseDirectoryMonitor, BaseDataConverter, BasePointPassportFormer, BasePlotWidget],
data: Union[list[str], list[pd.DataFrame], list[QWidget], list[dict]]): data: Union[list[str], list[pd.DataFrame], list[list], list[QWidget]]):
... ...
def push_settings (self, data: list[dict]): def push_settings (self, data: list[dict]):
... ...
@ -120,7 +123,8 @@ class BasePlotWidget:
"Settings": { "Settings": {
"zoom": False, "zoom": False,
"stages": True, "stages": True,
"performance": True "performance": True,
"ideals": True
}, },
"Real_signals": [ "Real_signals": [
{ {
@ -147,7 +151,8 @@ class BasePlotWidget:
"Settings": { "Settings": {
"zoom": True, "zoom": True,
"stages": False, "stages": False,
"performance": False "performance": False,
"ideals": True
}, },
"Real_signals": [ "Real_signals": [
{ {
@ -170,7 +175,8 @@ class BasePlotWidget:
"Settings": { "Settings": {
"zoom": False, "zoom": False,
"stages": True, "stages": True,
"performance": False "performance": False,
"ideals": True
}, },
"Real_signals": [ "Real_signals": [
{ {
@ -218,8 +224,6 @@ class BasePlotWidget:
def build(self, data: list[pd.DataFrame]) -> list[QWidget]: def build(self, data: list[pd.DataFrame]) -> list[QWidget]:
... ...
def update_settings(self, data: list[dict]) -> None:
...
class BaseController(QObject): class BaseController(QObject):
@ -231,6 +235,7 @@ class BaseController(QObject):
class BaseIdealDataBuilder(OptAlgorithm): class BaseIdealDataBuilder(OptAlgorithm):
def __init__(self, params: list[dict]): def __init__(self, params: list[dict]):
operator_params, system_params = params operator_params, system_params = params
self.mul = system_params['time_capture'] self.mul = system_params['time_capture']
@ -325,13 +330,15 @@ class BaseMainWindow(QWidget):
class BasePointPassportFormer: class BasePointPassportFormer:
def __init__(self): def __init__(self,
mediator: Optional[BaseMediator] = None):
self._mediator = mediator
self._clear_stage = "Welding" self._clear_stage = "Welding"
self._stages = [ self._stages = [
"Closing", "Closing",
"Squeeze", "Squeeze",
"Welding", "Welding",
"Relief", "Relief"
] ]
def _find_indexes(self, def _find_indexes(self,
@ -355,7 +362,7 @@ class BasePointPassportFormer:
def _filter_events(self, def _filter_events(self,
times: pd.Series, times: pd.Series,
dataframe: pd.DataFrame) -> dict[list[float]]: dataframe: pd.DataFrame) -> list[dict[list[float]], int]:
events = {} events = {}
if self._clear_stage in self._stages: if self._clear_stage in self._stages:
start_list, end_list = self._find_events(self._clear_stage, times, dataframe) start_list, end_list = self._find_events(self._clear_stage, times, dataframe)
@ -363,26 +370,30 @@ class BasePointPassportFormer:
for stage in self._stages: for stage in self._stages:
start_list, end_list = self._find_events(stage, times, dataframe) start_list, end_list = self._find_events(stage, times, dataframe)
events[stage] = [start_list[:point_quantity], end_list[:point_quantity]] events[stage] = [start_list[:point_quantity], end_list[:point_quantity]]
return events return events, point_quantity
def _initIdealBuilder(self, def _build_ideal_data(self,
idealDataBuilder: Optional[BaseIdealDataBuilder] = None, idealDataBuilder: Optional[BaseIdealDataBuilder] = None,
params: list[dict] = None): params: list[dict] = None) -> dict:
self.opt = idealDataBuilder(params) self.opt = idealDataBuilder(params)
self._stage_ideals = { stage_ideals = {
"Closing": self._opt.get_closingDF(), "Closing": self._opt.get_closingDF(),
"Squeeze": self._opt.get_compressionDF(), "Squeeze": self._opt.get_compressionDF(),
"Welding": self._opt.get_weldingDF(), "Welding": self._opt.get_weldingDF(),
"Relief": self._opt.get_openingDF(), "Relief": self._opt.get_openingDF(),
"Oncomming": self._opt.get_oncomingDF() "Oncomming": self._opt.get_oncomingDF(),
"Ideal cycle": self._opt.get_cycle_time()
} }
return stage_ideals
def _create_curve_ideal(self, def form_passports(self) -> list[list[pd.DataFrame, dict, list]]:
stage: str):
data = self._stage_ideals[stage]
... ...
def update_settings(self, params: list) -> None:
...
@property @property
def opt(self) -> BaseIdealDataBuilder: def opt(self) -> BaseIdealDataBuilder:
return self._opt return self._opt
@ -390,3 +401,11 @@ class BasePointPassportFormer:
@opt.setter @opt.setter
def opt(self, opt: BaseIdealDataBuilder): def opt(self, opt: BaseIdealDataBuilder):
self._opt = opt self._opt = opt
@property
def mediator(self) -> BaseMediator:
return self._mediator
@mediator.setter
def mediator(self, mediator: BaseMediator) -> None:
self._mediator = mediator