diff --git a/src - Ярлык.lnk b/src - Ярлык.lnk new file mode 100644 index 0000000..5985c31 Binary files /dev/null and b/src - Ярлык.lnk differ diff --git a/src/gui/__pycache__/plotter.cpython-310.pyc b/src/gui/__pycache__/plotter.cpython-310.pyc index 523d4ef..9f7357b 100644 Binary files a/src/gui/__pycache__/plotter.cpython-310.pyc and b/src/gui/__pycache__/plotter.cpython-310.pyc differ diff --git a/src/gui/plotter.py b/src/gui/plotter.py index 23d5a5e..510de8d 100644 --- a/src/gui/plotter.py +++ b/src/gui/plotter.py @@ -45,18 +45,17 @@ class PlotWidget(BasePlotWidget): return None @staticmethod - def _init_plot_widget(title: str) -> tuple[pg.PlotWidget, pg.LegendItem]: - plot_widget = pg.PlotWidget(title=title) + def _init_plot_item(title: str) -> tuple[pg.PlotItem, pg.LegendItem]: + plot_item = pg.PlotItem(title=title) # Оптимизация отображения графиков - plot_widget.setDownsampling(auto=True, mode='peak') - plot_widget.showGrid(x=True, y=True) - plot_widget.setClipToView(True) - legend = pg.LegendItem((80, 60), offset=(70, 20)) - legend.setParentItem(plot_widget.graphicsItem()) - return plot_widget, legend + plot_item.setDownsampling(auto=True, mode='peak') + plot_item.showGrid(x=True, y=True) + plot_item.setClipToView(True) + legend = plot_item.addLegend(offset=(70, 20)) + return plot_item, legend def _add_stage_regions(self, - plot_widget: pg.PlotWidget, + plot_item: pg.PlotItem, point_events: dict[str, list[float]], dataframe_headers: list[str], reg_items: dict, @@ -71,12 +70,12 @@ class PlotWidget(BasePlotWidget): region = self._create_stage_region(stage, start_t, end_t, transparency) if region is not None: region.setZValue(-20) - plot_widget.addItem(region) + plot_item.addItem(region) reg_items["real"].setdefault(stage, []) reg_items["real"][stage].append(region) def _add_ideal_stage_regions(self, - plot_widget: pg.PlotWidget, + plot_item: pg.PlotItem, ideal_data: dict[str, Any], point_events: dict[str, list[float]], reg_items: dict, @@ -92,12 +91,12 @@ class PlotWidget(BasePlotWidget): region = self._create_stage_region(stage, start_t, end_t, transparency) if region: region.setZValue(-10) - plot_widget.addItem(region) + plot_item.addItem(region) reg_items["ideal"].setdefault(stage, []) reg_items["ideal"][stage].append(region) def _add_ideal_signals(self, - plot_widget: pg.PlotWidget, + plot_item: pg.PlotItem, ideal_data: dict[str, Any], point_events: dict[str, list[float]], ideal_signals: list[dict[str, Any]], @@ -115,13 +114,13 @@ class PlotWidget(BasePlotWidget): ) if curve: curve.setZValue(10) - plot_widget.addItem(curve) + plot_item.addItem(curve) curve_items["ideal"].setdefault(signal["name"], {}) curve_items["ideal"][signal["name"]].setdefault(stage, []) curve_items["ideal"][signal["name"]][stage].append(curve) def _add_real_signals(self, - plot_widget: pg.PlotWidget, + plot_item: pg.PlotItem, dataframe: pd.DataFrame, real_signals: list[dict[str, Any]], legend: pg.LegendItem, @@ -132,7 +131,7 @@ class PlotWidget(BasePlotWidget): dataframe_headers = dataframe.columns.tolist() for signal in real_signals: if signal["name"] in dataframe_headers: - plot = plot_widget.plot(dataframe["time"], dataframe[signal["name"]], pen=signal["pen"], fast=True) + plot = plot_item.plot(dataframe["time"], dataframe[signal["name"]], pen=signal["pen"], fast=True) plot.setZValue(0) legend.addItem(plot, signal["name"]) curve_items["real"].setdefault(signal["name"], {}) @@ -163,8 +162,9 @@ class PlotWidget(BasePlotWidget): Собирает графический виджет для одного набора данных. Параметр `data` предполагается списком: [dataframe, points_pocket, useful_data]. """ - widget = QWidget() - layout = QVBoxLayout(widget) + result_widget = QWidget() + result_layout = QVBoxLayout(result_widget) + plot_layout = pg.GraphicsLayoutWidget() reg_items = {"real":{}, "ideal":{}} curve_items = {"real":{}, "ideal":{}} @@ -175,7 +175,7 @@ class PlotWidget(BasePlotWidget): dataframe_headers = dataframe.columns.tolist() for widget_num, (channel, description) in enumerate(self._plt_channels.items()): - plot_widget, legend = self._init_plot_widget(title=channel) + plot_item, legend = self._init_plot_item(title=channel) settings = description["Settings"] TWC_time = 0.0 @@ -184,7 +184,12 @@ class PlotWidget(BasePlotWidget): # TODO: рассчитать корректный параметр range if settings["mirror ME"]: - dataframe = self._mirror_shift_data("ME", description["Real_signals"], dataframe, range_ME) + dataframe = self._mirror_shift_data( + "ME", + description["Real_signals"], + dataframe, + range_ME + ) # Итерация по точкам for cur_point, point_data in enumerate(points_pocket): @@ -207,7 +212,7 @@ class PlotWidget(BasePlotWidget): # Добавляем реальные стадии if settings["stages"]: - self._add_stage_regions(plot_widget, point_events, dataframe_headers, reg_items, 75) + self._add_stage_regions(plot_item, point_events, dataframe_headers, reg_items, 75) # TODO: подобрать не вырвеглазные цвета, возможно ограничить зону if settings["workpiece"]: @@ -220,7 +225,7 @@ class PlotWidget(BasePlotWidget): rect_item.setZValue(-5) rect_item.setBrush(pg.mkBrush('grey')) rect_item.setPen(pg.mkPen('black', width=3)) - plot_widget.addItem(rect_item) + plot_item.addItem(rect_item) if settings["force accuracy"]: modifier = 0.05 @@ -235,12 +240,12 @@ class PlotWidget(BasePlotWidget): rect_item.setZValue(-5) rect_item.setBrush(pg.mkBrush((0,255,0, 50))) rect_item.setPen(pg.mkPen('black', width=0)) - plot_widget.addItem(rect_item) + plot_item.addItem(rect_item) # Добавляем идеальные стадии и идеальные сигналы if settings["ideals"]: - self._add_ideal_stage_regions(plot_widget, ideal_data, point_events, reg_items, 100) - self._add_ideal_signals(plot_widget, ideal_data, point_events, description["Ideal_signals"], curve_items) + self._add_ideal_stage_regions(plot_item, ideal_data, point_events, reg_items, 100) + self._add_ideal_signals(plot_item, ideal_data, point_events, description["Ideal_signals"], curve_items) # Подсчёт производительности if settings["performance"]: @@ -259,26 +264,26 @@ class PlotWidget(BasePlotWidget): worst_timeframe = point_timeframe # Добавляем реальные сигналы - self._add_real_signals(plot_widget, dataframe, description["Real_signals"], legend, curve_items) + self._add_real_signals(plot_item, dataframe, description["Real_signals"], legend, curve_items) if widget_num == 0: - main_plot = plot_widget + main_plot = plot_item else: # Связываем остальные графики с основным графиком - plot_widget.setXLink(main_plot) + plot_item.setXLink(main_plot) - # Если есть настройка производительности, добавляем label if settings["performance"]: - self._add_performance_label(layout, TWC_time, ideal_time, tesla_time) - navigator, ROI_region = self._create_navigator(worst_timeframe, main_plot, dataframe, description["Real_signals"]) + self._add_performance_label(result_layout, TWC_time, ideal_time, tesla_time) - layout.addWidget(plot_widget) + navigator, ROI_region = self._create_navigator(worst_timeframe, main_plot) + + plot_layout.addItem(plot_item, widget_num, 0) - layout.addWidget(navigator) + plot_layout.addItem(navigator, widget_num+1, 0) self._sync_main_plot_with_navigator(main_plot, ROI_region) main_plot.sigXRangeChanged.connect(lambda _, plot=main_plot, region=ROI_region: self._sync_navigator_with_main(main_plot=plot, region=region)) - widget.setLayout(layout) - return widget, reg_items, curve_items + result_layout.addWidget(plot_layout) + return result_widget, reg_items, curve_items def build(self, data: list[list[Any]]) -> None: """ diff --git a/src/utils/base/__pycache__/base.cpython-310.pyc b/src/utils/base/__pycache__/base.cpython-310.pyc index a931dec..37ad3b9 100644 Binary files a/src/utils/base/__pycache__/base.cpython-310.pyc and b/src/utils/base/__pycache__/base.cpython-310.pyc differ diff --git a/src/utils/base/base.py b/src/utils/base/base.py index 7b9a6a7..b48e234 100644 --- a/src/utils/base/base.py +++ b/src/utils/base/base.py @@ -240,27 +240,25 @@ class BasePlotWidget: def _create_navigator(self, time_region:tuple[float, float], - main_plot: pg.PlotWidget, - dataframe: pd.DataFrame, - real_signals: list[dict[str, Any]]) -> list[pg.PlotWidget, pg.LinearRegionItem]: + main_plot: pg.PlotItem) -> list[pg.PlotWidget, pg.LinearRegionItem]: """ Создаёт график-навигатор, отображающий все данные в уменьшенном масштабе. """ - navigator = pg.PlotWidget(title="Navigator") + navigator = pg.PlotItem(title="Navigator") navigator.setFixedHeight(100) - - for signal in real_signals: - if signal["name"] in dataframe.columns: - x = dataframe["time"] - y = dataframe[signal["name"]] - - x_downsampled, y_downsampled = self._downsample_data(x, y, max_points=1000) - navigator.plot(x_downsampled, y_downsampled, pen=signal["pen"], name=signal["name"]) + # Получение кривых из main_plot + for curve in main_plot.listDataItems(): + # Извлекаем данные из кривой + x, y = curve.getData() + curve_name = curve.opts.get("name", None) + signal_pen = curve.opts.get("pen", None) + x_downsampled, y_downsampled = self._downsample_data(x, y, max_points=1000) + navigator.plot(x_downsampled, y_downsampled, pen=signal_pen, name=curve_name) ROI_region = pg.LinearRegionItem(values=time_region, movable=True, brush=pg.mkBrush(0, 0, 255, 100), pen=pg.mkPen(width=4)) - ROI_region.setBounds([0, x.iloc[-1]]) + ROI_region.setBounds([0, x[-1]]) navigator.addItem(ROI_region) - navigator.getPlotItem().getViewBox().setLimits(xMin=0, xMax=x.iloc[-1]) + navigator.getViewBox().setLimits(xMin=0, xMax=x[-1]) # Связываем изменение региона навигатора с обновлением области просмотра основного графика ROI_region.sigRegionChanged.connect(lambda: self._sync_main_plot_with_navigator(main_plot, ROI_region)) @@ -268,7 +266,7 @@ class BasePlotWidget: return navigator, ROI_region def _sync_main_plot_with_navigator(self, - main_plot: pg.PlotWidget, + main_plot: pg.PlotItem, region: pg.LinearRegionItem): """ Синхронизирует область просмотра основного графика с регионом навигатора. @@ -301,7 +299,7 @@ class BasePlotWidget: dataframe[signal["name"]] = dataframe[signal["name"]].apply(lambda x: x + shift) return dataframe - def _sync_navigator_with_main(self, main_plot: pg.PlotWidget, region:pg.LinearRegionItem): + def _sync_navigator_with_main(self, main_plot: pg.PlotItem, region:pg.LinearRegionItem): """ Синхронизирует регион навигатора с областью просмотра основного графика. """