dev: добавлена возможность задавать параметры оператора для каждой точки
This commit is contained in:
parent
a0d6cba386
commit
0a9b1c50b8
@ -1,16 +1,226 @@
|
||||
{
|
||||
"dist_open_start_1": 0.005,
|
||||
"dist_open_start_2": 0.005,
|
||||
"dist_open_after_1": 0.006,
|
||||
"dist_open_after_2": 0.006,
|
||||
"dist_open_end_1": 0.01,
|
||||
"dist_open_end_2": 0.05,
|
||||
"dist_close_end_1": 0.005,
|
||||
"dist_close_end_2": 0.005,
|
||||
"time_wielding": 1,
|
||||
"time_command": 0.0,
|
||||
"time_robot_movement": 0.2,
|
||||
"object_thickness": 0.0045,
|
||||
"force_target": 5000,
|
||||
"force_capture": 500
|
||||
"dist_open_start_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_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
|
||||
]
|
||||
}
|
||||
@ -1,22 +1,22 @@
|
||||
{
|
||||
"trace_storage_path": "D:/downloads/a22",
|
||||
"monitor_update_period": 100,
|
||||
"a_max_1": 5.41,
|
||||
"v_max_1": 0.278,
|
||||
"a_max_2": 35.81,
|
||||
"v_max_2": 0.7,
|
||||
"mass_1": 270,
|
||||
"mass_2": 1,
|
||||
"k_hardness_1": 2148570,
|
||||
"k_hardness_2": 0,
|
||||
"torque_max_1": 20,
|
||||
"torque_max_2": 0,
|
||||
"transmission_ratio_1": 0.00125,
|
||||
"transmission_ratio_2": 1,
|
||||
"position_start_1": 0.08,
|
||||
"position_start_2": 0.08,
|
||||
"k_prop": 0.05,
|
||||
"time_capture": 100000,
|
||||
"UML_time_scaler": 1000
|
||||
"trace_storage_path": ["D:/downloads/a22"],
|
||||
"monitor_update_period": [100],
|
||||
"a_max_1": [5.41],
|
||||
"v_max_1": [0.278],
|
||||
"a_max_2": [35.81],
|
||||
"v_max_2": [0.7],
|
||||
"mass_1": [270],
|
||||
"mass_2": [1],
|
||||
"k_hardness_1": [2148570],
|
||||
"k_hardness_2": [0],
|
||||
"torque_max_1": [20],
|
||||
"torque_max_2": [0],
|
||||
"transmission_ratio_1": [0.00125],
|
||||
"transmission_ratio_2": [1],
|
||||
"position_start_1": [0.08],
|
||||
"position_start_2": [0.08],
|
||||
"k_prop": [0.05],
|
||||
"time_capture": [100000],
|
||||
"UML_time_scaler": [1000]
|
||||
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
src/controller/__pycache__/passportFormer.cpython-310.pyc
Normal file
BIN
src/controller/__pycache__/passportFormer.cpython-310.pyc
Normal file
Binary file not shown.
@ -3,18 +3,21 @@ import pandas as pd
|
||||
from typing import Union
|
||||
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):
|
||||
|
||||
def notify(self,
|
||||
source: Union[BaseDirectoryMonitor, BaseDataConverter, BasePlotWidget],
|
||||
data: Union[list[str], list[pd.DataFrame], list[QWidget]]):
|
||||
source: Union[BaseDirectoryMonitor, BaseDataConverter, BasePointPassportFormer, BasePlotWidget],
|
||||
data: Union[list[str], list[pd.DataFrame], list[list], list[QWidget]]):
|
||||
if issubclass(source.__class__, BaseDirectoryMonitor):
|
||||
self._converter.convert_data(data)
|
||||
|
||||
if issubclass(source.__class__, BaseDataConverter):
|
||||
self._passportFormer.form_passports(data)
|
||||
|
||||
if issubclass(source.__class__, BasePointPassportFormer):
|
||||
self._plot.build(data)
|
||||
|
||||
if issubclass(source.__class__, BasePlotWidget):
|
||||
@ -22,7 +25,7 @@ class Mediator(BaseMediator):
|
||||
|
||||
def push_settings(self, settings: list[dict]):
|
||||
self._monitor.update_settings(settings)
|
||||
self._plot.update_settings(settings)
|
||||
self._passportFormer.update_settings(settings)
|
||||
self._monitor.force_all_dir()
|
||||
|
||||
|
||||
|
||||
@ -29,8 +29,8 @@ class DirectoryMonitor(BaseDirectoryMonitor):
|
||||
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._directory_path = system_params['trace_storage_path'][0]
|
||||
self._update_time = system_params['monitor_update_period'][0]
|
||||
self._init_state()
|
||||
self.start()
|
||||
|
||||
|
||||
63
src/controller/passportFormer.py
Normal file
63
src/controller/passportFormer.py
Normal 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
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -45,7 +45,7 @@ class MainWindow(BaseMainWindow):
|
||||
|
||||
def keyPressEvent(self, a0):
|
||||
if a0.key() == Qt.Key_F5:
|
||||
self.clear()
|
||||
pass
|
||||
|
||||
def _show_settings(self):
|
||||
self.operSettings.show()
|
||||
|
||||
@ -5,34 +5,7 @@ import numpy as np
|
||||
from numpy import floating
|
||||
from typing import Optional, Any, NamedTuple
|
||||
|
||||
from src.utils.base.base import BasePlotWidget, BasePointPassportFormer, 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_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
|
||||
|
||||
from src.utils.base.base import BasePlotWidget
|
||||
|
||||
class ProcessStage(NamedTuple):
|
||||
mean_value: floating[Any]
|
||||
@ -40,16 +13,15 @@ class ProcessStage(NamedTuple):
|
||||
finish_index: int
|
||||
|
||||
|
||||
class PlotWidget(BasePlotWidget, BasePointPassportFormer):
|
||||
class PlotWidget(BasePlotWidget):
|
||||
def _create_curve_ideal(self,
|
||||
stage: str,
|
||||
signal: str,
|
||||
ideal_data: pd.DataFrame,
|
||||
start_timestamp: float,
|
||||
finish_timestamp: float) -> Optional[pg.PlotDataItem]:
|
||||
data = self._stage_ideals[stage]
|
||||
|
||||
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 None
|
||||
|
||||
@ -76,104 +48,109 @@ class PlotWidget(BasePlotWidget, BasePointPassportFormer):
|
||||
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 []
|
||||
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:
|
||||
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
|
||||
data = dataframe[signal_name] if signal_name in dataframe.columns.tolist() else []
|
||||
|
||||
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()
|
||||
layout = QVBoxLayout()
|
||||
|
||||
time_axis = dataframe["time"]
|
||||
dataframe_headers = dataframe.columns.tolist()
|
||||
|
||||
for channel, description in self._plt_channels.items():
|
||||
performance_list = []
|
||||
df_continuous = pd.DataFrame({})
|
||||
plot_widget, legend = self._init_plot_widget(title=channel)
|
||||
|
||||
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)
|
||||
point_quantity = len(events[self._clear_stage][0])
|
||||
if settings["stages"]:
|
||||
for stage in self._stages:
|
||||
|
||||
for dataframe, ideal_data, events in data:
|
||||
df_continuous = pd.concat([df_continuous, dataframe], axis=0)
|
||||
dataframe_headers = dataframe.columns.tolist()
|
||||
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]
|
||||
for i in range(len(start_t)):
|
||||
region = self._create_stage_region(stage, start_t[i], end_t[i])
|
||||
if region:
|
||||
plot_widget.addItem(region)
|
||||
for signal in description["Ideal_signals"]:
|
||||
ideal_plot = self._create_curve_ideal(stage, signal, start_t[i], end_t[i])
|
||||
if ideal_plot:
|
||||
plot_widget.addItem(ideal_plot)
|
||||
region = self._create_stage_region(stage, start_t, end_t)
|
||||
if region:
|
||||
plot_widget.addItem(region)
|
||||
|
||||
if settings["ideals"]:
|
||||
for stage in stages:
|
||||
for signal in description["Ideal_signals"]:
|
||||
curve = self._create_curve_ideal(signal, ideal_data[stage], events[stage][0], events[stage][1])
|
||||
if curve:
|
||||
plot_widget.addItem(curve)
|
||||
|
||||
if settings["performance"]:
|
||||
ideal_delta = self._opt.get_cycle_time()
|
||||
delta = np.zeros(point_quantity)
|
||||
for stage in self._stages:
|
||||
try:
|
||||
start_stage, stop_stage = events[stage]
|
||||
delta += np.array(stop_stage)-np.array(start_stage)
|
||||
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)
|
||||
ideal_delta = ideal_data["Ideal cycle"]
|
||||
delta = 0
|
||||
for stage in stages:
|
||||
delta += events[stage][1] - events[stage][0]
|
||||
performance = ideal_delta/delta*100
|
||||
performance_list.append(performance)
|
||||
|
||||
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]
|
||||
if settings["zoom"]:
|
||||
pass
|
||||
"""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,
|
||||
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(overshoot)
|
||||
plot_widget.addItem(stable)
|
||||
|
||||
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")
|
||||
|
||||
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)
|
||||
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"])
|
||||
plot = plot_widget.plot(df_continuous["time"], df_continuous[signal["name"]], pen=signal["pen"])
|
||||
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)
|
||||
|
||||
widget.setLayout(layout)
|
||||
@ -183,8 +160,5 @@ class PlotWidget(BasePlotWidget, BasePointPassportFormer):
|
||||
widgets = [self._build_widget(data_sample) for data_sample in data]
|
||||
self._mediator.notify(self, widgets)
|
||||
|
||||
def update_settings(self, params: list[dict]):
|
||||
self._initIdealBuilder(idealDataBuilder=idealDataBuilder, params=params)
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,55 +1,103 @@
|
||||
import pyqtgraph as pg
|
||||
from pyqtgraph.Qt import QtWidgets
|
||||
from pyqtgraph.parametertree import Parameter, ParameterTree
|
||||
from PyQt5.QtWidgets import QWidget, QTableWidget, QVBoxLayout, QTableWidgetItem, QLabel, QPushButton, QLineEdit, QHBoxLayout
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QIntValidator
|
||||
|
||||
|
||||
from src.utils.json_tools import read_json, write_json
|
||||
from src.gui import qt_settings as qts
|
||||
|
||||
class settingsWindow(QtWidgets.QWidget):
|
||||
class settingsWindow(QWidget):
|
||||
def __init__(self, path: str, name: str, upd_func):
|
||||
super(settingsWindow, self).__init__()
|
||||
self.settingsPath = path
|
||||
self.name = name
|
||||
self._settingsPath = path
|
||||
self._name = name
|
||||
self._data = {}
|
||||
self._upd_func = upd_func
|
||||
|
||||
self.data = {}
|
||||
self.params = None
|
||||
self.load_settings()
|
||||
self._init_ui()
|
||||
self.params.sigTreeStateChanged.connect(upd_func)
|
||||
|
||||
def load_settings(self) -> None:
|
||||
self.data = read_json(self.settingsPath)
|
||||
self._data = read_json(self._settingsPath)
|
||||
|
||||
def write_settings(self) -> None:
|
||||
self.getParams()
|
||||
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()
|
||||
write_json(self._settingsPath, self._data)
|
||||
|
||||
def getParams(self) -> dict:
|
||||
self.data = {}
|
||||
for p in self.params:
|
||||
if p.name() != 'Save':
|
||||
self.data[p.name()] = p.value()
|
||||
return self.data
|
||||
return self._data
|
||||
|
||||
|
||||
def _init_ui(self) -> None:
|
||||
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__':
|
||||
app = pg.mkQApp("Parameter Tree Example")
|
||||
|
||||
@ -7,6 +7,7 @@ from src.controller.mediator import Mediator
|
||||
from src.controller.converter import DataConverter
|
||||
from src.gui.plotter import PlotWidget
|
||||
from src.controller.controller import Controller
|
||||
from src.controller.passportFormer import PassportFormer
|
||||
|
||||
|
||||
def main():
|
||||
@ -15,8 +16,9 @@ def main():
|
||||
data_converter = DataConverter()
|
||||
plot_widget_builder = PlotWidget()
|
||||
controller = Controller()
|
||||
passport_former = PassportFormer()
|
||||
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()
|
||||
|
||||
controller.signal_widgets.connect(window.show_plot_tabs)
|
||||
|
||||
Binary file not shown.
@ -18,20 +18,23 @@ class BaseMediator:
|
||||
def __init__(self,
|
||||
monitor: BaseDirectoryMonitor,
|
||||
converter: BaseDataConverter,
|
||||
passportFormer: BasePointPassportFormer,
|
||||
plot: BasePlotWidget,
|
||||
controller: BaseController):
|
||||
self._monitor = monitor
|
||||
self._monitor.mediator = self
|
||||
self._converter = converter
|
||||
self._converter.mediator = self
|
||||
self._passportFormer = passportFormer
|
||||
self._passportFormer.mediator = self
|
||||
self._plot = plot
|
||||
self._plot.mediator = self
|
||||
self._controller = controller
|
||||
self._controller.mediator = self
|
||||
|
||||
def notify(self,
|
||||
source: Union[BaseDirectoryMonitor, BaseDataConverter, BasePlotWidget, BaseMainWindow],
|
||||
data: Union[list[str], list[pd.DataFrame], list[QWidget], list[dict]]):
|
||||
source: Union[BaseDirectoryMonitor, BaseDataConverter, BasePointPassportFormer, BasePlotWidget],
|
||||
data: Union[list[str], list[pd.DataFrame], list[list], list[QWidget]]):
|
||||
...
|
||||
def push_settings (self, data: list[dict]):
|
||||
...
|
||||
@ -120,7 +123,8 @@ class BasePlotWidget:
|
||||
"Settings": {
|
||||
"zoom": False,
|
||||
"stages": True,
|
||||
"performance": True
|
||||
"performance": True,
|
||||
"ideals": True
|
||||
},
|
||||
"Real_signals": [
|
||||
{
|
||||
@ -147,7 +151,8 @@ class BasePlotWidget:
|
||||
"Settings": {
|
||||
"zoom": True,
|
||||
"stages": False,
|
||||
"performance": False
|
||||
"performance": False,
|
||||
"ideals": True
|
||||
},
|
||||
"Real_signals": [
|
||||
{
|
||||
@ -170,7 +175,8 @@ class BasePlotWidget:
|
||||
"Settings": {
|
||||
"zoom": False,
|
||||
"stages": True,
|
||||
"performance": False
|
||||
"performance": False,
|
||||
"ideals": True
|
||||
},
|
||||
"Real_signals": [
|
||||
{
|
||||
@ -218,8 +224,6 @@ class BasePlotWidget:
|
||||
def build(self, data: list[pd.DataFrame]) -> list[QWidget]:
|
||||
...
|
||||
|
||||
def update_settings(self, data: list[dict]) -> None:
|
||||
...
|
||||
|
||||
class BaseController(QObject):
|
||||
|
||||
@ -231,6 +235,7 @@ class BaseController(QObject):
|
||||
|
||||
|
||||
class BaseIdealDataBuilder(OptAlgorithm):
|
||||
|
||||
def __init__(self, params: list[dict]):
|
||||
operator_params, system_params = params
|
||||
self.mul = system_params['time_capture']
|
||||
@ -325,13 +330,15 @@ class BaseMainWindow(QWidget):
|
||||
|
||||
class BasePointPassportFormer:
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self,
|
||||
mediator: Optional[BaseMediator] = None):
|
||||
self._mediator = mediator
|
||||
self._clear_stage = "Welding"
|
||||
self._stages = [
|
||||
"Closing",
|
||||
"Squeeze",
|
||||
"Welding",
|
||||
"Relief",
|
||||
"Relief"
|
||||
]
|
||||
|
||||
def _find_indexes(self,
|
||||
@ -355,7 +362,7 @@ class BasePointPassportFormer:
|
||||
|
||||
def _filter_events(self,
|
||||
times: pd.Series,
|
||||
dataframe: pd.DataFrame) -> dict[list[float]]:
|
||||
dataframe: pd.DataFrame) -> list[dict[list[float]], int]:
|
||||
events = {}
|
||||
if self._clear_stage in self._stages:
|
||||
start_list, end_list = self._find_events(self._clear_stage, times, dataframe)
|
||||
@ -363,26 +370,30 @@ class BasePointPassportFormer:
|
||||
for stage in self._stages:
|
||||
start_list, end_list = self._find_events(stage, times, dataframe)
|
||||
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,
|
||||
params: list[dict] = None):
|
||||
params: list[dict] = None) -> dict:
|
||||
self.opt = idealDataBuilder(params)
|
||||
|
||||
self._stage_ideals = {
|
||||
stage_ideals = {
|
||||
"Closing": self._opt.get_closingDF(),
|
||||
"Squeeze": self._opt.get_compressionDF(),
|
||||
"Welding": self._opt.get_weldingDF(),
|
||||
"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,
|
||||
stage: str):
|
||||
data = self._stage_ideals[stage]
|
||||
def form_passports(self) -> list[list[pd.DataFrame, dict, list]]:
|
||||
...
|
||||
|
||||
def update_settings(self, params: list) -> None:
|
||||
...
|
||||
|
||||
|
||||
@property
|
||||
def opt(self) -> BaseIdealDataBuilder:
|
||||
return self._opt
|
||||
@ -390,3 +401,11 @@ class BasePointPassportFormer:
|
||||
@opt.setter
|
||||
def opt(self, opt: BaseIdealDataBuilder):
|
||||
self._opt = opt
|
||||
|
||||
@property
|
||||
def mediator(self) -> BaseMediator:
|
||||
return self._mediator
|
||||
|
||||
@mediator.setter
|
||||
def mediator(self, mediator: BaseMediator) -> None:
|
||||
self._mediator = mediator
|
||||
Loading…
Reference in New Issue
Block a user