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