Compare commits

...

4 Commits

17 changed files with 129 additions and 41 deletions

View File

@ -51,7 +51,7 @@
0.075 0.075
], ],
"time_capture": [ "time_capture": [
1000.0 100.0
], ],
"UML_time_scaler": [ "UML_time_scaler": [
1000.0 1000.0

View File

@ -3,7 +3,9 @@ import pandas as pd
from typing import Union from typing import Union
from PyQt5.QtWidgets import QWidget from PyQt5.QtWidgets import QWidget
from utils.base.base import BaseMediator, BaseDirectoryMonitor, BaseDataConverter, BasePlotWidget, BasePointPassportFormer from utils.base.base import (BaseMediator, BaseDirectoryMonitor,
BaseDataConverter, BasePlotWidget,
BasePointPassportFormer)
class Mediator(BaseMediator): class Mediator(BaseMediator):

View File

@ -1,6 +1,4 @@
from time import sleep
import os import os
from loguru import logger from loguru import logger
from utils.base.base import BaseDirectoryMonitor from utils.base.base import BaseDirectoryMonitor
@ -28,7 +26,7 @@ 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 _, system_params = data
self._directory_path = system_params['trace_storage_path'][0] self._directory_path = system_params['trace_storage_path'][0]
self._update_time = system_params['monitor_update_period'][0] self._update_time = system_params['monitor_update_period'][0]
self._init_state() self._init_state()

View File

@ -1,6 +1,6 @@
from utils.base.base import BasePointPassportFormer, BaseIdealDataBuilder
import pandas as pd import pandas as pd
from utils.base.base import BasePointPassportFormer, BaseIdealDataBuilder
class idealDataBuilder(BaseIdealDataBuilder): class idealDataBuilder(BaseIdealDataBuilder):

View File

@ -1,15 +1,15 @@
from datetime import datetime as dt from datetime import datetime as dt
from typing import Optional from typing import Optional
from PyQt5 import QtWidgets 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 from gui.reportGui import ReportSettings
class MainWindow(BaseMainWindow): class MainWindow(BaseMainWindow):
def __init__(self, def __init__(self,
controller: Optional[BaseController] = None): controller: Optional[BaseController] = None) -> None:
super().__init__() super().__init__()
self._controller = controller self._controller = controller
self.initUI() self.initUI()
@ -34,15 +34,11 @@ class MainWindow(BaseMainWindow):
self.select_dir_button.setFixedWidth(175) self.select_dir_button.setFixedWidth(175)
self.report_button = QtWidgets.QPushButton("Generate report") self.report_button = QtWidgets.QPushButton("Generate report")
self.report_button.setFixedWidth(175) 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.report_button)
button_layout.addWidget(self.rep_settings_button)
layout.addLayout(button_layout) layout.addLayout(button_layout)
self.setLayout(layout) self.setLayout(layout)
@ -65,11 +61,13 @@ 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) -> None:
if a0.key() == Qt.Key_F5: if a0.key() == Qt.Key_F5:
pass tab_count = self.tabWidget.count()
for i in range(0, tab_count):
self._close_tab(i)
def _show_settings(self): def _show_settings(self) -> None:
self.operSettings.show() self.operSettings.show()
self.sysSettings.show() self.sysSettings.show()
@ -90,15 +88,11 @@ 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): def _report_window(self) -> None:
tab = self.tabWidget.currentWidget() tab = self.tabWidget.currentWidget()
reg_items = tab.property("reg_items") reg_items = tab.property("reg_items")
curve_items = tab.property("curve_items") curve_items = tab.property("curve_items")
print(curve_items) self.repSettings.build(reg_items, 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

@ -1,7 +1,7 @@
import pandas as pd
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QGraphicsRectItem from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QGraphicsRectItem
import copy import copy
import pyqtgraph as pg import pyqtgraph as pg
import pandas as pd
from typing import Optional, Any from typing import Optional, Any
from utils.base.base import BasePlotWidget from utils.base.base import BasePlotWidget
@ -117,7 +117,8 @@ class PlotWidget(BasePlotWidget):
curve.setZValue(10) curve.setZValue(10)
plot_widget.addItem(curve) plot_widget.addItem(curve)
curve_items["ideal"].setdefault(signal["name"], {}) curve_items["ideal"].setdefault(signal["name"], {})
curve_items["ideal"][signal["name"]][stage] = curve curve_items["ideal"][signal["name"]].setdefault(stage, [])
curve_items["ideal"][signal["name"]][stage].append(curve)
def _add_real_signals(self, def _add_real_signals(self,
plot_widget: pg.PlotWidget, plot_widget: pg.PlotWidget,
@ -269,8 +270,8 @@ class PlotWidget(BasePlotWidget):
Создает набор виджетов по предоставленному списку данных. Создает набор виджетов по предоставленному списку данных.
Предполагается, что data это список элементов вида: Предполагается, что data это список элементов вида:
[ [
[dataframe, points_pocket, tesla_time], [dataframe, points_pocket, useful_data],
[dataframe, points_pocket, tesla_time], [dataframe, points_pocket, useful_data],
... ...
] ]
""" """

View File

@ -2,16 +2,16 @@ import pyqtgraph as pg
from pyqtgraph.parametertree import Parameter, ParameterTree from pyqtgraph.parametertree import Parameter, ParameterTree
from typing import Union from typing import Union
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt
class ReportSettings(QtWidgets.QWidget): class ReportSettings(QtWidgets.QWidget):
def build(self, reg_items: dict, curve_items: dict) -> None: def build(self, reg_items: dict, curve_items: dict) -> None:
"""Создает ParameterTree для элементов всех графиков выбранной вкладки"""
self._clear()
param_tree = ParameterTree() param_tree = ParameterTree()
layout = QtWidgets.QVBoxLayout() layout = self.layout()
layout.addWidget(param_tree) layout.addWidget(param_tree)
self.setLayout(layout)
body= [ body= [
self._generate_reg_params(reg_items), self._generate_reg_params(reg_items),
@ -19,10 +19,30 @@ class ReportSettings(QtWidgets.QWidget):
] ]
# Добавляем параметры в дерево # Добавляем параметры в дерево
params = Parameter.create(name='params', type='group', children=body) params = Parameter.create(name='params', type='group', children=body)
params.sigTreeStateChanged.connect(
lambda: self._update_settings(reg_items, curve_items, params)
)
param_tree.setParameters(params, showTop=False) param_tree.setParameters(params, showTop=False)
self.show() self.show()
def _generate_reg_params(self, reg_items: dict) -> dict: def _clear(self) -> None:
"""
Приводит виджет в готовое к работе состояние.
Удаляет все содержимое, если имеется
"""
main = self.layout()
if self.layout() is not None:
while main.count():
child = main.takeAt(0)
if child.widget() is not None:
child.widget().deleteLater()
else:
self.setLayout(QtWidgets.QVBoxLayout())
def _generate_reg_params(self,
reg_items: dict) -> dict:
"""Созадет реальные и идеальные секторы"""
res = {'name': 'Sectors', 'type': 'group', 'children': [ res = {'name': 'Sectors', 'type': 'group', 'children': [
{'name': 'Real sectors', 'type': 'group', 'children': self._create_samples(reg_items["real"])}, {'name': 'Real sectors', 'type': 'group', 'children': self._create_samples(reg_items["real"])},
@ -30,7 +50,10 @@ class ReportSettings(QtWidgets.QWidget):
]} ]}
return res return res
def _generate_curve_params(self, curve_items: dict) -> dict: def _generate_curve_params(self,
curve_items: dict) -> dict:
"""Создает реальные и идеальные линии графиков"""
res = {'name': 'Plots', 'type': 'group', 'children': [ res = {'name': 'Plots', 'type': 'group', 'children': [
{'name': 'Real plots', 'type': 'group', 'children': self._create_samples(curve_items["real"])}, {'name': 'Real plots', 'type': 'group', 'children': self._create_samples(curve_items["real"])},
@ -38,15 +61,22 @@ class ReportSettings(QtWidgets.QWidget):
]} ]}
return res return res
def _create_ideal_curves(self, curve: dict) -> list[dict]: def _create_ideal_curves(self,
"""Создаем секторы с этапами циклограммы""" curve: dict) -> list[dict]:
"""Создает секторы с этапами циклограммы"""
res = [] res = []
for key, item in curve.items(): for key, item in curve.items():
param = {'name': key, 'type': 'group', 'children': self._create_samples(item)} param = {'name': key, 'type': 'group', 'children': self._create_samples(item)}
res.append(param) res.append(param)
return res return res
def _create_samples(self, sector: dict) -> list[dict]: def _create_samples(self,
sector: dict) -> list[dict]:
"""Создает список представленных элементов с их параметрами"""
res = [] res = []
for key, item in sector.items(): for key, item in sector.items():
sample = item[0] if type(item) == list else item sample = item[0] if type(item) == list else item
@ -54,8 +84,11 @@ class ReportSettings(QtWidgets.QWidget):
res.append(param) res.append(param)
return res return res
def _create_settings(self, item: Union[pg.LinearRegionItem, pg.PlotDataItem]) -> list[dict]: def _create_settings(self,
"""Настройки для элемента""" item: Union[pg.LinearRegionItem, pg.PlotDataItem]) -> list[dict]:
"""Получает настройки для элемента"""
if type(item) == pg.LinearRegionItem: if type(item) == pg.LinearRegionItem:
pen = item.lines[0].pen pen = item.lines[0].pen
brush = item.brush brush = item.brush
@ -74,4 +107,63 @@ class ReportSettings(QtWidgets.QWidget):
{'name': 'Fill color', 'type': 'color', 'value': fill_color}, {'name': 'Fill color', 'type': 'color', 'value': fill_color},
] ]
def _update_settings(self,
reg_items: dict,
curve_items: dict,
params: Parameter) -> None:
"""Задает параметры элементов в соответствии с paramTree"""
real_sectors = params.child("Sectors").child("Real sectors")
ideal_sectors = params.child("Sectors").child("Ideal sectors")
real_plots = params.child("Plots").child("Real plots")
ideal_plots = params.child("Plots").child("Ideal plots")
self._set_sector_settings(reg_items["real"], real_sectors)
self._set_sector_settings(reg_items["ideal"], ideal_sectors)
self._set_plot_settings(curve_items["real"], real_plots)
for key, item_dict in curve_items["ideal"].items():
self._set_plot_settings(item_dict, ideal_plots.child(key))
def _set_sector_settings(self,
sectors: dict,
settings: Parameter) -> None:
"""Задает параметры секторов в соответствии с настройками"""
for key, item in sectors.items():
sample = settings.child(key)
line_color = sample.child("Line color").value()
line_width = sample.child("Line thickness").value()
visibility = sample.child("Visibility").value()
fill_color = sample.child("Fill color").value()
pen = pg.mkPen(color=line_color, width=line_width)
brush=pg.mkBrush(fill_color)
for reg in item:
reg.setVisible(visibility)
reg.lines[0].setPen(pen)
reg.lines[1].setPen(pen)
reg.setBrush(brush)
def _set_plot_settings(self,
curves:dict,
settings: Parameter) -> None:
"""Задает параметры кривых в соответствии с настройками"""
for key, item in curves.items():
sample = settings.child(key)
line_color = sample.child("Line color").value()
line_width = sample.child("Line thickness").value()
visibility = sample.child("Visibility").value()
pen = pg.mkPen(color=line_color, width=line_width)
if type(item) == list:
for curve in item:
curve.setVisible(visibility)
curve.setPen(pen)
else:
item.setVisible(visibility)
item.setPen(pen)

View File

@ -1,7 +1,8 @@
from typing import Callable, Optional, Any from typing import Callable, Optional, Any
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (QWidget, QPushButton,
QWidget, QPushButton, QLineEdit, QHBoxLayout, QVBoxLayout, QLabel, QTableWidget, QTableWidgetItem QLineEdit, QHBoxLayout,
) QVBoxLayout, QLabel,
QTableWidget, QTableWidgetItem)
from PyQt5.QtGui import QIntValidator from PyQt5.QtGui import QIntValidator
from utils.json_tools import read_json, write_json from utils.json_tools import read_json, write_json
@ -11,7 +12,6 @@ class settingsWindow(QWidget):
def __init__(self, path: str, name: str, upd_func: Callable[[], None]): def __init__(self, path: str, name: str, upd_func: Callable[[], None]):
""" """
Окно настроек для редактирования параметров. Окно настроек для редактирования параметров.
:param path: Путь к файлу настроек (JSON). :param path: Путь к файлу настроек (JSON).
:param name: Название набора настроек. :param name: Название набора настроек.
:param upd_func: Функция обновления (коллбэк). :param upd_func: Функция обновления (коллбэк).

View File

@ -5,9 +5,8 @@ from typing import Optional, Union, Any
from cachetools import LRUCache from cachetools import LRUCache
import pandas as pd import pandas as pd
from PyQt5.QtCore import QThread, QObject, QTimer from PyQt5.QtCore import QObject, QTimer
from PyQt5.QtWidgets import QWidget, QTabWidget from PyQt5.QtWidgets import QWidget, QTabWidget
from PyQt5.QtOpenGL import QGLWidget
from OptAlgorithm import OptAlgorithm from OptAlgorithm import OptAlgorithm
import numpy as np import numpy as np
import pyqtgraph as pg import pyqtgraph as pg
@ -256,7 +255,9 @@ class BasePlotWidget:
navigator.plot(x_downsampled, y_downsampled, pen=signal["pen"], name=signal["name"]) navigator.plot(x_downsampled, y_downsampled, pen=signal["pen"], name=signal["name"])
ROI_region = pg.LinearRegionItem(values=time_region, movable=True, brush=pg.mkBrush(0, 0, 255, 100)) ROI_region = pg.LinearRegionItem(values=time_region, movable=True, brush=pg.mkBrush(0, 0, 255, 100))
ROI_region.setBounds([0, x.iloc[-1]])
navigator.addItem(ROI_region) navigator.addItem(ROI_region)
navigator.getPlotItem().getViewBox().setLimits(xMin=0, xMax=x.iloc[-1])
# Связываем изменение региона навигатора с обновлением области просмотра основного графика # Связываем изменение региона навигатора с обновлением области просмотра основного графика
ROI_region.sigRegionChanged.connect(lambda: self._sync_main_plot_with_navigator(main_plot, ROI_region)) ROI_region.sigRegionChanged.connect(lambda: self._sync_main_plot_with_navigator(main_plot, ROI_region))