Compare commits

..

No commits in common. "1a36aa217b9e449d53d92303838efd8bf0b7cedb" and "7d71a4774fdcee2255cb51e5d6378abc69016726" have entirely different histories.

19 changed files with 3067 additions and 484 deletions

View File

@ -1,16 +1,16 @@
{ {
"dist_open_start_1": 0.005, "dist_open_start_1" : 0.005,
"dist_open_start_2": 0.005, "dist_open_start_2" : 0.005,
"dist_open_after_1": 0.006, "dist_open_after_1" : 0.006,
"dist_open_after_2": 0.006, "dist_open_after_2" : 0.006,
"dist_open_end_1": 0.01, "dist_open_end_1" : 0.010,
"dist_open_end_2": 0.05, "dist_open_end_2" : 0.050,
"dist_close_end_1": 0.005, "dist_close_end_1" : 0.005,
"dist_close_end_2": 0.005, "dist_close_end_2" : 0.005,
"time_wielding": 1, "time_wielding" : 1,
"time_command": 0.06, "time_command" : 0.060,
"time_robot_movement": 0.2, "time_robot_movement" : 0.2,
"object_thickness": 0.0045, "object_thickness" : 4.5e-3,
"force_target": 5000, "force_target" : 5000,
"force_capture": 500 "force_capture" : 500
} }

View File

@ -15,9 +15,5 @@
"position_start_2": 0.08, "position_start_2": 0.08,
"k_prop": 0.05, "k_prop": 0.05,
"time_capture": 100000, "time_capture": 100000,
"UML_time_scaler": 1000, "UML_time_scaler": 1000
"Closure_signal": "Closing",
"Squeeze_signal": "Squeeze",
"Welding_signal": "Welding",
"Release_signal": "Relief"
} }

Binary file not shown.

View File

@ -1,3 +1,3 @@
from .plot_window import Plotter from .plot_window import PlotWindow
from .settings_window import settingsWindow from .settings_window import settingsWindow
from .app import tabWidgetGenerator from .app import app

View File

@ -3,75 +3,78 @@ import pyqtgraph as pg
from src.utils import read_json, DiagramParser from src.utils import read_json, DiagramParser
from src.uml import Request, UMLCreator from src.uml import Request, UMLCreator
from src.OptAlgorithm import OptAlgorithm from src.OptAlgorithm import OptAlgorithm
from src.gui import Plotter, settingsWindow from src.gui import PlotWindow, settingsWindow
class tabWidgetGenerator: class app:
def __init__(self, directory_to_save): def __init__(self):
self.UMLgenerator = Request(server_url='http://www.plantuml.com/plantuml/svg/')
self.uml_creator = UMLCreator(request_generator=self.UMLgenerator, path_to_save=directory_to_save)
self.operator_params = read_json("params/operator_params.json")
self.system_params = read_json("params/system_params.json")
self.operSettings = settingsWindow("params\operator_params.json", 'Operator', self._update)
self.sysSettings = settingsWindow("params\system_params.json", 'System', self._update)
self.paths = [] self.parser = DiagramParser()
self.plotters = [] self.request_generator = Request(server_url='http://www.plantuml.com/plantuml/svg/')
self.bool_dicts = []
self.float_dicts = [] self.operSettings = settingsWindow("params\operator_params.json", 'Operator', self._update_settings)
self.timings_dicts = [] self.sysSettings = settingsWindow("params\system_params.json", 'System', self._update_settings)
self.modes = []
self.names = [] self._load_preset()
def get_widget(self, path):
self.paths.append(path)
self.plotters.append(Plotter(show_settings_func=self._show_settings))
self._getParsedData(path)
self._update()
return self.plotters[-1].widget
def _get_ideal_timings(self, opt: OptAlgorithm) -> list[float]: def _get_ideal_timings(self, opt: OptAlgorithm) -> list[float]:
data = opt.Ts data = opt.Ts
ideal_time = [data['tclose'], data['tgrow'], opt.getMarkOpen(), data["tmovement"]] ideal_time = [data['tclose'], data['tgrow'], opt.getMarkOpen()]
return ideal_time return ideal_time
def _getParsedData(self, path): def _load_preset(self):
self.names.append(path) self.operator_params = read_json("params/operator_params.json")
parser = DiagramParser(system_config=self.system_params) self.system_params = read_json("params/system_params.json")
parser.setData(path)
self.bool_dicts.append(parser.getBoolDict())
self.float_dicts.append(parser.getFloatDict())
self.timings_dicts.append(parser.getRealTimings())
self.modes.append(parser.getMode())
self.opt_algorithm = OptAlgorithm(operator_config=self.operator_params, system_config=self.system_params)
self.ideal_times = self._get_ideal_timings(self.opt_algorithm)
def _update(self, _ = None): self.parser.setData("trace_samples/2024_11_08-19_30_49.csv")
self.operator_params = self.operSettings.getParams() self.bool_dict = self.parser.getBoolDict()
self.system_params = self.sysSettings.getParams() self.float_dict = self.parser.getFloatDict()
opt_algorithm = OptAlgorithm(operator_config=self.operator_params, system_config=self.system_params) self.plotter = PlotWindow(operator_config=self.operator_params,
ideal_times = self._get_ideal_timings(opt_algorithm)
for i in range (len(self.plotters)):
self.plotters[i].update_data(operator_config=self.operator_params,
system_config=self.system_params, system_config=self.system_params,
opt=opt_algorithm, opt=self.opt_algorithm,
bool_dict=self.bool_dicts[i], bool_dict=self.bool_dict,
ideal_time=ideal_times, float_dict=self.float_dict,
float_dict=self.float_dicts[i], show_settings_func=self._show_settings)
mode = self.modes[i],
timings_dict=self.timings_dicts[i]) self.uml_creator = UMLCreator(operator_config=self.operator_params,
system_config=self.system_params,
request_generator=self.request_generator,
ideal_time=self.ideal_times,
bool_dict=self.bool_dict,
float_dict=self.float_dict)
self.uml_creator.update_uml(operator_config=self.operator_params, self.uml_creator.update_uml(operator_config=self.operator_params,
system_config=self.system_params, system_config=self.system_params,
ideal_time=ideal_times, request_generator=self.request_generator,
bool_dict=self.bool_dicts[i], ideal_time=self.ideal_times,
float_dict=self.float_dicts[i], bool_dict=self.bool_dict,
mode = self.modes[i], float_dict=self.float_dict)
timings_dict=self.timings_dicts[i],
name = self.names[i])
def _update_settings(self, _):
self.operator_params = self.operSettings.getParams()
self.system_params = self.sysSettings.getParams()
self.opt_algorithm = OptAlgorithm(operator_config=self.operator_params, system_config=self.system_params)
self.ideal_times = self._get_ideal_timings(self.opt_algorithm)
self.uml_creator.update_uml(system_config=self.system_params,
request_generator=self.request_generator,
ideal_time=self.ideal_times,
bool_dict=self.bool_dict,
float_dict=self.float_dict)
self.plotter.update_data(operator_config=self.operator_params,
system_config=self.system_params,
opt=self.opt_algorithm,
bool_dict=self.bool_dict,
float_dict=self.float_dict)
def _show_settings(self): def _show_settings(self):
self.operSettings.show() self.operSettings.show()
self.sysSettings.show() self.sysSettings.show()
@ -79,7 +82,5 @@ class tabWidgetGenerator:
if __name__ == '__main__': if __name__ == '__main__':
pg.mkQApp("Plotting") pg.mkQApp("Plotting")
temp = tabWidgetGenerator() temp = app()
widget = temp.get_widget("trace_samples/2024_11_08-19_30_49.csv")
widget.show()
pg.exec() pg.exec()

View File

@ -1,6 +1,5 @@
import pyqtgraph as pg import pyqtgraph as pg
from pyqtgraph.Qt import QtWidgets from pyqtgraph.Qt import QtWidgets
from PyQt5.QtCore import Qt
import numpy as np import numpy as np
from src.gui import qt_settings as qts from src.gui import qt_settings as qts
@ -8,10 +7,22 @@ from src.gui import qt_settings as qts
from src.OptAlgorithm import OptAlgorithm from src.OptAlgorithm import OptAlgorithm
class Plotter: class PlotWindow:
def __init__(self, show_settings_func): def __init__(self,
system_config : dict,
operator_config: dict,
opt: OptAlgorithm,
bool_dict: dict,
float_dict: dict, show_settings_func):
pg.setConfigOptions(antialias=True) 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.alpha = 100 #[0-255 прозрачность фона]
self._getIdealTimings()
self._init_ui() self._init_ui()
self.settings_button.clicked.connect(show_settings_func) self.settings_button.clicked.connect(show_settings_func)
@ -20,23 +31,16 @@ class Plotter:
system_config : dict, system_config : dict,
operator_config: dict, operator_config: dict,
opt: OptAlgorithm, opt: OptAlgorithm,
ideal_time: list[float],
bool_dict: dict, bool_dict: dict,
float_dict: dict, float_dict: dict):
timings_dict: dict,
mode: bool):
self.opt = opt self.opt = opt
self.bool_dict = bool_dict self.bool_dict = bool_dict
self.float_dict = float_dict self.float_dict = float_dict
self.timings_dict = timings_dict
self.idealTime = ideal_time
self.theor_mode = mode
self.scaler = int(system_config['UML_time_scaler']) self.scaler = int(system_config['UML_time_scaler'])
self.WeldTime = operator_config['time_wielding'] #[sec] self.WeldTime = operator_config['time_wielding'] #[sec]
self.WeldData = self.opt.calcPhaseGrow(self.idealTime[1]) self._getIdealTimings()
self._updatePlots() self._updatePlots()
def _init_ui(self): def _init_ui(self):
self.widget = QtWidgets.QWidget() self.widget = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout() layout = QtWidgets.QVBoxLayout()
@ -49,15 +53,7 @@ class Plotter:
layout.addWidget(self.win) layout.addWidget(self.win)
self.settings_button = QtWidgets.QPushButton("Show settings") self.settings_button = QtWidgets.QPushButton("Show settings")
self.settings_button.setFixedWidth(160) self.settings_button.setFixedWidth(160)
info_layout = QtWidgets.QHBoxLayout() layout.addWidget(self.settings_button)
layout.addLayout(info_layout)
info_layout.addWidget(self.settings_button, alignment = Qt.AlignLeft)
info_layout.setSpacing(20)
self.efficiency = QtWidgets.QLabel()
info_layout.addWidget(self.efficiency, alignment = Qt.AlignRight)
self.p11, self.l11 = self._init_graph('Electrode force, closure', 'Force', 'N', 'Time', 'ms') 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.p21, _ = self._init_graph('Electrode force, compression', 'Force', 'N', 'Time', 'ms')
@ -78,7 +74,9 @@ class Plotter:
self.p11.setAutoVisible(x=False, y=True) self.p11.setAutoVisible(x=False, y=True)
self.p12.setAutoVisible(x=False, y=True) self.p12.setAutoVisible(x=False, y=True)
self.p13.setAutoVisible(x=False, y=True) self.p13.setAutoVisible(x=False, y=True)
self._updatePlots()
self.widget.setStyleSheet(qts.dark_style) self.widget.setStyleSheet(qts.dark_style)
self.widget.show()
def _init_graph(self, title, Yname, Yunits, Xname, Xunits): def _init_graph(self, title, Yname, Yunits, Xname, Xunits):
plot = self.win.addPlot(title = title) plot = self.win.addPlot(title = title)
@ -97,125 +95,40 @@ class Plotter:
self.p13.clear() self.p13.clear()
self.l13.clear() self.l13.clear()
if not self.theor_mode:
self._plotRealData() self._plotRealData()
self._form_idealdatGraph() times = np.arange(20000)/10
self._calcOurScore() self._plotIdealData(times)
def _calcOurScore (self): def _getIdealTimings(self):
success = [] data = self.opt.Ts
start = np.array(self.timings_dict["closure"])[:, 0] self.idealTime = [data['tclose'], data['tgrow'], self.opt.getMarkOpen(), data["tmovement"]]
end = np.array(self.timings_dict["opening"])[:, 1]
points_timings = end-start
ideal_time = sum(self.idealTime[:3])+self.WeldTime def _form_idealdatGraph(self, times):
for point in points_timings: self.idealPhase0 = (self.idealTime[0])*self.scaler #Подъезд
success.append(int(ideal_time/point * 100)) self.idealPhase1 = (self.idealTime[0]+ self.idealTime[1])*self.scaler #Сжатие
if len(success) > 1: self.idealPhase2 = (self.idealTime[0]+ self.idealTime[1] + self.WeldTime)*self.scaler #Сварка
maxS = max(success) self.idealPhase3 = (self.idealTime[0]+ self.idealTime[1] + self.idealTime[2] + self.WeldTime)*self.scaler #Разъезд
minS = min(success) self.idealPhase4 = (sum(self.idealTime[:4]) + self.WeldTime)*self.scaler #Последнее смыкание #TODO добавить идеальное время вместо 0.25
average = int(sum(success[:])/len(success)) self.x_splitter = np.array([[0, self.idealPhase0],
self.efficiency.setText(f'Efficiency Maximum: {maxS}%, Average: {average}%, Minimum: {minS}%' ) [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: else:
self.efficiency.setText(f'Efficiency Maximum: {success[0]}' ) x_fe, x_me, v_fe, v_me, f = self.opt.calcPhaseMovement(time/self.scaler-sum(self.idealTime[:3])-self.WeldTime)
self.efficiency.setStyleSheet(qts.BigSuccessLabel) data.append([x_fe, x_me, v_fe, v_me, f])
data = np.array(data).T
return data
def _form_idealdatGraph(self):
if self.theor_mode:
self.timings_dict["closure"] = [[0, self.idealTime[0]]]
self.timings_dict["compression"] = [[self.idealTime[0], sum(self.idealTime[:2])]]
self.timings_dict["welding"] = [[sum(self.idealTime[:2]), sum(self.idealTime[:2])+self.WeldTime]]
self.timings_dict["opening"] = [[sum(self.idealTime[:2])+self.WeldTime, sum(self.idealTime[:3])+self.WeldTime]]
delta = 10 #points_per_ms
for key, items in self.timings_dict.items():
for item in items:
item_data = []
time_data = []
if key == 'closure':
ideal_time = self.idealTime[0]
calc = self.opt.calcPhaseClose
color = qts.RGBA[0]
for i in range(0, int(ideal_time*self.scaler)*delta):
time = i/delta
item_data.append(calc(time/self.scaler))
time_data.append(time+item[0]*self.scaler)
#print (item_data[-1], time_data[-1])
self._plotIdealData(np.array(time_data), np.array(item_data).T)
self._addBackgroundSplitter([item[0]*self.scaler,item[0]*self.scaler + time], color)
elif key == 'compression':
ideal_time = self.idealTime[1]
calc = self.opt.calcPhaseGrow
color = qts.RGBA[1]
for i in range(int(ideal_time*self.scaler)*delta, 0, -1):
time = i/delta
item_data.append(calc(time/self.scaler))
time_data.append(item[1]*self.scaler-(ideal_time*self.scaler-time))
#print (item_data[-1], time_data[-1])
self._plotIdealData(np.array(time_data), np.array(item_data).T)
self._addBackgroundSplitter([(item[1]-ideal_time)*self.scaler, item[1]*self.scaler], color)
temp = item_data[0][4]
x = [time_data[0], time_data[-1], time_data[-1]-0.0001]
y = [temp, temp, temp]
a1, b1, c1 = self._calculate_equidistant(x, y, 2.5, 3)
self.p11.addItem(a1)
self.p11.addItem(b1)
self.p11.addItem(c1)
elif key == 'welding':
ideal_time = self.WeldTime
calc = self._returnWeldData
color = qts.RGBA[2]
for i in range(0, int(ideal_time*self.scaler)*delta):
time = i/delta
item_data.append(calc(time/self.scaler))
time_data.append(time+item[0]*self.scaler)
#print (item_data[-1], time_data[-1])
self._plotIdealData(np.array(time_data), np.array(item_data).T)
self._addBackgroundSplitter([item[0]*self.scaler,item[0]*self.scaler + time], color)
x = [time_data[0], time_data[-1], time_data[-1]+0.0001]
y = [item_data[0][4], item_data[0][4], item_data[0][4]]
a1, b1, c1 = self._calculate_equidistant(x, y, 0.75, 3)
self.p11.addItem(a1)
self.p11.addItem(b1)
self.p11.addItem(c1)
elif key == 'opening':
calc = self.opt.calcPhaseOpen
ideal_time = self.idealTime[2]
ideal_closure = self.idealTime[3]
color = qts.RGBA[3]
color_closure = qts.RGBA[4]
for i in range(0, int(ideal_time*self.scaler)*delta):
time = i/delta
item_data.append(calc(time/self.scaler))
time_data.append(time+item[0]*self.scaler)
#print (item_data[-1], time_data[-1])
self._plotIdealData(np.array(time_data), np.array(item_data).T)
self._addBackgroundSplitter([item[0]*self.scaler,item[0]*self.scaler + time], color)
item_data = []
time_data = []
for i in range(0, int(ideal_closure*self.scaler)*delta):
time = i/delta
item_data.append(self.opt.calcPhaseMovement(time/self.scaler))
time_data.append(time+item[1]*self.scaler)
self._plotIdealData(np.array(time_data), np.array(item_data).T)
self._addBackgroundSplitter([item[1]*self.scaler,item[1]*self.scaler + time], color_closure)
def _returnWeldData(self, _):
return self.WeldData
def _plotRealData(self): def _plotRealData(self):
for i, (key, dat) in enumerate(self.float_dict.items()): for i, (key, dat) in enumerate(self.float_dict.items()):
@ -233,37 +146,40 @@ class Plotter:
self.l13.addItem(curve, key) self.l13.addItem(curve, key)
return dat[0] return dat[0]
def _plotIdealData(self, time, data): def _plotIdealData(self, times):
x_fe = pg.PlotDataItem(time, data[0]*1000, pen=pg.mkPen(color=qts.colors[8], width=2), name='x_fe', autoDownsample=True, downsample=True) data = self._form_idealdatGraph(times)
x_me = pg.PlotDataItem(time, data[1]*1000, pen=pg.mkPen(color=qts.colors[9], width=2), name='x_me', autoDownsample=True, downsample=True)
v_fe = pg.PlotDataItem(time, data[2]*1000, pen=pg.mkPen(color=qts.colors[8], width=2), name='v_fe', autoDownsample=True, downsample=True) x_fe = pg.PlotDataItem(times, data[0]*1000, pen=pg.mkPen(color=qts.colors[8], width=2), name='x_fe', autoDownsample=True, downsample=True)
v_me = pg.PlotDataItem(time, data[3]*1000, pen=pg.mkPen(color=qts.colors[9], width=2), name='v_me', 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)
f = pg.PlotDataItem(time, data[4], pen=pg.mkPen(color=qts.colors[8], width=2), name='f', 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.p11.addItem(f)
#self.l11.addItem(f, 'Ideal force') self.l11.addItem(f, 'Ideal force')
self.p12.addItem(x_fe) self.p12.addItem(x_fe)
#self.l12.addItem(x_fe, 'FE POS') self.l12.addItem(x_fe, 'FE POS')
self.p12.addItem(x_me) self.p12.addItem(x_me)
#self.l12.addItem(x_me, 'ME POS') self.l12.addItem(x_me, 'ME POS')
self.p13.addItem(v_fe) self.p13.addItem(v_fe)
#self.l13.addItem(v_fe, 'FE VEL') self.l13.addItem(v_fe, 'FE VEL')
self.p13.addItem(v_me) self.p13.addItem(v_me)
#self.l13.addItem(v_me, 'ME VEL') self.l13.addItem(v_me, 'ME VEL')
#self._addBackgroundSplitter() self._addBackgroundSplitter()
#self._addEquidistances(time, data) self._addEquidistances(times, data)
def _addBackgroundSplitter(self, x, color): def _addBackgroundSplitter(self):
alpha = self.alpha alpha = self.alpha
y01 = np.array([10000, 10000]) y01 = np.array([10000, 10000])
y0_1 = np.array([-10000, -10000]) y0_1 = np.array([-10000, -10000])
a01 = pg.PlotDataItem(x, y01, pen=pg.mkPen(color=qts.colors[8], width=2), name=' ') for i, _ in enumerate(self.x_splitter):
a0_1 = pg.PlotDataItem(x, y0_1, pen=pg.mkPen(color=qts.colors[8], width=2), name=' ') a01 = pg.PlotDataItem(_, y01, pen=pg.mkPen(color=qts.colors[8], width=2), name=' ')
bg1 = pg.FillBetweenItem(a01, a0_1, color+(alpha,)) a0_1 = pg.PlotDataItem(_, y0_1, pen=pg.mkPen(color=qts.colors[8], width=2), name=' ')
bg2 = pg.FillBetweenItem(a01, a0_1, color+(alpha,)) bg1 = pg.FillBetweenItem(a01, a0_1, qts.RGBA[i]+(alpha,))
bg3 = pg.FillBetweenItem(a01, a0_1, color+(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.p11.addItem(bg1)
self.p12.addItem(bg2) self.p12.addItem(bg2)
self.p13.addItem(bg3) self.p13.addItem(bg3)
@ -272,6 +188,19 @@ class Plotter:
self.p12.setYRange(-50, 250) self.p12.setYRange(-50, 250)
self.p13.setYRange(-400, 400) 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): def _makeFiller(self, x1, y1, x2, y2, color):
alpha = self.alpha alpha = self.alpha
@ -281,7 +210,11 @@ class Plotter:
return eq1, eq2, bg return eq1, eq2, bg
def _calculate_equidistant(self, x, y, percent, color): 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): if len(x) != len(y):
raise ValueError("x и y должны быть одного размера") raise ValueError("x и y должны быть одного размера")
distance = max(y)/100*percent distance = max(y)/100*percent
@ -291,6 +224,8 @@ class Plotter:
y_eq2 = [] y_eq2 = []
for i in range(0, len(x) - 1): for i in range(0, len(x) - 1):
if splitter[0]<= x[i] and x[i] <= splitter[1]:
dx = x[i + 1] - x[i] dx = x[i + 1] - x[i]
dy = y[i + 1] - y[i] dy = y[i + 1] - y[i]
length = np.sqrt(dx ** 2 + dy ** 2) length = np.sqrt(dx ** 2 + dy ** 2)

View File

@ -233,13 +233,7 @@ QPushButton:disabled {
} }
""" """
BigSuccessLabel = """
QLabel {
color: #ffffff;
font-size: 26px;
font-weight: bold;
font-family: "Segoe UI", sans-serif;
}"""
colors = [ colors = [
'#FF6F61', # яркий коралловый '#FF6F61', # яркий коралловый

View File

@ -1,115 +1,12 @@
import sys import pyqtgraph as pg
import os
import time
from PyQt5.QtWidgets import (
QApplication,
QMainWindow,
QTabWidget,
QWidget,
QVBoxLayout,
QLabel,
)
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QObject, QFileSystemWatcher
from PyQt5.QtGui import QIcon
from src.gui import qt_settings as qts
# Импортируйте ваш класс `app` здесь
# Предполагается, что класс `app` предоставляет интерфейс для отображения данных
# Если `app` не предоставляет виджет, возможно, потребуется его модифицировать
from src.gui.app import tabWidgetGenerator
class DirectoryWatcher(QObject):
file_created = pyqtSignal(str)
def __init__(self, directory_path):
super().__init__()
self.directory_path = directory_path
self.watcher = QFileSystemWatcher()
self.watcher.addPath(self.directory_path)
self.existing_files = set(os.listdir(self.directory_path))
self.watcher.directoryChanged.connect(self.on_directory_changed)
def on_directory_changed(self, _):
try:
current_files = set(os.listdir(self.directory_path))
new_files = current_files - self.existing_files
self.existing_files = current_files
for file in new_files:
if file.lower().endswith(".csv"):
full_path = os.path.join(self.directory_path, file)
self.file_created.emit(full_path)
except Exception as e:
print(f"Ошибка при обработке изменений директории: {e}")
class MainWindow(QMainWindow):
def __init__(self, directory_to_watch):
super().__init__()
self.setWindowTitle("Мониторинг CSV-файлов")
self.setGeometry(100, 100, 800, 600)
self.tabs = QTabWidget()
self.tabs.setStyleSheet(qts.dark_style)
self.tabGen = tabWidgetGenerator(directory_to_watch)
self.handle_new_file()
self.setCentralWidget(self.tabs)
# self.setWindowIcon(QIcon("path_to_icon.png"))
self.start_directory_watcher(directory_to_watch)
def start_directory_watcher(self, directory_path):
self.watcher_thread = QThread()
self.watcher = DirectoryWatcher(directory_path)
self.watcher.moveToThread(self.watcher_thread)
self.watcher.file_created.connect(self.handle_new_file)
self.watcher_thread.started.connect(self.watcher.on_directory_changed)
self.watcher_thread.start()
def handle_new_file(self, file_path = None):
time.sleep(0.2)
if file_path:
file_name = os.path.basename(file_path)
else:
file_path = None
file_name = 'Ideal'
tab_widget = self.tabGen.get_widget(path=file_path)
tab = QWidget()
layout = QVBoxLayout()
layout.addWidget(tab_widget)
label = QLabel(f"{file_name}")
label.setAlignment(Qt.AlignCenter)
layout.addWidget(label)
tab.setLayout(layout)
self.tabs.addTab(tab, file_name)
def closeEvent(self, event):
self.watcher_thread.quit()
self.watcher_thread.wait()
event.accept()
from src.gui import app
def main(): def main():
directory_to_watch = "D:/downloads/a22" pg.mkQApp("Plotting")
temp = app()
if not os.path.isdir(directory_to_watch): pg.exec()
print(f"Директория не найдена: {directory_to_watch}")
sys.exit(1)
app_instance = QApplication(sys.argv)
window = MainWindow(directory_to_watch)
window.show()
sys.exit(app_instance.exec_())
if __name__ == "__main__": if __name__ == '__main__':
main() main()

View File

@ -2,48 +2,39 @@ from src.uml.request_generator import Request
class UMLCreator: class UMLCreator:
def __init__(self, request_generator: Request, path_to_save: str): def __init__(self,
system_config: dict,
operator_config: dict,
request_generator: Request,
ideal_time: list[float],
bool_dict: dict,
float_dict: dict):
self._request_generator = request_generator self._request_generator = request_generator
self.path_to_save = path_to_save self._ideal_time = ideal_time
self.bool_dict = bool_dict
self.float_dict = float_dict
self.scaler = int(system_config['UML_time_scaler'])
self.WeldTime = operator_config['time_wielding']
def _build_data(self): def _build_data(self):
real_data = [] sig = [
ideal_data = [] "Closing",
if not self.theor_mode: "Relief",
"Squeeze",
"Welding"
]
closure = [self.bool_dict[sig[0]][1][0], self.bool_dict[sig[0]][2][0]]
compression = [self.bool_dict[sig[2]][1][0], self.bool_dict[sig[2]][2][0]]
opening = [self.bool_dict[sig[1]][1][0], self.bool_dict[sig[1]][-1][0]]
for key, items in self.timings_dict.items(): real_data = [
if key == 'closure': ideal_time = self._ideal_time[0] [closure[0]*self.scaler, 'closure #green'],
elif key == 'compression': ideal_time = self._ideal_time[1] [closure[1]*self.scaler, '{-}'],
elif key == 'welding': ideal_time = self.WeldTime [compression[0]*self.scaler+0.0001, 'compression #green'],
elif key == 'opening': ideal_time = self._ideal_time[2] [compression[1]*self.scaler, 'welding #green'],
[opening[0]*self.scaler+0.0001, 'opening #green'],
for item in items: [opening[1]*self.scaler, '{-}'],
real_data.append([item[0]*self.scaler+0.0001, str(key) + '#green'])
real_data.append([item[1]*self.scaler, '{-}'])
if key == 'compression':
ideal_data.append([(item[1]-ideal_time)*self.scaler, str(key) + '#yellow'])
ideal_data.append([(item[1]-0.0001)*self.scaler, '{-}'])
else:
ideal_data.append([item[0]*self.scaler+0.0001, str(key) + '#yellow'])
ideal_data.append([(item[0]+ideal_time)*self.scaler, '{-}'])
if key == 'opening':
ideal_data.append([item[1]*self.scaler+0.0001, 'coming #yellow'])
ideal_data.append([(item[1]+self._ideal_time[3])*self.scaler, '{-}'])
else:
real_data = []
ideal_data = [
[0.0, 'closure #yellow'],
[self._ideal_time[0] * self.scaler, '{-}'],
[(self._ideal_time[0] + 0.0001) * self.scaler, 'compression #yellow'],
[sum(self._ideal_time[:2]) * self.scaler, '{-}'],
[(sum(self._ideal_time[:2])+ 0.0001) * self.scaler, 'welding #yellow'],
[(sum(self._ideal_time[:2]) + self.WeldTime)*self.scaler, '{-}'],
[(sum(self._ideal_time[:2]) + 0.0001 + self.WeldTime) * self.scaler, 'opening #yellow'],
[(sum(self._ideal_time[:3]) + self.WeldTime) * self.scaler, 'coming #yellow'],
[(sum(self._ideal_time[:4]) + self.WeldTime) * self.scaler, '{-}'],
] ]
client_data = [ client_data = [
@ -57,15 +48,31 @@ class UMLCreator:
[0.300 * self.scaler, '{-}'], [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, '{-}'],
[(self._ideal_time[0] + self._ideal_time[1]+ 0.0001) * self.scaler, 'welding #yellow'],
[(self._ideal_time[0] + self._ideal_time[1] + self.WeldTime)*self.scaler, '{-}'],
[(self._ideal_time[0] + self._ideal_time[1] + 0.0001 + self.WeldTime) * self.scaler, 'opening #yellow'],
[(self._ideal_time[0] + self._ideal_time[1] + self._ideal_time[2] + self.WeldTime) * self.scaler, '{-}'],
]
return real_data, client_data, ideal_data, self.bool_dict 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: def _generate_svg(self, real_data, client_data, ideal_data, bool_data) -> None:
try:
self._request_generator.clear() self._request_generator.clear()
self._request_generator.appendStr('scale 25 as 50 pixels')
if not self.theor_mode:
self._request_generator.addLineStyle('biba', 'red', 2) self._request_generator.addLineStyle('biba', 'red', 2)
for i, [signal, changes] in enumerate(bool_data.items()): for i, [signal, changes] in enumerate(bool_data.items()):
@ -78,33 +85,28 @@ class UMLCreator:
self._request_generator.addConcise('RD', 'Real data') self._request_generator.addConcise('RD', 'Real data')
self._request_generator.setTimestamps('RD', real_data) self._request_generator.setTimestamps('RD', real_data)
else: self.name = self.path_to_save + '/Ideal'
self._request_generator.addConcise('CD', 'Client data') self._request_generator.addConcise('CD', 'Client data')
self._request_generator.setTimestamps('CD', client_data) self._request_generator.setTimestamps('CD', client_data)
self._request_generator.addConcise('ID', 'Ideal data') self._request_generator.addConcise('ID', 'Ideal data')
self._request_generator.setTimestamps('ID', ideal_data) self._request_generator.setTimestamps('ID', ideal_data)
try:
self._request_generator.generateSVG(self.name) self._request_generator.generateSVG()
except Exception as e: except Exception as e:
print(f"SVG generate error: {e}") print(f"SVG generate error: {e}")
def update_uml(self, def update_uml(self,
operator_config: dict, operator_config: dict,
system_config : dict, system_config : dict,
request_generator: Request,
ideal_time: list[float], ideal_time: list[float],
bool_dict: dict, bool_dict: dict,
float_dict: dict, float_dict: dict):
timings_dict: dict,
mode: bool,
name:str):
self._request_generator = request_generator
self._ideal_time = ideal_time self._ideal_time = ideal_time
self.bool_dict = bool_dict self.bool_dict = bool_dict
self.float_dict = float_dict self.float_dict = float_dict
self.timings_dict = timings_dict
self.theor_mode = mode
self.name = name
self.scaler = int(system_config['UML_time_scaler']) self.scaler = int(system_config['UML_time_scaler'])
self.WeldTime = operator_config['time_wielding'] self.WeldTime = operator_config['time_wielding']

View File

@ -48,10 +48,10 @@ class Request:
def addLineStyle(self, name, color = 'green', thicknes = 1): def addLineStyle(self, name, color = 'green', thicknes = 1):
self.lineStyles[name] = [f'LineColor {color}', f'LineThickness {thicknes}'] self.lineStyles[name] = [f'LineColor {color}', f'LineThickness {thicknes}']
def generateSVG(self, name): def generateSVG(self):
self._compileUML(name) self._compileUML()
filename = abspath(f'{name}.txt') filename = abspath('UML.txt')
self.server.processes_file(filename, outfile=f'{name}.svg') self.server.processes_file(filename, outfile='UML.svg')
#result = self.server.processes(self.stringUML) #result = self.server.processes(self.stringUML)
#return result #return result
@ -78,11 +78,12 @@ class Request:
self.reqArr.append('}') self.reqArr.append('}')
self.reqArr.append('</style>') self.reqArr.append('</style>')
self.reqArr.append('scale 10 as 50 pixels')
def _addVariables(self): def _addVariables(self):
for var in self.variables: self.reqArr.append(str(var)) for var in self.variables: self.reqArr.append(str(var))
def _compileUML(self, name): def _compileUML(self):
self._addHeader() self._addHeader()
self._addVariables() self._addVariables()
@ -92,7 +93,7 @@ class Request:
self._endUML() self._endUML()
self.stringUML = [line + '\n' for line in self.reqArr] self.stringUML = [line + '\n' for line in self.reqArr]
with open(f'{name}.txt', 'w', encoding='utf-8') as file: with open('UML.txt', 'w', encoding='utf-8') as file:
file.writelines(self.stringUML) file.writelines(self.stringUML)

View File

@ -2,60 +2,28 @@ import pandas as pd
import numpy as np import numpy as np
class DiagramParser: class DiagramParser:
def __init__(self, system_config: dict): def __init__(self):
self.data = pd.DataFrame({}) self.data = pd.DataFrame({})
self.signals = [system_config["Closure_signal"],
system_config["Squeeze_signal"],
system_config["Welding_signal"],
system_config["Release_signal"]]
self.boolDict = {}
self.floatDict = {}
self.timingsDict = {}
self.theor_mode = False
def setData(self, path): def setData(self, path):
if not path:
self.theor_mode = True
else:
self.data = pd.read_csv(path) self.data = pd.read_csv(path)
def getBoolDict (self):
boolDict = {}
for signalName in self.data.columns: for signalName in self.data.columns:
if type (self.data[signalName].iloc[0]) == np.bool: if type (self.data[signalName].iloc[0]) == np.bool:
self.boolDict[signalName] = self._getBoolChanges(signalName) boolDict[signalName] = self._getBoolChanges(signalName)
return boolDict
def getFloatDict (self):
floatDict = {}
for signalName in self.data.columns: for signalName in self.data.columns:
if type (self.data[signalName].iloc[0]) == np.float64: if type (self.data[signalName].iloc[0]) == np.float64:
self.floatDict[signalName] = self._getFloatChanges(signalName) floatDict[signalName] = self._getFloatChanges(signalName)
return floatDict
for key, items in self.boolDict.items():
if key == self.signals[0]: name = "closure"
elif key == self.signals[1]: name = "compression"
elif key == self.signals[2]: name = "welding"
elif key == self.signals[3]: name = "opening"
self.timingsDict[name] = [] def _getBoolChanges(self, signalName):
len_items = len(items)
for i, item in enumerate(items):
if item[1] == 'high':
if i < len_items-1:
self.timingsDict[name].append([items[i][0], items[i+1][0]])
else:
self.timingsDict[name].append([items[i][0], items[i][0]+0.01])
def getBoolDict (self) -> dict:
return self.boolDict
def getFloatDict (self) -> dict:
return self.floatDict
def getRealTimings(self) -> dict:
return self.timingsDict
def getMode(self) -> bool:
return self.theor_mode
def _getBoolChanges(self, signalName) -> list:
timeCode = self.data['time'] timeCode = self.data['time']
signal_values = self.data[signalName] signal_values = self.data[signalName]
changes = [] changes = []
@ -70,7 +38,7 @@ class DiagramParser:
return changes return changes
def _getFloatChanges(self, signalName) -> list: def _getFloatChanges(self, signalName):
timeCode = self.data['time'] timeCode = self.data['time']
signal_values = self.data[signalName] signal_values = self.data[signalName]
changes = [] changes = []

File diff suppressed because it is too large Load Diff