Compare commits
4 Commits
10e7cf2a37
...
507036e81c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
507036e81c | ||
|
|
0a9b1c50b8 | ||
|
|
a0d6cba386 | ||
|
|
cee262939b |
@ -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
|
||||||
|
]
|
||||||
}
|
}
|
||||||
@ -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.
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 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()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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()
|
||||||
|
|
||||||
|
|||||||
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(), data['tmovement']] # 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):
|
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()
|
||||||
|
|||||||
@ -6,34 +6,6 @@ from numpy import floating
|
|||||||
from typing import Optional, Any, NamedTuple
|
from typing import Optional, Any, NamedTuple
|
||||||
|
|
||||||
from src.utils.base.base import BasePlotWidget
|
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_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]
|
||||||
@ -43,14 +15,13 @@ class ProcessStage(NamedTuple):
|
|||||||
|
|
||||||
class PlotWidget(BasePlotWidget):
|
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
|
||||||
|
|
||||||
@ -64,19 +35,6 @@ class PlotWidget(BasePlotWidget):
|
|||||||
region.setBrush(pg.mkBrush(self._stage_colors[stage]))
|
region.setBrush(pg.mkBrush(self._stage_colors[stage]))
|
||||||
return region
|
return region
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _get_timestamp(self,
|
|
||||||
stage: str,
|
|
||||||
times: pd.Series,
|
|
||||||
dataframe: pd.DataFrame) -> Optional[list[float]]:
|
|
||||||
stage_diff = np.diff(dataframe[stage])
|
|
||||||
start_index = np.where(stage_diff == 1)[0]
|
|
||||||
finish_index = np.where(stage_diff == -1)[0]
|
|
||||||
if start_index.size:
|
|
||||||
start_timestamp = times[start_index[0]]
|
|
||||||
finish_timestamp = times[finish_index[0]] if finish_index.size else times[len(times) - 1]
|
|
||||||
return start_timestamp, finish_timestamp
|
|
||||||
return None
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _init_plot_widget(title: str) -> tuple[pg.PlotWidget, pg.LegendItem]:
|
def _init_plot_widget(title: str) -> tuple[pg.PlotWidget, pg.LegendItem]:
|
||||||
@ -90,110 +48,109 @@ class PlotWidget(BasePlotWidget):
|
|||||||
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 []
|
|
||||||
|
|
||||||
if data.size and start_index.size:
|
|
||||||
start = start_index[0]
|
|
||||||
finish = finish_index[0] if finish_index.size else (len(data) - 1)
|
|
||||||
data_slice = data[start:finish]
|
|
||||||
mean = np.mean(data_slice)
|
|
||||||
return ProcessStage(mean_value=mean, start_index=int(start), finish_index=int(finish))
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _build_widget(self, dataframe: pd.DataFrame) -> QWidget:
|
stage_diff = np.diff(dataframe[stage])
|
||||||
|
start_index = np.where(stage_diff == 1)[0]
|
||||||
|
finish_index = np.where(stage_diff == -1)[0]
|
||||||
|
|
||||||
|
data = dataframe[signal_name] if signal_name in dataframe.columns.tolist() else []
|
||||||
|
|
||||||
|
if data.size and start_index.size:
|
||||||
|
start = start_index[0]
|
||||||
|
finish = finish_index[0] if finish_index.size else (len(data) - 1)
|
||||||
|
data_slice = data[start:finish]
|
||||||
|
mean = np.mean(data_slice)
|
||||||
|
return ProcessStage(mean_value=mean, start_index=int(start), finish_index=int(finish))
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _build_widget(self, 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"] and all([stage in dataframe_headers for stage in self._stages]):
|
|
||||||
for stage in self._stages:
|
for dataframe, ideal_data, events in data:
|
||||||
start_timestamp, finish_timestamp = self._get_timestamp(stage, time_axis, dataframe)
|
df_continuous = pd.concat([df_continuous, dataframe], axis=0)
|
||||||
region = self._create_stage_region(stage, start_timestamp, finish_timestamp)
|
dataframe_headers = dataframe.columns.tolist()
|
||||||
if region:
|
stages = events.keys()
|
||||||
plot_widget.addItem(region)
|
|
||||||
|
|
||||||
for signal in description["Ideal_signals"]:
|
|
||||||
ideal_plot = self._create_curve_ideal(stage, signal, start_timestamp, finish_timestamp)
|
|
||||||
if ideal_plot:
|
|
||||||
plot_widget.addItem(ideal_plot)
|
|
||||||
|
|
||||||
end_timestamp = time_axis[len(time_axis) - 1]
|
if settings["stages"] and all([stage in dataframe_headers for stage in stages]):
|
||||||
region = self._create_stage_region("Oncoming", finish_timestamp, end_timestamp)
|
for stage in stages:
|
||||||
if region:
|
start_t, end_t = events[stage]
|
||||||
plot_widget.addItem(region)
|
region = self._create_stage_region(stage, start_t, end_t)
|
||||||
|
if region:
|
||||||
|
plot_widget.addItem(region)
|
||||||
|
|
||||||
for signal in description["Ideal_signals"]:
|
if settings["ideals"]:
|
||||||
ideal_plot = self._create_curve_ideal("Oncoming", signal, finish_timestamp, end_timestamp)
|
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"] and all([stage in dataframe_headers for stage in self._stages]):
|
if settings["performance"]:
|
||||||
delta_timestamp = 0
|
ideal_delta = ideal_data["Ideal cycle"]
|
||||||
for stage in self._stages:
|
delta = 0
|
||||||
start_timestamp, finish_timestamp = self._get_timestamp(stage, time_axis, dataframe)
|
for stage in stages:
|
||||||
delta_timestamp += finish_timestamp - start_timestamp
|
delta += events[stage][1] - events[stage][0]
|
||||||
|
performance = ideal_delta/delta*100
|
||||||
|
performance_list.append(performance)
|
||||||
|
|
||||||
ideal_delta = self._opt.get_cycle_time()
|
if settings["zoom"]:
|
||||||
performance = round(ideal_delta/delta_timestamp*100, 2)
|
pass
|
||||||
performance_label = QLabel(f"Performance = {performance} %")
|
"""if max(time_axis) < 5.0:
|
||||||
layout.addWidget(performance_label)
|
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"]:
|
overshoot = pg.BarGraphItem(x0=0,
|
||||||
if max(time_axis) < 5.0:
|
y0=mean - mean * 0.05,
|
||||||
stages = [self.get_stage_info("Welding",
|
height=mean * 0.05 * 2,
|
||||||
dataframe,
|
width=start,
|
||||||
signal["name"]) for signal in description["Real_signals"]]
|
brush=pg.mkBrush([0, 250, 0, 100]))
|
||||||
if stages:
|
plot_widget.addItem(overshoot)
|
||||||
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,
|
stable = pg.BarGraphItem(x0=start,
|
||||||
y0=mean - mean * 0.05,
|
y0=mean - mean * 0.015,
|
||||||
height=mean * 0.05 * 2,
|
height=mean * 0.015 * 2,
|
||||||
width=start,
|
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)
|
||||||
@ -203,8 +160,5 @@ class PlotWidget(BasePlotWidget):
|
|||||||
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, data: list[dict]):
|
|
||||||
self._initIdealBuilder(idealDataBuilder=idealDataBuilder, data=data)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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.data = {}
|
self._upd_func = upd_func
|
||||||
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 getParams(self) -> dict:
|
||||||
|
return 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:
|
def _init_ui(self) -> None:
|
||||||
temp = self._getTreeStructure()
|
save_button = QPushButton()
|
||||||
self.params = Parameter.create(name=self.name, type='group', children=temp)
|
restore_button = QPushButton()
|
||||||
self.params.param('Save').sigActivated.connect(self.write_settings)
|
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)
|
||||||
|
|
||||||
ParamsTree = ParameterTree()
|
save_button.pressed.connect(self._save)
|
||||||
ParamsTree.setParameters(self.params, showTop=True)
|
restore_button.pressed.connect(self._restore)
|
||||||
layout = QtWidgets.QGridLayout()
|
self._num_points.editingFinished.connect(self._expand)
|
||||||
layout.addWidget(ParamsTree, 0,0)
|
|
||||||
|
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.setLayout(layout)
|
||||||
self.setStyleSheet(qts.white_style)
|
self.setStyleSheet(qts.white_style)
|
||||||
# self.show()
|
#self.show()
|
||||||
|
|
||||||
def getParams(self) -> dict:
|
def _save(self) -> dict:
|
||||||
self.data = {}
|
self._data = {}
|
||||||
for p in self.params:
|
for i in range(self._param_table.rowCount()):
|
||||||
if p.name() != 'Save':
|
key = self._param_table.item(i, 0).text()
|
||||||
self.data[p.name()] = p.value()
|
data = []
|
||||||
return self.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")
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
Binary file not shown.
@ -2,6 +2,7 @@ from typing import Optional
|
|||||||
import os
|
import os
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
from intervaltree import Interval, IntervalTree
|
||||||
|
|
||||||
from roboter import RobotPerformance, TWC_Performance
|
from roboter import RobotPerformance, TWC_Performance
|
||||||
|
|
||||||
@ -10,8 +11,25 @@ class PerformanceProcessor:
|
|||||||
def calc_performance(self, path, df):
|
def calc_performance(self, path, df):
|
||||||
robot = RobotPerformance()
|
robot = RobotPerformance()
|
||||||
TWC = TWC_Performance()
|
TWC = TWC_Performance()
|
||||||
rob_df = robot.job(path)
|
point_tree, movement_tree, dialog_tree = robot.job(path)
|
||||||
TWC_df = TWC.job(df)
|
closing_tree, squeeze_tree, relief_tree = TWC.job(df)
|
||||||
|
|
||||||
|
dialog_inPoint = point_tree & dialog_tree
|
||||||
|
dialog_inMovement = movement_tree & dialog_tree
|
||||||
|
|
||||||
|
closing_inPoint = point_tree & closing_tree
|
||||||
|
closing_inMovement = movement_tree & closing_tree
|
||||||
|
|
||||||
|
squeeze_inPoint = point_tree & squeeze_tree
|
||||||
|
squeeze_inMovement = movement_tree & squeeze_tree
|
||||||
|
|
||||||
|
relief_inPoint = point_tree & relief_tree
|
||||||
|
relief_inMovement = movement_tree & relief_tree
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -20,4 +38,5 @@ if __name__ == "__main__":
|
|||||||
robot = RobotPerformance()
|
robot = RobotPerformance()
|
||||||
#TWC = TWC_Performance()
|
#TWC = TWC_Performance()
|
||||||
result = robot.job(path)
|
result = robot.job(path)
|
||||||
print (result)
|
print (result[0])
|
||||||
|
print (result[1])
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import os
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
|
from intervaltree import Interval, IntervalTree
|
||||||
|
|
||||||
|
|
||||||
class BasePerformanceFactory(ABC):
|
class BasePerformanceFactory(ABC):
|
||||||
|
|
||||||
@ -88,16 +90,35 @@ class BaseProduct(ABC):
|
|||||||
stage_diff = np.diff(dataframe[signal])
|
stage_diff = np.diff(dataframe[signal])
|
||||||
start_idx = np.where(stage_diff == 1)
|
start_idx = np.where(stage_diff == 1)
|
||||||
finish_idx = np.where(stage_diff == -1)
|
finish_idx = np.where(stage_diff == -1)
|
||||||
return start_idx, finish_idx
|
return start_idx[0], finish_idx[0]
|
||||||
|
|
||||||
def operation(self, dataframe: pd.DataFrame) -> pd.DataFrame:
|
def _find_events(self,
|
||||||
all_idx = np.array([])
|
dataframe: pd.DataFrame,
|
||||||
for signal in self._signals:
|
signals: list[str]) -> Optional[dict[dict[pd.Series]]]:
|
||||||
|
intervals = {}
|
||||||
|
end_time = 0
|
||||||
|
for signal in signals:
|
||||||
start_idx, finish_idx = np.array(self._find_indexes(signal, dataframe))
|
start_idx, finish_idx = np.array(self._find_indexes(signal, dataframe))
|
||||||
all_idx = np.hstack([all_idx, start_idx[0], finish_idx[0]])
|
start_series = dataframe.loc[start_idx, "time"].reset_index(drop=True)
|
||||||
all_idx = np.sort(np.array(all_idx, dtype="int64"))
|
end_series = dataframe.loc[finish_idx, "time"].reset_index(drop=True)
|
||||||
result = dataframe.loc[all_idx, self._signals + ["time"]]
|
end_series.fillna(end_time)
|
||||||
return result
|
intervals[signal] = {"rise": start_series,
|
||||||
|
"fall": end_series}
|
||||||
|
return intervals
|
||||||
|
|
||||||
|
def _form_intervals(self,
|
||||||
|
start: pd.Series,
|
||||||
|
end: pd.Series) -> IntervalTree:
|
||||||
|
if len(start) != len(end):
|
||||||
|
for i in range(1, len(end)):
|
||||||
|
if end[i-1] > start[i]:
|
||||||
|
start = start.drop(i).reset_index(drop=True)
|
||||||
|
tree = IntervalTree(Interval(start[i], end[i], i) for i in range(len (start)))
|
||||||
|
return tree
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def operation(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
class RobotPerformance(BasePerformanceFactory):
|
class RobotPerformance(BasePerformanceFactory):
|
||||||
@ -105,33 +126,18 @@ class RobotPerformance(BasePerformanceFactory):
|
|||||||
def factory_method(self) -> BaseProduct:
|
def factory_method(self) -> BaseProduct:
|
||||||
return RobotDF()
|
return RobotDF()
|
||||||
|
|
||||||
def job(self, path) -> pd.DataFrame:
|
def job(self, path) -> list[pd.DataFrame]:
|
||||||
product = self.factory_method()
|
product = self.factory_method()
|
||||||
dataframe = self._get_file_data(path)
|
dataframe = self._get_file_data(path)
|
||||||
rob_df = product.operation(dataframe)
|
rob_df = product.operation(dataframe)
|
||||||
in_point, in_moving, in_dialog = False, False, False
|
|
||||||
for index, row in rob_df.iterrows():
|
|
||||||
if row["$OUT3012"] == 1:
|
|
||||||
if not in_point:
|
|
||||||
in_point = True
|
|
||||||
start_point = row["time"]
|
|
||||||
else:
|
|
||||||
in_point = False
|
|
||||||
time_in_point = row["time"] - start_point
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return rob_df
|
return rob_df
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TWC_Performance(BasePerformanceFactory):
|
class TWC_Performance(BasePerformanceFactory):
|
||||||
|
|
||||||
def factory_method(self) -> BaseProduct:
|
def factory_method(self) -> BaseProduct:
|
||||||
return TWC_DF()
|
return TWC_DF()
|
||||||
|
|
||||||
def job(self, TWC_DF: pd.DataFrame) -> pd.DataFrame:
|
def job(self, TWC_DF: pd.DataFrame) -> list[pd.DataFrame]:
|
||||||
product = self.factory_method()
|
product = self.factory_method()
|
||||||
result = product.operation(TWC_DF)
|
result = product.operation(TWC_DF)
|
||||||
return result
|
return result
|
||||||
@ -145,6 +151,13 @@ class RobotDF(BaseProduct):
|
|||||||
"$OUT3003"
|
"$OUT3003"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def operation(self, dataframe: pd.DataFrame) -> list[IntervalTree]:
|
||||||
|
events = self._find_events(dataframe, self._signals)
|
||||||
|
point_tree = self._form_intervals(start=events["$OUT3012"]["rise"], end=events["$OUT3012"]["fall"])
|
||||||
|
movement_tree = self._form_intervals(start=events["$OUT3003"]["fall"], end=events["$OUT3012"]["rise"])
|
||||||
|
dialog_tree = []
|
||||||
|
return point_tree, movement_tree, dialog_tree
|
||||||
|
|
||||||
|
|
||||||
class TWC_DF(BaseProduct):
|
class TWC_DF(BaseProduct):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -155,6 +168,13 @@ class TWC_DF(BaseProduct):
|
|||||||
"Relief"
|
"Relief"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def operation(self, dataframe: pd.DataFrame) -> list[IntervalTree]:
|
||||||
|
events = self._find_events(dataframe, self._signals)
|
||||||
|
closing_tree = self._form_intervals(start=events["Closing"]["rise"], end=events["Closing"]["fall"])
|
||||||
|
squeeze_tree = self._form_intervals(start=events["Squeeze"]["rise"], end=events["Squeeze"]["fall"])
|
||||||
|
relief_tree = self._form_intervals(start=events["Relief"]["rise"], end=events["Relief"]["fall"])
|
||||||
|
return closing_tree, squeeze_tree, relief_tree
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@ -8,26 +8,33 @@ from PyQt5.QtCore import QThread, QObject, QTimer
|
|||||||
from PyQt5.QtWidgets import QWidget, QTabWidget
|
from PyQt5.QtWidgets import QWidget, QTabWidget
|
||||||
from src.OptAlgorithm import OptAlgorithm
|
from src.OptAlgorithm import OptAlgorithm
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class BaseMediator:
|
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]):
|
||||||
...
|
...
|
||||||
@ -102,27 +109,22 @@ class BasePlotWidget:
|
|||||||
mediator: Optional[BaseMediator] = None):
|
mediator: Optional[BaseMediator] = None):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._mediator = mediator
|
self._mediator = mediator
|
||||||
|
|
||||||
self._stages = [
|
|
||||||
"Closing",
|
|
||||||
"Squeeze",
|
|
||||||
"Welding",
|
|
||||||
"Relief"
|
|
||||||
]
|
|
||||||
|
|
||||||
self._stage_colors = {
|
self._stage_colors = {
|
||||||
"Closing": [208, 28, 31, 100],
|
"Closing": [208, 28, 31, 100],
|
||||||
"Squeeze": [45, 51, 89, 150],
|
"Squeeze": [45, 51, 89, 150],
|
||||||
"Welding": [247, 183, 24, 100],
|
"Welding": [247, 183, 24, 100],
|
||||||
"Relief": [0, 134, 88, 100],
|
"Relief": [0, 134, 88, 100],
|
||||||
"Oncoming": [222, 184, 135, 100]
|
"Oncomming": [222, 184, 135, 100]
|
||||||
}
|
}
|
||||||
self._plt_channels = {
|
self._plt_channels = {
|
||||||
"Electrode Force, N & Welding Current, kA": {
|
"Electrode Force, N & Welding Current, kA": {
|
||||||
"Settings": {
|
"Settings": {
|
||||||
"zoom": False,
|
"zoom": False,
|
||||||
"stages": True,
|
"stages": True,
|
||||||
"performance": True
|
"performance": True,
|
||||||
|
"ideals": True
|
||||||
},
|
},
|
||||||
"Real_signals": [
|
"Real_signals": [
|
||||||
{
|
{
|
||||||
@ -149,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": [
|
||||||
{
|
{
|
||||||
@ -172,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": [
|
||||||
{
|
{
|
||||||
@ -200,18 +204,7 @@ 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(),
|
|
||||||
"Relief": self._opt.get_openingDF(),
|
|
||||||
"Oncoming": self._opt.get_oncomingDF()
|
|
||||||
}
|
|
||||||
@property
|
@property
|
||||||
def mediator(self) -> BaseMediator:
|
def mediator(self) -> BaseMediator:
|
||||||
return self._mediator
|
return self._mediator
|
||||||
@ -231,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):
|
||||||
|
|
||||||
@ -243,10 +234,10 @@ class BaseController(QObject):
|
|||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
# FIXME: WeldingDF показывает только 1 секунду
|
|
||||||
class BaseIdealDataBuilder(OptAlgorithm):
|
class BaseIdealDataBuilder(OptAlgorithm):
|
||||||
def __init__(self, data: list[dict]):
|
|
||||||
operator_params, system_params = data
|
def __init__(self, params: list[dict]):
|
||||||
|
operator_params, system_params = params
|
||||||
self.mul = system_params['time_capture']
|
self.mul = system_params['time_capture']
|
||||||
self.welding_time = operator_params['time_wielding']
|
self.welding_time = operator_params['time_wielding']
|
||||||
super().__init__(operator_params, system_params)
|
super().__init__(operator_params, system_params)
|
||||||
@ -337,4 +328,85 @@ class BaseMainWindow(QWidget):
|
|||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
class BasePointPassportFormer:
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
mediator: Optional[BaseMediator] = None):
|
||||||
|
self._mediator = mediator
|
||||||
|
self._clear_stage = "Welding"
|
||||||
|
self._stages = [
|
||||||
|
"Closing",
|
||||||
|
"Squeeze",
|
||||||
|
"Welding",
|
||||||
|
"Relief",
|
||||||
|
"Oncomming"
|
||||||
|
]
|
||||||
|
|
||||||
|
def _find_indexes(self,
|
||||||
|
signal: str,
|
||||||
|
dataframe: pd.DataFrame) -> list[list[float], list[float]]:
|
||||||
|
stage_diff = np.diff(dataframe[signal])
|
||||||
|
start_idx = np.where(stage_diff == 1)
|
||||||
|
finish_idx = np.where(stage_diff == -1)
|
||||||
|
return start_idx[0], finish_idx[0]
|
||||||
|
|
||||||
|
def _find_events(self,
|
||||||
|
signal: str,
|
||||||
|
times:pd.Series,
|
||||||
|
dataframe: pd.DataFrame) -> list[list[float]]:
|
||||||
|
start_idx, finish_idx = self._find_indexes(signal, dataframe)
|
||||||
|
start_list = times.loc[start_idx].tolist()
|
||||||
|
end_list = times.loc[finish_idx].tolist()
|
||||||
|
if len(start_list) - len(end_list) == 1:
|
||||||
|
end_list.append(float(times[len(times)-1]))
|
||||||
|
return start_list, end_list
|
||||||
|
|
||||||
|
def _filter_events(self,
|
||||||
|
times: pd.Series,
|
||||||
|
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)
|
||||||
|
point_quantity = len(start_list)
|
||||||
|
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, point_quantity
|
||||||
|
|
||||||
|
def _build_ideal_data(self,
|
||||||
|
idealDataBuilder: Optional[BaseIdealDataBuilder] = None,
|
||||||
|
params: list[dict] = None) -> dict:
|
||||||
|
self.opt = idealDataBuilder(params)
|
||||||
|
|
||||||
|
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(),
|
||||||
|
"Ideal cycle": self._opt.get_cycle_time()
|
||||||
|
}
|
||||||
|
return stage_ideals
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
@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
|
||||||
BIN
weldingSpotPerformance.7z
Normal file
BIN
weldingSpotPerformance.7z
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user