2024-11-15 11:36:05 +03:00
|
|
|
from typing import Optional
|
|
|
|
|
|
2024-11-14 13:45:57 +03:00
|
|
|
import pandas as pd
|
|
|
|
|
from PyQt5.QtWidgets import QWidget, QVBoxLayout
|
|
|
|
|
import pyqtgraph as pg
|
2024-11-14 22:49:48 +03:00
|
|
|
import numpy as np
|
2024-11-14 13:45:57 +03:00
|
|
|
|
|
|
|
|
from base.base import BasePlotWidget
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PlotWidget(BasePlotWidget):
|
|
|
|
|
|
2024-11-14 22:49:48 +03:00
|
|
|
def _create_stage_region(self,
|
|
|
|
|
stage: str,
|
|
|
|
|
times: pd.Series,
|
2024-11-15 11:36:05 +03:00
|
|
|
dataframe: pd.DataFrame) -> Optional[pg.LinearRegionItem]:
|
2024-11-14 22:49:48 +03:00
|
|
|
stage_diff = np.diff(dataframe[stage])
|
|
|
|
|
start_index = np.where(stage_diff == 1)[0]
|
|
|
|
|
finish_index = np.where(stage_diff == -1)[0]
|
2024-11-15 12:06:49 +03:00
|
|
|
|
|
|
|
|
if start_index.size:
|
2024-11-15 11:36:05 +03:00
|
|
|
start_timestamp = times[start_index[0]]
|
2024-11-15 12:06:49 +03:00
|
|
|
finish_timestamp = times[finish_index[0]] if finish_index.size else times[len(times) - 1]
|
2024-11-15 11:36:05 +03:00
|
|
|
region = pg.LinearRegionItem([start_timestamp, finish_timestamp], movable=False)
|
|
|
|
|
region.setBrush(pg.mkBrush(self._stage_colors[stage]))
|
|
|
|
|
return region
|
|
|
|
|
return None
|
2024-11-14 22:49:48 +03:00
|
|
|
|
2024-11-15 13:51:26 +03:00
|
|
|
def _find_mid_in_stage(self,
|
|
|
|
|
stage: str,
|
|
|
|
|
dataframe: pd.DataFrame,
|
|
|
|
|
signal_name: str) -> float:
|
|
|
|
|
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 mean
|
|
|
|
|
return 0.0
|
|
|
|
|
|
2024-11-14 22:49:48 +03:00
|
|
|
def _build_widget(self, dataframe: pd.DataFrame) -> QWidget:
|
2024-11-14 13:45:57 +03:00
|
|
|
widget = QWidget()
|
|
|
|
|
layout = QVBoxLayout()
|
|
|
|
|
|
|
|
|
|
time_axis = dataframe["time"]
|
2024-11-14 21:39:44 +03:00
|
|
|
dataframe_headers = dataframe.columns.tolist()
|
2024-11-14 13:45:57 +03:00
|
|
|
|
2024-11-14 21:39:44 +03:00
|
|
|
for channel, description in self._plt_channels.items():
|
2024-11-14 13:45:57 +03:00
|
|
|
plot_widget = pg.PlotWidget(title=channel)
|
|
|
|
|
plot_widget.showGrid(x=True, y=True)
|
|
|
|
|
legend = pg.LegendItem((80, 60), offset=(70, 20))
|
|
|
|
|
legend.setParentItem(plot_widget.graphicsItem())
|
2024-11-14 21:39:44 +03:00
|
|
|
settings = description["Settings"]
|
2024-11-14 13:45:57 +03:00
|
|
|
|
2024-11-14 22:49:48 +03:00
|
|
|
if settings["stages"] and all([stage in dataframe_headers for stage in self._stages]):
|
|
|
|
|
for stage in self._stages:
|
|
|
|
|
region = self._create_stage_region(stage, time_axis, dataframe)
|
2024-11-15 11:36:05 +03:00
|
|
|
if region:
|
|
|
|
|
plot_widget.addItem(region)
|
2024-11-14 22:49:48 +03:00
|
|
|
|
2024-11-15 13:51:26 +03:00
|
|
|
if settings["zoom"] and max(time_axis) < 5.0:
|
|
|
|
|
means_raw = [self._find_mid_in_stage("Welding",
|
|
|
|
|
dataframe,
|
|
|
|
|
signal["name"]) for signal in description["Signals"]]
|
|
|
|
|
mean = max(means_raw)
|
|
|
|
|
region_stable = pg.LinearRegionItem([mean - mean * 0.015,
|
|
|
|
|
mean + mean * 0.015],
|
|
|
|
|
orientation='horizontal')
|
|
|
|
|
region_stable.setBrush(pg.mkBrush([250, 250, 0, 25]))
|
|
|
|
|
plot_widget.addItem(region_stable)
|
|
|
|
|
|
|
|
|
|
region_overshoot = pg.LinearRegionItem([mean - mean * 0.05,
|
|
|
|
|
mean + mean * 0.05],
|
|
|
|
|
orientation='horizontal')
|
|
|
|
|
region_overshoot.setBrush(pg.mkBrush([0, 250, 0, 30]))
|
|
|
|
|
plot_widget.addItem(region_overshoot)
|
|
|
|
|
|
|
|
|
|
plot_widget.setYRange(mean - 260, mean + 260)
|
|
|
|
|
plot_widget.setInteractive(False)
|
|
|
|
|
|
2024-11-14 21:39:44 +03:00
|
|
|
for signal in description["Signals"]:
|
|
|
|
|
if signal["name"] in dataframe_headers:
|
2024-11-14 20:59:21 +03:00
|
|
|
plot = plot_widget.plot(time_axis, dataframe[signal["name"]], pen=signal["pen"])
|
2024-11-14 21:39:44 +03:00
|
|
|
legend.addItem(plot, signal["name"])
|
2024-11-14 13:45:57 +03:00
|
|
|
|
|
|
|
|
layout.addWidget(plot_widget)
|
|
|
|
|
|
|
|
|
|
widget.setLayout(layout)
|
|
|
|
|
return widget
|
|
|
|
|
|
|
|
|
|
def build(self, data: list[pd.DataFrame]) -> None:
|
2024-11-14 22:49:48 +03:00
|
|
|
widgets = [self._build_widget(data_sample) for data_sample in data]
|
2024-11-14 13:45:57 +03:00
|
|
|
self._mediator.notify(self, widgets)
|