import pyqtgraph as pg from pyqtgraph.Qt import QtWidgets import numpy as np from src.gui import qt_settings as qts from src.OptAlgorithm import OptAlgorithm class PlotWindow: def __init__(self, system_config : dict, operator_config: dict, opt: OptAlgorithm, bool_dict: dict, float_dict: dict, show_settings_func): pg.setConfigOptions(antialias=True) self.opt = opt self.bool_dict = bool_dict self.float_dict = float_dict self.scaler = int(system_config['UML_time_scaler']) self.WeldTime = operator_config['time_wielding'] #[sec] self.alpha = 100 #[0-255 прозрачность фона] self._getIdealTimings() self._init_ui() self.settings_button.clicked.connect(show_settings_func) def update_data(self, system_config : dict, operator_config: dict, opt: OptAlgorithm, bool_dict: dict, float_dict: dict): self.opt = opt self.bool_dict = bool_dict self.float_dict = float_dict self.scaler = int(system_config['UML_time_scaler']) self.WeldTime = operator_config['time_wielding'] #[sec] self._getIdealTimings() self._updatePlots() def _init_ui(self): self.widget = QtWidgets.QWidget() layout = QtWidgets.QVBoxLayout() self.widget.setLayout(layout) self.win = pg.GraphicsLayoutWidget(show=True, title="") self.win.resize(1000,600) self.win.setWindowTitle('') layout.addWidget(self.win) self.settings_button = QtWidgets.QPushButton("Show settings") self.settings_button.setFixedWidth(160) layout.addWidget(self.settings_button) self.p11, self.l11 = self._init_graph('Electrode force, closure', 'Force', 'N', 'Time', 'ms') #self.p21, _ = self._init_graph('Electrode force, compression', 'Force', 'N', 'Time', 'ms') #self.p31, _ = self._init_graph('Electrode force, compression', 'Force', 'N', 'Time', 'ms') self.win.nextRow() self.p12, self.l12 = self._init_graph('Rotor Position, closure', 'Posicion', 'mm', 'Time', 'ms') #self.p22, _ = self._init_graph('Rotor Position, compression', 'Posicion', 'mm', 'Time', 'ms') #self.p32, _ = self._init_graph('Rotor Position, compression', 'Posicion', 'mm', 'Time', 'ms') self.win.nextRow() self.p13, self.l13 = self._init_graph('Rotor Speed, closure', 'Speed', 'mm/s', 'Time', 'ms') #self.p23, _ = self._init_graph('Rotor Speed, compression', 'Speed', 'mm/s', 'Time', 'ms') #self.p33, _ = self._init_graph('Rotor Speed, compression', 'Speed', 'mm/s', 'Time', 'ms') self.win.nextRow() self.p12.setXLink(self.p11) self.p13.setXLink(self.p11) self.p11.setAutoVisible(x=False, y=True) self.p12.setAutoVisible(x=False, y=True) self.p13.setAutoVisible(x=False, y=True) self._updatePlots() self.widget.setStyleSheet(qts.dark_style) self.widget.show() def _init_graph(self, title, Yname, Yunits, Xname, Xunits): plot = self.win.addPlot(title = title) plot.showGrid(x=True, y=True) plot.setLabel('left', Yname, units=Yunits) plot.setLabel('bottom', Xname, units=Xunits) legend1 = pg.LegendItem((80,60), offset=(70,20)) legend1.setParentItem(plot) return plot, legend1 def _updatePlots(self): self.p11.clear() self.l11.clear() self.p12.clear() self.l12.clear() self.p13.clear() self.l13.clear() self._plotRealData() times = np.arange(20000)/10 self._plotIdealData(times) def _getIdealTimings(self): data = self.opt.Ts self.idealTime = [data['tclose'], data['tgrow'], self.opt.getMarkOpen(), data["tmovement"]] def _form_idealdatGraph(self, times): self.idealPhase0 = (self.idealTime[0])*self.scaler #Подъезд self.idealPhase1 = (self.idealTime[0]+ self.idealTime[1])*self.scaler #Сжатие self.idealPhase2 = (self.idealTime[0]+ self.idealTime[1] + self.WeldTime)*self.scaler #Сварка self.idealPhase3 = (self.idealTime[0]+ self.idealTime[1] + self.idealTime[2] + self.WeldTime)*self.scaler #Разъезд self.idealPhase4 = (sum(self.idealTime[:4]) + self.WeldTime)*self.scaler #Последнее смыкание #TODO добавить идеальное время вместо 0.25 self.x_splitter = np.array([[0, self.idealPhase0], [self.idealPhase0, self.idealPhase1], [self.idealPhase1, self.idealPhase2], [self.idealPhase2, self.idealPhase3], [self.idealPhase3, self.idealPhase4]]) data = [] for time in times: if time <= self.idealPhase0: x_fe, x_me, v_fe, v_me, f = self.opt.calcPhaseClose(time/self.scaler) elif time <= self.idealPhase1: x_fe, x_me, v_fe, v_me, f = self.opt.calcPhaseGrow(time/self.scaler-self.idealTime[0]) elif time <= self.idealPhase2: x_fe, x_me, v_fe, v_me, f = data[-1] elif time <= self.idealPhase3: x_fe, x_me, v_fe, v_me, f = self.opt.calcPhaseOpen(time/self.scaler-self.idealTime[0]-self.idealTime[1]-self.WeldTime) else: x_fe, x_me, v_fe, v_me, f = self.opt.calcPhaseMovement(time/self.scaler-sum(self.idealTime[:3])-self.WeldTime) data.append([x_fe, x_me, v_fe, v_me, f]) data = np.array(data).T return data def _plotRealData(self): for i, (key, dat) in enumerate(self.float_dict.items()): dat = np.array(dat).T dat[0] = dat[0]*self.scaler curve = pg.PlotDataItem(dat[0], dat[1], pen=pg.mkPen(color=qts.colors[i], width=2), name=key, autoDownsample=True, downsample=True) if 'Electrode Force' in key: self.p11.addItem(curve) self.l11.addItem(curve, key) elif 'Rotor Position' in key: self.p12.addItem(curve) self.l12.addItem(curve, key) elif 'Rotor Speed' in key: self.p13.addItem(curve) self.l13.addItem(curve, key) return dat[0] def _plotIdealData(self, times): data = self._form_idealdatGraph(times) x_fe = pg.PlotDataItem(times, data[0]*1000, pen=pg.mkPen(color=qts.colors[8], width=2), name='x_fe', autoDownsample=True, downsample=True) x_me = pg.PlotDataItem(times, data[1]*1000, pen=pg.mkPen(color=qts.colors[9], width=2), name='x_me', autoDownsample=True, downsample=True) v_fe = pg.PlotDataItem(times, data[2]*1000, pen=pg.mkPen(color=qts.colors[8], width=2), name='v_fe', autoDownsample=True, downsample=True) v_me = pg.PlotDataItem(times, data[3]*1000, pen=pg.mkPen(color=qts.colors[9], width=2), name='v_me', autoDownsample=True, downsample=True) f = pg.PlotDataItem(times, data[4], pen=pg.mkPen(color=qts.colors[8], width=2), name='f', autoDownsample=True, downsample=True) self.p11.addItem(f) self.l11.addItem(f, 'Ideal force') self.p12.addItem(x_fe) self.l12.addItem(x_fe, 'FE POS') self.p12.addItem(x_me) self.l12.addItem(x_me, 'ME POS') self.p13.addItem(v_fe) self.l13.addItem(v_fe, 'FE VEL') self.p13.addItem(v_me) self.l13.addItem(v_me, 'ME VEL') self._addBackgroundSplitter() self._addEquidistances(times, data) def _addBackgroundSplitter(self): alpha = self.alpha y01 = np.array([10000, 10000]) y0_1 = np.array([-10000, -10000]) for i, _ in enumerate(self.x_splitter): a01 = pg.PlotDataItem(_, y01, pen=pg.mkPen(color=qts.colors[8], width=2), name=' ') a0_1 = pg.PlotDataItem(_, y0_1, pen=pg.mkPen(color=qts.colors[8], width=2), name=' ') bg1 = pg.FillBetweenItem(a01, a0_1, qts.RGBA[i]+(alpha,)) bg2 = pg.FillBetweenItem(a01, a0_1, qts.RGBA[i]+(alpha,)) bg3 = pg.FillBetweenItem(a01, a0_1, qts.RGBA[i]+(alpha,)) self.p11.addItem(bg1) self.p12.addItem(bg2) self.p13.addItem(bg3) self.p11.setYRange(-1000, 5000) self.p12.setYRange(-50, 250) self.p13.setYRange(-400, 400) def _addEquidistances(self, times, data): a1, b1, c1 = self._calculate_equidistant('fill', max(data[4]), 2.5, self.x_splitter[1], 3) self.p11.addItem(a1) self.p11.addItem(b1) self.p11.addItem(c1) a1, b1, c1 = self._calculate_equidistant(times, data[4], 0.75, self.x_splitter[2], 3) self.p11.addItem(a1) self.p11.addItem(b1) self.p11.addItem(c1) def _makeFiller(self, x1, y1, x2, y2, color): alpha = self.alpha eq1 = pg.PlotDataItem(x1, y1, pen=pg.mkPen(color='#000000', width=1)) eq2 = pg.PlotDataItem(x2, y2, pen=pg.mkPen(color='#000000', width=1)) bg = pg.FillBetweenItem(eq1, eq2, qts.RGBA[color]+(alpha,)) return eq1, eq2, bg def _calculate_equidistant(self, x, y, percent, splitter, color): if str(x) == 'fill': x = [splitter[0]+0.001, splitter[0]+0.002, splitter[1]-0.002, splitter[1]-0.001] y = [y, y, y, y] if len(x) != len(y): raise ValueError("x и y должны быть одного размера") distance = max(y)/100*percent x_eq1 = [] y_eq1 = [] x_eq2 = [] y_eq2 = [] for i in range(0, len(x) - 1): if splitter[0]<= x[i] and x[i] <= splitter[1]: dx = x[i + 1] - x[i] dy = y[i + 1] - y[i] length = np.sqrt(dx ** 2 + dy ** 2) sinA = dy/length sinB = dx/length nx = -sinA*distance ny = sinB*distance x_eq1.append(x[i] + nx) y_eq1.append(y[i] + ny) x_eq2.append(x[i] - nx) y_eq2.append(y[i] - ny) return self._makeFiller(np.array(x_eq1), np.array(y_eq1), np.array(x_eq2), np.array(y_eq2), color)