From 1ece32a57c053ad714c455e981c35b571a90e0f4 Mon Sep 17 00:00:00 2001 From: andrei Date: Fri, 8 Nov 2024 10:50:18 +0300 Subject: [PATCH] =?UTF-8?q?dev:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D1=8D=D0=BA=D0=B2=D0=B8=D0=B4=D0=B8=D1=81?= =?UTF-8?q?=D1=82=D0=B0=D0=BD=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- params/operator_params.json | 2 +- params/system_params.json | 3 +- src/gui/__init__.py | 2 +- src/gui/plot_window.py | 355 ++++++++++++++---------- src/gui/qt_settings.py | 509 ++++++++++++++++++----------------- src/main.py | 87 +++--- src/uml/__init__.py | 2 +- src/uml/creator.py | 198 +++++++------- src/uml/request_generator.py | 198 +++++++------- src/utils/__init__.py | 2 +- src/utils/diagram_parser.py | 108 ++++---- src/utils/json_tools.py | 22 +- 12 files changed, 777 insertions(+), 711 deletions(-) diff --git a/params/operator_params.json b/params/operator_params.json index fcb6da4..47ac1ec 100644 --- a/params/operator_params.json +++ b/params/operator_params.json @@ -7,7 +7,7 @@ "dist_open_end_2" : 0.050, "dist_close_end_1" : 0.005, "dist_close_end_2" : 0.005, - "time_wielding" : 2, + "time_wielding" : 1, "time_command" : 0.060, "time_robot_movement" : 0.2, "object_thickness" : 4.5e-3, diff --git a/params/system_params.json b/params/system_params.json index 9ffc926..bf23a5d 100644 --- a/params/system_params.json +++ b/params/system_params.json @@ -14,5 +14,6 @@ "position_start_1" : 0.080, "position_start_2" : 0.080, "k_prop" : 0.05, - "time_capture" : 100000 + "time_capture" : 100000, + "UML_time_scaler": 1000 } diff --git a/src/gui/__init__.py b/src/gui/__init__.py index 76af526..2e2d808 100644 --- a/src/gui/__init__.py +++ b/src/gui/__init__.py @@ -1 +1 @@ -from .plot_window import PlotWindow +from .plot_window import PlotWindow diff --git a/src/gui/plot_window.py b/src/gui/plot_window.py index 6634a01..3a7e244 100644 --- a/src/gui/plot_window.py +++ b/src/gui/plot_window.py @@ -1,148 +1,207 @@ -import pyqtgraph as pg -import numpy as np - -from src.gui import qt_settings as qts -from src.OptAlgorithm import OptAlgorithm - - -class PlotWindow: - def __init__(self, - opt: OptAlgorithm, - bool_dict: dict, - float_dict: dict): - pg.setConfigOptions(antialias=True) - self.opt = opt - self.bool_dict = bool_dict - self.float_dict = float_dict - - self.scaler = 1000 - self._getIdealTimings() - self._init_app() - self.WeldTime = 1.0 #[sec] # TODO: to external config - self.alpha = 100 #[0-255 прозрачность фона] - - def _init_app(self): - self.app = pg.mkQApp("Plotting") - self.win = pg.GraphicsLayoutWidget(show=True, title="") - self.win.resize(1000,600) - self.win.setWindowTitle('') - - 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) - - def _init_graph(self, title, Yname, Yunits, Xname, Xunits): - p11 = self.win.addPlot(title = title) - p11.showGrid(x=True, y=True) - p11.setLabel('left', Yname, units=Yunits) - p11.setLabel('bottom', Xname, units=Xunits) - legend1 = pg.LegendItem((80,60), offset=(70,20)) - legend1.setParentItem(p11) - return p11, legend1 - - def updatePlots(self): - 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()] - - 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 #Разъезд - 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 = 0, 0, 0, 0, 0 - 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() - - def _addBackgroundSplitter(self): - alpha = self.alpha - x = [[0, self.idealPhase0], - [self.idealPhase0, self.idealPhase1], - [self.idealPhase1, self.idealPhase2], - [self.idealPhase2, self.idealPhase3]] - y01 = [10000, 10000] - y0_1 = [-10000, -10000] - for i, _ in enumerate(x): - 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) \ No newline at end of file +import pyqtgraph as pg +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): + 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._getIdealTimings() + self._init_app() + self.alpha = 100 #[0-255 прозрачность фона] + + def _init_app(self): + self.app = pg.mkQApp("Plotting") + self.win = pg.GraphicsLayoutWidget(show=True, title="") + self.win.resize(1000,600) + self.win.setWindowTitle('') + + 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) + + def _init_graph(self, title, Yname, Yunits, Xname, Xunits): + p11 = self.win.addPlot(title = title) + p11.showGrid(x=True, y=True) + p11.setLabel('left', Yname, units=Yunits) + p11.setLabel('bottom', Xname, units=Xunits) + legend1 = pg.LegendItem((80,60), offset=(70,20)) + legend1.setParentItem(p11) + return p11, legend1 + + def updatePlots(self): + 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()] + + 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 = (self.idealTime[0]+ self.idealTime[1] + self.idealTime[2] + self.WeldTime + 0.25)*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 = 0, 0, 0, 0, 0 + 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=2)) + eq2 = pg.PlotDataItem(x2, y2, pen=pg.mkPen(color='#000000', width=2)) + 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) \ No newline at end of file diff --git a/src/gui/qt_settings.py b/src/gui/qt_settings.py index 18f4327..928f9f0 100644 --- a/src/gui/qt_settings.py +++ b/src/gui/qt_settings.py @@ -1,255 +1,256 @@ -white_style = """ -QMainWindow { - background-color: #ffffff; - font-family: "Segoe UI", sans-serif; - font-size: 14px; -} -QMessageBox { - background-color: #ffffff; - font-family: "Segoe UI", sans-serif; - font-size: 14px; -} -QPushButton { - background-color: #d3d3d3; - color: #000000; - padding: 10px 20px; - border: none; - border-radius: 4px; - font-family: "Segoe UI", sans-serif; - font-size: 14px; -} -QPushButton:hover:!disabled { - background-color: #b0b0b0; -} -QPushButton:disabled { - background-color: #a9a9a9; - color: #7f7f7f; -} -QCheckBox { - color: #000000; - font-size: 14px; - font-family: "Segoe UI", sans-serif; -} -QLineEdit { - background-color: #f0f0f0; - color: #000000; - padding: 5px; - border: 1px solid #a9a9a9; - border-radius: 4px; - font-family: "Segoe UI", sans-serif; - font-size: 14px; -} -QLabel { - color: #000000; - font-size: 16px; - font-family: "Segoe UI", sans-serif; -} -QGroupBox { - color: #000000; - font-family: "Segoe UI", sans-serif; - font-size: 14px; -} -QRadioButton { - color: #000000; - font-family: "Segoe UI", sans-serif; - font-size: 14px; -} -""" - -dark_style = """ -QMainWindow { - background-color: #0D1117; /* Тёмный, современный цвет для фона */ - font-family: "Segoe UI", sans-serif; - font-size: 14px; -} -QMessageBox { - background-color: #161B22; - font-family: "Segoe UI", sans-serif; - font-size: 14px; -} -QPushButton { - background-color: #FFCC00; /* Яркий жёлтый цвет для акцента */ - color: #0D1117; /* Темный цвет текста для контраста с желтым */ - padding: 12px 25px; - border: 2px solid #E6B800; - border-radius: 8px; - font-family: "Segoe UI", sans-serif; - font-size: 16px; - font-weight: bold; -} -QPushButton:hover:!disabled { - background-color: #FFD700; /* Светлый желтый цвет для эффекта наведения */ -} -QPushButton:disabled { - background-color: #555555; - color: #cccccc; - border: none; -} -QCheckBox { - color: #ffffff; - font-size: 14px; - font-family: "Segoe UI", sans-serif; - font-weight: bold; -} -QLineEdit { - background-color: #21262D; - color: #ffffff; - padding: 8px; - border: 2px solid #30363D; - border-radius: 6px; - font-family: "Segoe UI", sans-serif; - font-size: 16px; - font-weight: bold; -} -QLabel { - color: #ffffff; - font-size: 16px; - font-weight: bold; - font-family: "Segoe UI", sans-serif; -} -QGroupBox { - color: #ffffff; - font-family: "Segoe UI", sans-serif; - font-size: 16px; - font-weight: bold; - border: 1px solid #30363D; - border-radius: 6px; - margin-top: 10px; -} -QRadioButton { - color: #ffffff; - font-family: "Segoe UI", sans-serif; - font-size: 16px; - font-weight: bold; -} -QSpinBox { - font-family: "Segoe UI", sans-serif; - font-size: 16px; - font-weight: bold; -} -QDoubleSpinBox { - font-family: "Segoe UI", sans-serif; - font-size: 16px; - font-weight: bold; -} -""" - -dis_robots = """ -QPushButton { - background-color: #555555; - color: #cccccc; - padding: 12px 25px; - border: none; - border-radius: 8px; - font-family: "Segoe UI", sans-serif; - font-size: 16px; -} -QWidget#robot { - border: none; - padding: 5px; - background-color: rgba(33, 33, 33, 100); -} -""" - -selected_robot = """ -QWidget#robot { - border: 2px solid #E6B800; - border-radius: 10px; - padding: 5px; -} -""" - - - -en_button = """ -QPushButton { - background-color: #FFCC00; - color: #0D1117; - padding: 12px 25px; - border: 2px solid #E6B800; - border-radius: 8px; - font-family: "Segoe UI", sans-serif; - font-size: 16px; - font-weight: bold; -} -QPushButton:hover:!disabled { - background-color: #FFD700; -} -""" - - -dis_button = """ -QPushButton { - background-color: #555555; - color: #cccccc; - padding: 12px 25px; - border: none; - border-radius: 8px; - font-family: "Segoe UI", sans-serif; - font-size: 16px; -} -""" - - -saved_button = """ -QPushButton { - background-color: #28a745; - color: #ffffff; - padding: 12px 25px; - border: none; - border-radius: 8px; - font-family: "Segoe UI", sans-serif; - font-size: 16px; - font-weight: bold; -} -""" - - - -start_button = """ -QPushButton { - background-color: #FFCC00; - color: #0D1117; - padding: 20px 40px; - border: 2px solid #E6B800; - border-radius: 10px; - font-family: "Segoe UI", sans-serif; - font-size: 24px; - font-weight: bold; - background-image: linear-gradient(to bottom, #FFD700, #FFCC00); -} -QPushButton:hover:!disabled { - background-color: #FFD700; -} -QPushButton:pressed { - background-color: #E6B800; - padding-top: 22px; - padding-bottom: 18px; -} -QPushButton:disabled { - background-color: #555555; - color: #cccccc; - border: none; -} - -""" - - -colors = [ - '#FF6F61', # яркий коралловый - '#6B5B95', # приглушенный фиолетовый - '#88B04B', # яркий зеленый - '#F7CAC9', # светлый розовый - '#92A8D1', # светло-голубой - '#955251', # теплый терракотовый - '#B565A7', # лавандовый - '#009B77', # глубокий бирюзовый - '#DD4124', # ярко-красный - '#45B8AC' # мягкий мятный -] - -RGBA = [(255, 255, 0), - (32, 178, 70), - (255, 69, 0), - (123, 104, 238) +white_style = """ +QMainWindow { + background-color: #ffffff; + font-family: "Segoe UI", sans-serif; + font-size: 14px; +} +QMessageBox { + background-color: #ffffff; + font-family: "Segoe UI", sans-serif; + font-size: 14px; +} +QPushButton { + background-color: #d3d3d3; + color: #000000; + padding: 10px 20px; + border: none; + border-radius: 4px; + font-family: "Segoe UI", sans-serif; + font-size: 14px; +} +QPushButton:hover:!disabled { + background-color: #b0b0b0; +} +QPushButton:disabled { + background-color: #a9a9a9; + color: #7f7f7f; +} +QCheckBox { + color: #000000; + font-size: 14px; + font-family: "Segoe UI", sans-serif; +} +QLineEdit { + background-color: #f0f0f0; + color: #000000; + padding: 5px; + border: 1px solid #a9a9a9; + border-radius: 4px; + font-family: "Segoe UI", sans-serif; + font-size: 14px; +} +QLabel { + color: #000000; + font-size: 16px; + font-family: "Segoe UI", sans-serif; +} +QGroupBox { + color: #000000; + font-family: "Segoe UI", sans-serif; + font-size: 14px; +} +QRadioButton { + color: #000000; + font-family: "Segoe UI", sans-serif; + font-size: 14px; +} +""" + +dark_style = """ +QMainWindow { + background-color: #0D1117; /* Тёмный, современный цвет для фона */ + font-family: "Segoe UI", sans-serif; + font-size: 14px; +} +QMessageBox { + background-color: #161B22; + font-family: "Segoe UI", sans-serif; + font-size: 14px; +} +QPushButton { + background-color: #FFCC00; /* Яркий жёлтый цвет для акцента */ + color: #0D1117; /* Темный цвет текста для контраста с желтым */ + padding: 12px 25px; + border: 2px solid #E6B800; + border-radius: 8px; + font-family: "Segoe UI", sans-serif; + font-size: 16px; + font-weight: bold; +} +QPushButton:hover:!disabled { + background-color: #FFD700; /* Светлый желтый цвет для эффекта наведения */ +} +QPushButton:disabled { + background-color: #555555; + color: #cccccc; + border: none; +} +QCheckBox { + color: #ffffff; + font-size: 14px; + font-family: "Segoe UI", sans-serif; + font-weight: bold; +} +QLineEdit { + background-color: #21262D; + color: #ffffff; + padding: 8px; + border: 2px solid #30363D; + border-radius: 6px; + font-family: "Segoe UI", sans-serif; + font-size: 16px; + font-weight: bold; +} +QLabel { + color: #ffffff; + font-size: 16px; + font-weight: bold; + font-family: "Segoe UI", sans-serif; +} +QGroupBox { + color: #ffffff; + font-family: "Segoe UI", sans-serif; + font-size: 16px; + font-weight: bold; + border: 1px solid #30363D; + border-radius: 6px; + margin-top: 10px; +} +QRadioButton { + color: #ffffff; + font-family: "Segoe UI", sans-serif; + font-size: 16px; + font-weight: bold; +} +QSpinBox { + font-family: "Segoe UI", sans-serif; + font-size: 16px; + font-weight: bold; +} +QDoubleSpinBox { + font-family: "Segoe UI", sans-serif; + font-size: 16px; + font-weight: bold; +} +""" + +dis_robots = """ +QPushButton { + background-color: #555555; + color: #cccccc; + padding: 12px 25px; + border: none; + border-radius: 8px; + font-family: "Segoe UI", sans-serif; + font-size: 16px; +} +QWidget#robot { + border: none; + padding: 5px; + background-color: rgba(33, 33, 33, 100); +} +""" + +selected_robot = """ +QWidget#robot { + border: 2px solid #E6B800; + border-radius: 10px; + padding: 5px; +} +""" + + + +en_button = """ +QPushButton { + background-color: #FFCC00; + color: #0D1117; + padding: 12px 25px; + border: 2px solid #E6B800; + border-radius: 8px; + font-family: "Segoe UI", sans-serif; + font-size: 16px; + font-weight: bold; +} +QPushButton:hover:!disabled { + background-color: #FFD700; +} +""" + + +dis_button = """ +QPushButton { + background-color: #555555; + color: #cccccc; + padding: 12px 25px; + border: none; + border-radius: 8px; + font-family: "Segoe UI", sans-serif; + font-size: 16px; +} +""" + + +saved_button = """ +QPushButton { + background-color: #28a745; + color: #ffffff; + padding: 12px 25px; + border: none; + border-radius: 8px; + font-family: "Segoe UI", sans-serif; + font-size: 16px; + font-weight: bold; +} +""" + + + +start_button = """ +QPushButton { + background-color: #FFCC00; + color: #0D1117; + padding: 20px 40px; + border: 2px solid #E6B800; + border-radius: 10px; + font-family: "Segoe UI", sans-serif; + font-size: 24px; + font-weight: bold; + background-image: linear-gradient(to bottom, #FFD700, #FFCC00); +} +QPushButton:hover:!disabled { + background-color: #FFD700; +} +QPushButton:pressed { + background-color: #E6B800; + padding-top: 22px; + padding-bottom: 18px; +} +QPushButton:disabled { + background-color: #555555; + color: #cccccc; + border: none; +} + +""" + + +colors = [ + '#FF6F61', # яркий коралловый + '#6B5B95', # приглушенный фиолетовый + '#88B04B', # яркий зеленый + '#F7CAC9', # светлый розовый + '#92A8D1', # светло-голубой + '#955251', # теплый терракотовый + '#B565A7', # лавандовый + '#009B77', # глубокий бирюзовый + '#DD4124', # ярко-красный + '#45B8AC' # мягкий мятный +] + +RGBA = [(255, 255, 0), + (32, 178, 70), + (255, 69, 0), + (123, 104, 238), + (99, 42, 15) ] \ No newline at end of file diff --git a/src/main.py b/src/main.py index 41a1242..a782bec 100644 --- a/src/main.py +++ b/src/main.py @@ -1,42 +1,45 @@ -import pyqtgraph as pg - -from utils import read_json, DiagramParser -from uml import Request, UMLCreator -from OptAlgorithm import OptAlgorithm -from gui import PlotWindow - - -def get_ideal_timings(opt: OptAlgorithm) -> list[float]: - data = opt.Ts - ideal_time = [data['tclose'], data['tgrow'], opt.getMarkOpen()] - return ideal_time - - -def main(): - operator_params = read_json("params/operator_params.json") - system_params = read_json("params/system_params.json") - opt_algorithm = OptAlgorithm(operator_config=operator_params, system_config=system_params) - ideal_times = get_ideal_timings(opt_algorithm) - - parser = DiagramParser() - parser.setData("trace_samples/2024_11_01-09_39_17B00.csv") - bool_dict = parser.getBoolDict() - float_dict = parser.getFloatDict() - - request_generator = Request(server_url='http://www.plantuml.com/plantuml/svg/') - uml_creator = UMLCreator(request_generator=request_generator, - ideal_time=ideal_times, - bool_dict=bool_dict, - float_dict=float_dict) - uml_creator.update_uml() - - app = PlotWindow(opt=opt_algorithm, - bool_dict=bool_dict, - float_dict=float_dict) - - app.updatePlots() - pg.exec() - - -if __name__ == '__main__': - main() +import pyqtgraph as pg + +from src.utils import read_json, DiagramParser +from src.uml import Request, UMLCreator +from src.OptAlgorithm import OptAlgorithm +from src.gui import PlotWindow + + +def get_ideal_timings(opt: OptAlgorithm) -> list[float]: + data = opt.Ts + ideal_time = [data['tclose'], data['tgrow'], opt.getMarkOpen()] + return ideal_time + + +def main(): + operator_params = read_json("params/operator_params.json") + system_params = read_json("params/system_params.json") + opt_algorithm = OptAlgorithm(operator_config=operator_params, system_config=system_params) + ideal_times = get_ideal_timings(opt_algorithm) + + parser = DiagramParser() + parser.setData("trace_samples/2024_11_01-09_39_17B00.csv") + bool_dict = parser.getBoolDict() + float_dict = parser.getFloatDict() + + request_generator = Request(server_url='http://www.plantuml.com/plantuml/svg/') + uml_creator = UMLCreator(system_config=system_params, + request_generator=request_generator, + ideal_time=ideal_times, + bool_dict=bool_dict, + float_dict=float_dict) + uml_creator.update_uml() + + app = PlotWindow(operator_config=operator_params, + system_config=system_params, + opt=opt_algorithm, + bool_dict=bool_dict, + float_dict=float_dict) + + app.updatePlots() + pg.exec() + + +if __name__ == '__main__': + main() diff --git a/src/uml/__init__.py b/src/uml/__init__.py index a275da1..4ff3af1 100644 --- a/src/uml/__init__.py +++ b/src/uml/__init__.py @@ -1,2 +1,2 @@ -from .request_generator import Request +from .request_generator import Request from .creator import UMLCreator \ No newline at end of file diff --git a/src/uml/creator.py b/src/uml/creator.py index bdc093d..e3d43ff 100644 --- a/src/uml/creator.py +++ b/src/uml/creator.py @@ -1,98 +1,100 @@ -from src.uml.request_generator import Request - - -class UMLCreator: - def __init__(self, - request_generator: Request, - ideal_time: list[float], - bool_dict: dict, - float_dict: dict): - self._request_generator = request_generator - self._ideal_time = ideal_time - self.bool_dict = bool_dict - self.float_dict = float_dict - - def _build_data(self): - scaler = 1000 # TODO: external config? - sig = [ - 'Electrode Closing Algorithm Execute', # Начало закрытия - 'Electrode Closing Algorithm Done', - # 'STEP 3: ME Hold P2 AND Condition Start Force Control', # Конец закрытия и Начало набора усилия - 'STEP 4: ME Force Control', - 'Position Control ME', # Начало разъезда или 'Posision Control Activated FE' - 'Position Control FE', # Начало разъезда - 'Position Control Completed ME', # Конец разъезда - 'Position Control Completed FE', # Конец разъезда - 'STEP 4: ME Force Control Complete', # Конец набора усилия - ] - closure = self._get_time([sig[0], sig[1]]) - compression = self._get_time([sig[2], sig[3]]) - # opening = self.__getTime([sig[4], sig[5], sig[6], sig[7]]) - - real_data = [ - [closure[0], 'closure #green'], - [closure[1], '{-}'], - [compression[0], 'compression #green'], - [compression[1], '{-}'], - # [max(opening[0:2]), 'opening #green'], - # [max(opening[2:4]), '{-}'], - ] - - client_data = [ - [0.0 * scaler, 'closure'], - [0.165 * scaler, '{-}'], - [0.166 * scaler, 'compression'], - [0.176 * scaler, '{-}'], - # [0.180*scaler, 'welding'], - # [0.200*scaler, '{-}'], - [0.210 * scaler, 'opening'], - [0.300 * scaler, '{-}'], - ] - - ideal_data = [ - [0.0 * scaler, 'closure #yellow'], - [self._ideal_time[0] * scaler, '{-}'], - [(self._ideal_time[0] + 0.0001) * scaler, 'compression #yellow'], - [(self._ideal_time[0] + self._ideal_time[1]) * scaler, '{-}'], - # [0.*scaler, 'welding #yellow'], - # [0.*scaler, '{-}'], - [(self._ideal_time[0] + self._ideal_time[1] + 0.0001) * scaler, 'opening #yellow'], - [(self._ideal_time[0] + self._ideal_time[1] + self._ideal_time[2]) * scaler, '{-}'], - ] - return real_data, client_data, ideal_data, self.bool_dict - - def _get_time(self, signals = '', states = ''): - res = [] - for i, sig in enumerate(signals): - if states: state = states[i] - else: state = 'high' - index1 = next ((i for i, _ in enumerate(self.bool_dict[sig]) if _[1]==state), -1) - time = self.bool_dict[sig][index1][0] - res.append(time) - return res - - def _generate_svg(self, real_data, client_data, ideal_data, bool_data) -> None: - try: - self._request_generator.clear() - self._request_generator.addLineStyle('biba', 'red', 2) - - for i, [signal, changes] in enumerate(bool_data.items()): - name = 'bool_' + str(i) - self._request_generator.addBinary(name, str(signal), 'biba') - self._request_generator.setTimestamps(name, changes) - - self._request_generator.addConcise('RD', 'Real data') - self._request_generator.setTimestamps('RD', real_data) - self._request_generator.addConcise('CD', 'Client data') - self._request_generator.setTimestamps('CD', client_data) - self._request_generator.addConcise('ID', 'Ideal data') - self._request_generator.setTimestamps('ID', ideal_data) - - self._request_generator.generateSVG() - - except Exception as e: - print(f"SVG generate error: {e}") - - def update_uml(self) -> None: - real, client, ideal, bool_ = self._build_data() - self._generate_svg(real, client, ideal, bool_) +from src.uml.request_generator import Request + + +class UMLCreator: + def __init__(self, + system_config : dict, + request_generator: Request, + ideal_time: list[float], + bool_dict: dict, + float_dict: dict): + self._request_generator = request_generator + self._ideal_time = ideal_time + self.bool_dict = bool_dict + self.float_dict = float_dict + self.scaler = int(system_config['UML_time_scaler']) + + + def _build_data(self): + sig = [ + 'Electrode Closing Algorithm Execute', # Начало закрытия + 'Electrode Closing Algorithm Done', + # 'STEP 3: ME Hold P2 AND Condition Start Force Control', # Конец закрытия и Начало набора усилия + 'STEP 4: ME Force Control', + 'Position Control ME', # Начало разъезда или 'Posision Control Activated FE' + 'Position Control FE', # Начало разъезда + 'Position Control Completed ME', # Конец разъезда + 'Position Control Completed FE', # Конец разъезда + 'STEP 4: ME Force Control Complete', # Конец набора усилия + ] + closure = self._get_time([sig[0], sig[1]]) + compression = self._get_time([sig[2], sig[3]]) + # opening = self.__getTime([sig[4], sig[5], sig[6], sig[7]]) + + real_data = [ + [closure[0], 'closure #green'], + [closure[1], '{-}'], + [compression[0], 'compression #green'], + [compression[1], '{-}'], + # [max(opening[0:2]), 'opening #green'], + # [max(opening[2:4]), '{-}'], + ] + + client_data = [ + [0.0 * self.scaler, 'closure'], + [0.165 * self.scaler, '{-}'], + [0.166 * self.scaler, 'compression'], + [0.176 * self.scaler, '{-}'], + # [0.180*self.scaler, 'welding'], + # [0.200*self.scaler, '{-}'], + [0.210 * self.scaler, 'opening'], + [0.300 * self.scaler, '{-}'], + ] + + ideal_data = [ + [0.0 * self.scaler, 'closure #yellow'], + [self._ideal_time[0] * self.scaler, '{-}'], + [(self._ideal_time[0] + 0.0001) * self.scaler, 'compression #yellow'], + [(self._ideal_time[0] + self._ideal_time[1]) * self.scaler, '{-}'], + # [0.*self.scaler, 'welding #yellow'], + # [0.*self.scaler, '{-}'], + [(self._ideal_time[0] + self._ideal_time[1] + 0.0001) * self.scaler, 'opening #yellow'], + [(self._ideal_time[0] + self._ideal_time[1] + self._ideal_time[2]) * self.scaler, '{-}'], + ] + return real_data, client_data, ideal_data, self.bool_dict + + def _get_time(self, signals = '', states = ''): + res = [] + for i, sig in enumerate(signals): + if states: state = states[i] + else: state = 'high' + index1 = next ((i for i, _ in enumerate(self.bool_dict[sig]) if _[1]==state), -1) + time = self.bool_dict[sig][index1][0] + res.append(time) + return res + + def _generate_svg(self, real_data, client_data, ideal_data, bool_data) -> None: + try: + self._request_generator.clear() + self._request_generator.addLineStyle('biba', 'red', 2) + + for i, [signal, changes] in enumerate(bool_data.items()): + name = 'bool_' + str(i) + self._request_generator.addBinary(name, str(signal), 'biba') + self._request_generator.setTimestamps(name, changes) + + self._request_generator.addConcise('RD', 'Real data') + self._request_generator.setTimestamps('RD', real_data) + self._request_generator.addConcise('CD', 'Client data') + self._request_generator.setTimestamps('CD', client_data) + self._request_generator.addConcise('ID', 'Ideal data') + self._request_generator.setTimestamps('ID', ideal_data) + + self._request_generator.generateSVG() + + except Exception as e: + print(f"SVG generate error: {e}") + + def update_uml(self) -> None: + real, client, ideal, bool_ = self._build_data() + self._generate_svg(real, client, ideal, bool_) diff --git a/src/uml/request_generator.py b/src/uml/request_generator.py index 8e89bbc..a470f25 100644 --- a/src/uml/request_generator.py +++ b/src/uml/request_generator.py @@ -1,99 +1,99 @@ -from plantuml import PlantUML -from os.path import abspath - - -class Request: - def __init__(self, server_url: str): - self._server_url = server_url - - self._init_server() - - def _init_server(self): - self.server = PlantUML(url=self._server_url) - self.clear() - - def _startUML(self): - self.reqArr.append('@startuml') - - def _endUML(self): - self.reqArr.append('@enduml') - - def clear(self): - self.timestamps = {} - self.reqArr = [] - self.variables = [] - self.lineStyles = {} - self.stringUML = '' - self._startUML() - - def addAnalog(self, name, string): - self.variables.append(f'analog "{string}" as {name}') - - def addBinary(self, name, string, style = ''): - if style: name = name + '<<' + style + '>>' - self.variables.append(f'binary "{string}" as {name}') - - def addClock(self, name, string): - self.variables.append(f'clock "{string}" as {name}') - - def addConcise(self, name, string): - self.variables.append(f'concise "{string}" as {name}') - - def addRobust(self, name, string): - self.variables.append(f'robust "{string}" as {name}') - - def appendStr(self, string = ''): - self.variables.append(string) - - def addLineStyle(self, name, color = 'green', thicknes = 1): - self.lineStyles[name] = [f'LineColor {color}', f'LineThickness {thicknes}'] - - def generateSVG(self): - self._compileUML() - filename = abspath('UML.txt') - self.server.processes_file(filename, outfile='UML.svg') - #result = self.server.processes(self.stringUML) - #return result - - def setTimestamps(self, name, input): - for time, state in input: - try: - self.timestamps[f'@{time}'].append(f'{name} is {state}') - except KeyError: - self.timestamps[f'@{time}'] = [f'{name} is {state}'] - - def _addTimestamp(self, timecode, vars): - self.reqArr.append(timecode) - for var in vars: - self.reqArr.append(var) - - def _addHeader(self): - self.reqArr.append('') - - def _addVariables(self): - for var in self.variables: self.reqArr.append(str(var)) - - def _compileUML(self): - self._addHeader() - self._addVariables() - - if self.timestamps: - for key, item in self.timestamps.items(): - self._addTimestamp(key, item) - - self._endUML() - self.stringUML = [line + '\n' for line in self.reqArr] - with open('UML.txt', 'w', encoding='utf-8') as file: - file.writelines(self.stringUML) - - - +from plantuml import PlantUML +from os.path import abspath + + +class Request: + def __init__(self, server_url: str): + self._server_url = server_url + + self._init_server() + + def _init_server(self): + self.server = PlantUML(url=self._server_url) + self.clear() + + def _startUML(self): + self.reqArr.append('@startuml') + + def _endUML(self): + self.reqArr.append('@enduml') + + def clear(self): + self.timestamps = {} + self.reqArr = [] + self.variables = [] + self.lineStyles = {} + self.stringUML = '' + self._startUML() + + def addAnalog(self, name, string): + self.variables.append(f'analog "{string}" as {name}') + + def addBinary(self, name, string, style = ''): + if style: name = name + '<<' + style + '>>' + self.variables.append(f'binary "{string}" as {name}') + + def addClock(self, name, string): + self.variables.append(f'clock "{string}" as {name}') + + def addConcise(self, name, string): + self.variables.append(f'concise "{string}" as {name}') + + def addRobust(self, name, string): + self.variables.append(f'robust "{string}" as {name}') + + def appendStr(self, string = ''): + self.variables.append(string) + + def addLineStyle(self, name, color = 'green', thicknes = 1): + self.lineStyles[name] = [f'LineColor {color}', f'LineThickness {thicknes}'] + + def generateSVG(self): + self._compileUML() + filename = abspath('UML.txt') + self.server.processes_file(filename, outfile='UML.svg') + #result = self.server.processes(self.stringUML) + #return result + + def setTimestamps(self, name, input): + for time, state in input: + try: + self.timestamps[f'@{time}'].append(f'{name} is {state}') + except KeyError: + self.timestamps[f'@{time}'] = [f'{name} is {state}'] + + def _addTimestamp(self, timecode, vars): + self.reqArr.append(timecode) + for var in vars: + self.reqArr.append(var) + + def _addHeader(self): + self.reqArr.append('') + + def _addVariables(self): + for var in self.variables: self.reqArr.append(str(var)) + + def _compileUML(self): + self._addHeader() + self._addVariables() + + if self.timestamps: + for key, item in self.timestamps.items(): + self._addTimestamp(key, item) + + self._endUML() + self.stringUML = [line + '\n' for line in self.reqArr] + with open('UML.txt', 'w', encoding='utf-8') as file: + file.writelines(self.stringUML) + + + diff --git a/src/utils/__init__.py b/src/utils/__init__.py index 5cedfcd..170ff94 100644 --- a/src/utils/__init__.py +++ b/src/utils/__init__.py @@ -1,2 +1,2 @@ -from .json_tools import read_json +from .json_tools import read_json from .diagram_parser import DiagramParser \ No newline at end of file diff --git a/src/utils/diagram_parser.py b/src/utils/diagram_parser.py index 36110c7..471709f 100644 --- a/src/utils/diagram_parser.py +++ b/src/utils/diagram_parser.py @@ -1,55 +1,55 @@ -import pandas as pd -import numpy as np - -class DiagramParser: - def __init__(self, scaler = 1): - self.data = pd.DataFrame({}) - self.scaler = scaler - - def setData(self, path): - self.data = pd.read_csv(path) - - def getBoolDict (self): - boolDict = {} - for signalName in self.data.columns: - if type (self.data[signalName].iloc[0]) == np.bool: - boolDict[signalName] = self._getBoolChanges(signalName) - return boolDict - - def getFloatDict (self): - floatDict = {} - for signalName in self.data.columns: - if type (self.data[signalName].iloc[0]) == np.float64: - floatDict[signalName] = self._getFloatChanges(signalName) - return floatDict - - - def _getBoolChanges(self, signalName): - timeCode = self.data['time'] - signal_values = self.data[signalName] - changes = [] - - if len(signal_values) > 0: - changes.append([float(timeCode.iloc[0]), 'high' if bool(signal_values.iloc[0]) else 'low']) - - for i in range(1, len(signal_values)): - if signal_values.iloc[i] != signal_values.iloc[i - 1]: - changes.append([float(timeCode.iloc[i])*self.scaler, 'high' if bool(signal_values.iloc[i]) else 'low']) - - return changes - - - def _getFloatChanges(self, signalName): - timeCode = self.data['time'] - signal_values = self.data[signalName] - changes = [] - - if len(signal_values) > 0: - for i in range (len(signal_values)): - changes.append([float(timeCode.iloc[i]), float(signal_values.iloc[i])]) - - return changes - - - +import pandas as pd +import numpy as np + +class DiagramParser: + def __init__(self, scaler = 1): + self.data = pd.DataFrame({}) + self.scaler = scaler + + def setData(self, path): + self.data = pd.read_csv(path) + + def getBoolDict (self): + boolDict = {} + for signalName in self.data.columns: + if type (self.data[signalName].iloc[0]) == np.bool: + boolDict[signalName] = self._getBoolChanges(signalName) + return boolDict + + def getFloatDict (self): + floatDict = {} + for signalName in self.data.columns: + if type (self.data[signalName].iloc[0]) == np.float64: + floatDict[signalName] = self._getFloatChanges(signalName) + return floatDict + + + def _getBoolChanges(self, signalName): + timeCode = self.data['time'] + signal_values = self.data[signalName] + changes = [] + + if len(signal_values) > 0: + changes.append([float(timeCode.iloc[0]), 'high' if bool(signal_values.iloc[0]) else 'low']) + + for i in range(1, len(signal_values)): + if signal_values.iloc[i] != signal_values.iloc[i - 1]: + changes.append([float(timeCode.iloc[i])*self.scaler, 'high' if bool(signal_values.iloc[i]) else 'low']) + + return changes + + + def _getFloatChanges(self, signalName): + timeCode = self.data['time'] + signal_values = self.data[signalName] + changes = [] + + if len(signal_values) > 0: + for i in range (len(signal_values)): + changes.append([float(timeCode.iloc[i]), float(signal_values.iloc[i])]) + + return changes + + + \ No newline at end of file diff --git a/src/utils/json_tools.py b/src/utils/json_tools.py index ace78c5..3b3b14f 100644 --- a/src/utils/json_tools.py +++ b/src/utils/json_tools.py @@ -1,11 +1,11 @@ -from os import path -import json - - -def read_json(filepath: str) -> dict: - if not path.exists(filepath): - raise FileNotFoundError(f"JSON file {filepath} not found!") - - with open(filepath, 'r') as json_file: - data = json.load(json_file) - return data +from os import path +import json + + +def read_json(filepath: str) -> dict: + if not path.exists(filepath): + raise FileNotFoundError(f"JSON file {filepath} not found!") + + with open(filepath, 'r') as json_file: + data = json.load(json_file) + return data