WeldingSpotPerformance/src/gui/plotter.py

177 lines
8.3 KiB
Python
Raw Normal View History

import pandas as pd
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QGraphicsRectItem
import pyqtgraph as pg
import numpy as np
from numpy import floating
from typing import Optional, Any, NamedTuple
from src.utils.base.base import BasePlotWidget
class ProcessStage(NamedTuple):
mean_value: floating[Any]
start_index: int
finish_index: int
class PlotWidget(BasePlotWidget):
def _create_curve_ideal(self,
signal: str,
ideal_data: pd.DataFrame,
start_timestamp: float,
finish_timestamp: float) -> Optional[pg.PlotDataItem]:
if start_timestamp and finish_timestamp:
plot = pg.PlotDataItem(x=start_timestamp+ideal_data["time"], y=ideal_data[signal["name"]], pen=signal["pen"])
return plot
return None
def _create_stage_region(self,
stage: str,
start_timestamp: float,
finish_timestamp: float,
transparency:int) -> Optional[pg.LinearRegionItem]:
if start_timestamp and finish_timestamp:
region = pg.LinearRegionItem([start_timestamp, finish_timestamp], movable=False)
region.setBrush(pg.mkBrush(self._stage_colors[stage][:3] + [transparency]))
return region
return None
@staticmethod
def _init_plot_widget(title: str) -> tuple[pg.PlotWidget, pg.LegendItem]:
plot_widget = pg.PlotWidget(title=title)
plot_widget.showGrid(x=True, y=True)
legend = pg.LegendItem((80, 60), offset=(70, 20))
legend.setParentItem(plot_widget.graphicsItem())
return plot_widget, legend
def get_stage_info(self,
stage: str,
dataframe: pd.DataFrame,
signal_name: str) -> Optional[ProcessStage]:
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, dict, list]) -> QWidget:
widget = QWidget()
layout = QVBoxLayout()
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["performance"]:
TWC_time = 0
ideal_time = 0
for cur_point, (dataframe, ideal_data, events, tesla_time) in enumerate(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]
region = self._create_stage_region(stage, start_t, end_t, 75)
if region:
plot_widget.addItem(region)
if settings["ideals"]:
for i, stage in enumerate(stages):
start_t, _ = events[stage]
end_t = start_t + ideal_data["Ideal timings"][i]
region = self._create_stage_region(stage, start_t, end_t, 125)
if region:
plot_widget.addItem(region)
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"]:
if cur_point == len(data) -1:
ideal_time += sum(ideal_data["Ideal timings"][0:3])
TWC_time += sum([events[stage][1] - events[stage][0] for stage in ["Closing", "Squeeze", "Welding"]])
else:
for stage in stages:
TWC_time += events[stage][1] - events[stage][0]
ideal_time += ideal_data["Ideal cycle"]
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,
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(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")
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(df_continuous["time"], df_continuous[signal["name"]], pen=signal["pen"])
legend.addItem(plot, signal["name"])
if settings["performance"]:
tesla_TWC = round((1 - TWC_time/tesla_time)*100,2)
tesla_ideal = round((1 - ideal_time/tesla_time)*100,2)
TWC_ideal = round((TWC_time/ideal_time - 1)*100,2)
performance_label = QLabel(f"Сокращение длительности: фактическое = {tesla_TWC} %, идеальное = {tesla_ideal} %, разница идеала и факта = {TWC_ideal}%")
layout.addWidget(performance_label)
layout.addWidget(plot_widget)
widget.setLayout(layout)
return widget
def build(self, data: list[pd.DataFrame]) -> None:
widgets = [self._build_widget(data_sample) for data_sample in data]
self._mediator.notify(self, widgets)