dev: добавлено окно, отображающее параметры каждого элемента графика

This commit is contained in:
Andrew 2024-12-17 20:40:04 +03:00
parent 365118bc22
commit eaec12d3ff
12 changed files with 152 additions and 28 deletions

View File

@ -81,19 +81,19 @@
], ],
"distance_l_2": [ "distance_l_2": [
0.0275, 0.0275,
0.03, 0.0255,
0.033, 0.0242,
0.033, 0.0245,
0.033, 0.0228,
0.033, 0.0236,
0.033, 0.0229,
0.033, 0.0248,
0.033, 0.024,
0.033, 0.0235,
0.033, 0.025,
0.033, 0.0276,
0.033, 0.0234,
0.033 0.0215
], ],
"distance_h_end1": [ "distance_h_end1": [
0.003, 0.003,

View File

@ -17,4 +17,5 @@ class Controller(BaseController):
self.signal_settings.emit(settings) self.signal_settings.emit(settings)
def open_custom_file (self, filepath: str) -> None: def open_custom_file (self, filepath: str) -> None:
self.signal_monitor.emit(filepath) self.signal_monitor.emit(filepath)

Binary file not shown.

View File

@ -5,6 +5,7 @@ from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from utils.base.base import BaseMainWindow, BaseController from utils.base.base import BaseMainWindow, BaseController
from gui.settings_window import settingsWindow from gui.settings_window import settingsWindow
from gui.reportGui import ReportSettings
class MainWindow(BaseMainWindow): class MainWindow(BaseMainWindow):
def __init__(self, def __init__(self,
@ -15,8 +16,10 @@ class MainWindow(BaseMainWindow):
self.set_style(self) self.set_style(self)
self.settings_button.clicked.connect(self._show_settings) self.settings_button.clicked.connect(self._show_settings)
self.select_dir_button.clicked.connect(self._select_dir) self.select_dir_button.clicked.connect(self._select_dir)
self.report_button.clicked.connect(self._report_window)
self.operSettings = settingsWindow("params/operator_params.json", 'Operator', self._updater_trigger) self.operSettings = settingsWindow("params/operator_params.json", 'Operator', self._updater_trigger)
self.sysSettings = settingsWindow("params/system_params.json", 'System', self._updater_trigger) self.sysSettings = settingsWindow("params/system_params.json", 'System', self._updater_trigger)
self.repSettings = ReportSettings()
def initUI(self) -> None: def initUI(self) -> None:
self.tabWidget = QtWidgets.QTabWidget() self.tabWidget = QtWidgets.QTabWidget()
@ -29,19 +32,30 @@ class MainWindow(BaseMainWindow):
self.settings_button.setFixedWidth(160) self.settings_button.setFixedWidth(160)
self.select_dir_button = QtWidgets.QPushButton("Open directory") self.select_dir_button = QtWidgets.QPushButton("Open directory")
self.select_dir_button.setFixedWidth(175) self.select_dir_button.setFixedWidth(175)
self.report_button = QtWidgets.QPushButton("Generate report")
self.report_button.setFixedWidth(175)
self.rep_settings_button = QtWidgets.QPushButton("Report settings")
self.rep_settings_button.setFixedWidth(175)
self.rep_settings_button.setVisible(False)
button_layout = QtWidgets.QHBoxLayout() button_layout = QtWidgets.QHBoxLayout()
button_layout.setSpacing(2) button_layout.setSpacing(2)
button_layout.addWidget(self.settings_button) button_layout.addWidget(self.settings_button)
button_layout.addWidget(self.select_dir_button) button_layout.addWidget(self.select_dir_button)
button_layout.addWidget(self.report_button)
button_layout.addWidget(self.rep_settings_button)
layout.addLayout(button_layout) layout.addLayout(button_layout)
self.setLayout(layout) self.setLayout(layout)
def show_plot_tabs(self, plot_widgets: list[QtWidgets.QWidget]) -> None: def show_plot_tabs(self, plot_widgets: list[QtWidgets.QWidget]) -> None:
for plot_widget in plot_widgets: for plot_widget in plot_widgets:
widget, reg_items, curve_items = plot_widget
tab = QtWidgets.QWidget() tab = QtWidgets.QWidget()
tab.setProperty("reg_items", reg_items)
tab.setProperty("curve_items", curve_items)
grid = QtWidgets.QGridLayout() grid = QtWidgets.QGridLayout()
grid.addWidget(plot_widget) grid.addWidget(widget)
tab.setLayout(grid) tab.setLayout(grid)
self.tabWidget.addTab(tab, "SF_trace_" + dt.now().strftime('%Y_%m_%d-%H_%M_%S')) self.tabWidget.addTab(tab, "SF_trace_" + dt.now().strftime('%Y_%m_%d-%H_%M_%S'))
self.tabWidget.setCurrentWidget(tab) self.tabWidget.setCurrentWidget(tab)
@ -51,7 +65,6 @@ class MainWindow(BaseMainWindow):
for i in range(0, tab_count-2): for i in range(0, tab_count-2):
self._close_tab(i) self._close_tab(i)
def keyPressEvent(self, a0): def keyPressEvent(self, a0):
if a0.key() == Qt.Key_F5: if a0.key() == Qt.Key_F5:
pass pass
@ -77,5 +90,22 @@ class MainWindow(BaseMainWindow):
if folder_path: if folder_path:
self._controller.open_custom_file(folder_path) self._controller.open_custom_file(folder_path)
def _report_window(self):
tab = self.tabWidget.currentWidget()
reg_items = tab.property("reg_items")
curve_items = tab.property("curve_items")
print(curve_items)
print(reg_items)
self.rep_settings_button.setVisible(True)
self.rep_settings_button.clicked.connect(lambda:self.repSettings.build(reg_items, curve_items))

View File

@ -59,6 +59,7 @@ class PlotWidget(BasePlotWidget):
plot_widget: pg.PlotWidget, plot_widget: pg.PlotWidget,
point_events: dict[str, list[float]], point_events: dict[str, list[float]],
dataframe_headers: list[str], dataframe_headers: list[str],
reg_items: dict,
transparency: int = 75) -> None: transparency: int = 75) -> None:
""" """
Добавляет регионы для реальных этапов, если все стадии есть в заголовках датафрейма. Добавляет регионы для реальных этапов, если все стадии есть в заголовках датафрейма.
@ -71,11 +72,14 @@ class PlotWidget(BasePlotWidget):
if region is not None: if region is not None:
region.setZValue(-20) region.setZValue(-20)
plot_widget.addItem(region) plot_widget.addItem(region)
reg_items["real"].setdefault(stage, [])
reg_items["real"][stage].append(region)
def _add_ideal_stage_regions(self, def _add_ideal_stage_regions(self,
plot_widget: pg.PlotWidget, plot_widget: pg.PlotWidget,
ideal_data: dict[str, Any], ideal_data: dict[str, Any],
point_events: dict[str, list[float]], point_events: dict[str, list[float]],
reg_items: dict,
transparency: int = 125) -> None: transparency: int = 125) -> None:
""" """
Добавляет регионы для идеальных этапов. Добавляет регионы для идеальных этапов.
@ -89,12 +93,15 @@ class PlotWidget(BasePlotWidget):
if region: if region:
region.setZValue(-10) region.setZValue(-10)
plot_widget.addItem(region) plot_widget.addItem(region)
reg_items["ideal"].setdefault(stage, [])
reg_items["ideal"][stage].append(region)
def _add_ideal_signals(self, def _add_ideal_signals(self,
plot_widget: pg.PlotWidget, plot_widget: pg.PlotWidget,
ideal_data: dict[str, Any], ideal_data: dict[str, Any],
point_events: dict[str, list[float]], point_events: dict[str, list[float]],
ideal_signals: list[dict[str, Any]]) -> None: ideal_signals: list[dict[str, Any]],
curve_items: dict) -> None:
""" """
Добавляет идеальные сигналы для каждого этапа. Добавляет идеальные сигналы для каждого этапа.
""" """
@ -109,12 +116,15 @@ class PlotWidget(BasePlotWidget):
if curve: if curve:
curve.setZValue(10) curve.setZValue(10)
plot_widget.addItem(curve) plot_widget.addItem(curve)
curve_items["ideal"].setdefault(signal["name"], {})
curve_items["ideal"][signal["name"]][stage] = curve
def _add_real_signals(self, def _add_real_signals(self,
plot_widget: pg.PlotWidget, plot_widget: pg.PlotWidget,
dataframe: pd.DataFrame, dataframe: pd.DataFrame,
real_signals: list[dict[str, Any]], real_signals: list[dict[str, Any]],
legend: pg.LegendItem) -> None: legend: pg.LegendItem,
curve_items: dict) -> None:
""" """
Добавляет реальные сигналы из dataframe на виджет. Добавляет реальные сигналы из dataframe на виджет.
""" """
@ -124,6 +134,8 @@ class PlotWidget(BasePlotWidget):
plot = plot_widget.plot(dataframe["time"], dataframe[signal["name"]], pen=signal["pen"], fast=True) plot = plot_widget.plot(dataframe["time"], dataframe[signal["name"]], pen=signal["pen"], fast=True)
plot.setZValue(0) plot.setZValue(0)
legend.addItem(plot, signal["name"]) legend.addItem(plot, signal["name"])
curve_items["real"].setdefault(signal["name"], {})
curve_items["real"][signal["name"]] = plot
def _add_performance_label(self, def _add_performance_label(self,
layout: QVBoxLayout, layout: QVBoxLayout,
@ -152,6 +164,8 @@ class PlotWidget(BasePlotWidget):
""" """
widget = QWidget() widget = QWidget()
layout = QVBoxLayout(widget) layout = QVBoxLayout(widget)
reg_items = {"real":{}, "ideal":{}}
curve_items = {"real":{}, "ideal":{}}
dataframe, points_pocket, useful_data = data dataframe, points_pocket, useful_data = data
tesla_time = useful_data["tesla_time"] tesla_time = useful_data["tesla_time"]
@ -192,7 +206,7 @@ class PlotWidget(BasePlotWidget):
# Добавляем реальные стадии # Добавляем реальные стадии
if settings["stages"]: if settings["stages"]:
self._add_stage_regions(plot_widget, point_events, dataframe_headers, 75) self._add_stage_regions(plot_widget, point_events, dataframe_headers, reg_items, 75)
# TODO: подобрать не вырвеглазные цвета, возможно ограничить зону # TODO: подобрать не вырвеглазные цвета, возможно ограничить зону
if settings["workpiece"]: if settings["workpiece"]:
@ -209,8 +223,8 @@ class PlotWidget(BasePlotWidget):
# Добавляем идеальные стадии и идеальные сигналы # Добавляем идеальные стадии и идеальные сигналы
if settings["ideals"]: if settings["ideals"]:
self._add_ideal_stage_regions(plot_widget, ideal_data, point_events, 100) self._add_ideal_stage_regions(plot_widget, ideal_data, point_events, reg_items, 100)
self._add_ideal_signals(plot_widget, ideal_data, point_events, description["Ideal_signals"]) self._add_ideal_signals(plot_widget, ideal_data, point_events, description["Ideal_signals"], curve_items)
# Подсчёт производительности # Подсчёт производительности
if settings["performance"]: if settings["performance"]:
@ -229,7 +243,7 @@ class PlotWidget(BasePlotWidget):
worst_timeframe = point_timeframe worst_timeframe = point_timeframe
# Добавляем реальные сигналы # Добавляем реальные сигналы
self._add_real_signals(plot_widget, dataframe, description["Real_signals"], legend) self._add_real_signals(plot_widget, dataframe, description["Real_signals"], legend, curve_items)
if widget_num == 0: if widget_num == 0:
main_plot = plot_widget main_plot = plot_widget
else: else:
@ -248,7 +262,7 @@ class PlotWidget(BasePlotWidget):
main_plot.sigXRangeChanged.connect(lambda _, plot=main_plot, region=ROI_region: self._sync_navigator_with_main(main_plot=plot, region=region)) main_plot.sigXRangeChanged.connect(lambda _, plot=main_plot, region=ROI_region: self._sync_navigator_with_main(main_plot=plot, region=region))
widget.setLayout(layout) widget.setLayout(layout)
return widget return widget, reg_items, curve_items
def build(self, data: list[list[Any]]) -> None: def build(self, data: list[list[Any]]) -> None:
""" """
@ -260,6 +274,8 @@ class PlotWidget(BasePlotWidget):
... ...
] ]
""" """
widgets = [self._build_widget(data_sample) for data_sample in data] widgets_datapack = [self._build_widget(data_sample) for data_sample in data]
self._mediator.notify(self, widgets) self._mediator.notify(self, widgets_datapack)

77
src/gui/reportGui.py Normal file
View File

@ -0,0 +1,77 @@
import pyqtgraph as pg
from pyqtgraph.parametertree import Parameter, ParameterTree
from typing import Union
from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt
class ReportSettings(QtWidgets.QWidget):
def build(self, reg_items: dict, curve_items: dict) -> None:
param_tree = ParameterTree()
layout = QtWidgets.QVBoxLayout()
layout.addWidget(param_tree)
self.setLayout(layout)
body= [
self._generate_reg_params(reg_items),
self._generate_curve_params(curve_items)
]
# Добавляем параметры в дерево
params = Parameter.create(name='params', type='group', children=body)
param_tree.setParameters(params, showTop=False)
self.show()
def _generate_reg_params(self, reg_items: dict) -> dict:
res = {'name': 'Sectors', 'type': 'group', 'children': [
{'name': 'Real sectors', 'type': 'group', 'children': self._create_samples(reg_items["real"])},
{'name': 'Ideal sectors', 'type': 'group', 'children': self._create_samples(reg_items["ideal"])},
]}
return res
def _generate_curve_params(self, curve_items: dict) -> dict:
res = {'name': 'Plots', 'type': 'group', 'children': [
{'name': 'Real plots', 'type': 'group', 'children': self._create_samples(curve_items["real"])},
{'name': 'Ideal plots', 'type': 'group', 'children': self._create_ideal_curves(curve_items["ideal"])},
]}
return res
def _create_ideal_curves(self, curve: dict) -> list[dict]:
"""Создаем секторы с этапами циклограммы"""
res = []
for key, item in curve.items():
param = {'name': key, 'type': 'group', 'children': self._create_samples(item)}
res.append(param)
return res
def _create_samples(self, sector: dict) -> list[dict]:
res = []
for key, item in sector.items():
sample = item[0] if type(item) == list else item
param = {'name': key, 'type': 'group', 'children': self._create_settings(sample)}
res.append(param)
return res
def _create_settings(self, item: Union[pg.LinearRegionItem, pg.PlotDataItem]) -> list[dict]:
"""Настройки для элемента"""
if type(item) == pg.LinearRegionItem:
pen = item.lines[0].pen
brush = item.brush
fill_color = brush.color().getRgb()
else:
pen = pg.mkPen(item.opts.get("pen"))
fill_color = None
line_color = pen.color().getRgb()
line_thickness = pen.width()
visibility = item.isVisible()
return [
{'name': 'Line color', 'type': 'color', 'value': line_color},
{'name': 'Line thickness', 'type': 'int', 'value': line_thickness, 'limits': (1, 10)},
{'name': 'Visibility', 'type': 'bool', 'value': visibility},
{'name': 'Fill color', 'type': 'color', 'value': fill_color},
]

View File

@ -123,7 +123,7 @@ class BasePlotWidget:
"zoom": False, "zoom": False,
"stages": True, "stages": True,
"performance": True, "performance": True,
"ideals": True, "ideals": False,
"mirror ME": False, "mirror ME": False,
"workpiece": False, "workpiece": False,
"force compensation FE": False "force compensation FE": False
@ -154,7 +154,7 @@ class BasePlotWidget:
"zoom": False, "zoom": False,
"stages": True, "stages": True,
"performance": False, "performance": False,
"ideals": True, "ideals": False,
"mirror ME": True, "mirror ME": True,
"workpiece": True, "workpiece": True,
"force compensation FE": True "force compensation FE": True