From 05ee548704c3391e44e0d366a0a549022a705f2e Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 27 Jan 2025 19:12:02 +0300 Subject: [PATCH] =?UTF-8?q?chode:=20=D0=BD=D0=B0=D0=B2=D0=B8=D0=B3=D0=B0?= =?UTF-8?q?=D1=82=D0=BE=D1=80=20=D0=B2=D1=8B=D0=BD=D0=B5=D1=81=D0=B5=D0=BD?= =?UTF-8?q?=20=D0=B2=20=D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B?= =?UTF-8?q?=D0=B9=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/gui/plotter.py | 136 +++++++++++++++++++++++---------------------- 1 file changed, 70 insertions(+), 66 deletions(-) diff --git a/src/gui/plotter.py b/src/gui/plotter.py index 1885256..04eb29b 100644 --- a/src/gui/plotter.py +++ b/src/gui/plotter.py @@ -58,67 +58,6 @@ class PlotWidget(BasePlotWidget): # Notify mediator self._mediator.notify(self, widgets_datapack) - @staticmethod - def _downsample_data(x:list, y:list, max_points=5000): - """ - Понижает разрешение данных до заданного количества точек для улучшения производительности навигатора. - """ - if len(x) > max_points: - factor = len(x) // max_points - x_downsampled = x[::factor] - y_downsampled = y[::factor] - return x_downsampled, y_downsampled - return x, y - - def _create_navigator(self, - time_region:tuple[float, float], - main_plot: pg.PlotItem) -> Tuple[pg.PlotWidget, pg.LinearRegionItem]: - """ - Создаёт график-навигатор, отображающий все данные в уменьшенном масштабе. - """ - navigator = pg.PlotItem(title="Navigator") - navigator.setFixedHeight(100) - # Получение кривых из 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[-1]]) - navigator.addItem(ROI_region) - navigator.getViewBox().setLimits(xMin=0, xMax=x[-1]) - - # Связываем изменение региона навигатора с обновлением области просмотра основного графика - ROI_region.sigRegionChanged.connect(lambda: self._sync_main_plot_with_navigator(main_plot, ROI_region)) - return (navigator, ROI_region) - - @staticmethod - def _sync_main_plot_with_navigator(main_plot: pg.PlotItem, - region: pg.LinearRegionItem) -> None: - """ - Синхронизирует область просмотра основного графика с регионом навигатора. - """ - x_min, x_max = region.getRegion() - if main_plot: - main_plot.blockSignals(True) - main_plot.setXRange(x_min, x_max, padding=0) - main_plot.blockSignals(False) - - @staticmethod - def _sync_navigator_with_main(main_plot: pg.PlotItem, region:pg.LinearRegionItem): - """ - Синхронизирует регион навигатора с областью просмотра основного графика. - """ - if region: - x_min, x_max = main_plot - region.blockSignals(True) # Предотвращаем рекурсию - region.setRegion([x_min, x_max]) - region.blockSignals(False) - def _add_performance_label(self, layout: QVBoxLayout, timings: ChannelTimings, @@ -163,7 +102,6 @@ class PlotWidget(BasePlotWidget): """ container_widget, container_layout, plot_layout, pyqt_container = self._generate_widget_container() plotter = PlotItemGenerator(graphic_passport, len(self._plt_channels), self._stage_colors) - for widget_num, (channel, description) in enumerate(self._plt_channels.items()): plot_item, plot_timings = plotter.generate_plot_item(widget_num, channel, description, pyqt_container) @@ -179,11 +117,9 @@ class PlotWidget(BasePlotWidget): plot_layout.addItem(plot_item, widget_num, 0) - navigator, ROI_region = self._create_navigator(plot_timings.worst_timeframe, main_plot) + navigator = NavigatorPlot(plot_timings.worst_timeframe, main_plot) if navigator is not None: 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)) container_layout.addWidget(plot_layout) container_widget.setProperty("pyqt_container", pyqt_container) @@ -517,4 +453,72 @@ class PlotItemGenerator: dataframe.loc[point_idxs] = self._shift_data("FE", real_signals, dataframe.loc[point_idxs], lambda x: x + F_comp) return dataframe - \ No newline at end of file +class NavigatorPlot(pg.PlotItem): + def __init__(self, + time_region:tuple[float, float], + main_plot: pg.PlotItem): + super().__init__() + self._init_navigator(time_region, main_plot) + + @staticmethod + def _downsample_data(x:list, y:list, max_points=5000): + """ + Понижает разрешение данных до заданного количества точек для улучшения производительности навигатора. + """ + if len(x) > max_points: + factor = len(x) // max_points + x_downsampled = x[::factor] + y_downsampled = y[::factor] + return x_downsampled, y_downsampled + return x, y + + @staticmethod + def _sync_main_plot_with_navigator(main_plot: pg.PlotItem, + region: pg.LinearRegionItem) -> None: + """ + Синхронизирует область просмотра основного графика с регионом навигатора. + """ + x_min, x_max = region.getRegion() + if main_plot: + main_plot.blockSignals(True) + main_plot.setXRange(x_min, x_max, padding=0) + main_plot.blockSignals(False) + + @staticmethod + def _sync_navigator_with_main(main_plot: pg.PlotItem, region:pg.LinearRegionItem): + """ + Синхронизирует регион навигатора с областью просмотра основного графика. + """ + if region: + x_min, x_max = main_plot + region.blockSignals(True) # Предотвращаем рекурсию + region.setRegion([x_min, x_max]) + region.blockSignals(False) + + def _init_navigator(self, + time_region:tuple[float, float], + main_plot: pg.PlotItem) -> None: + """ + Создаёт график-навигатор, отображающий все данные в уменьшенном масштабе. + """ + self.setTitle("Navigator") + self.setFixedHeight(100) + # Получение кривых из 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) + self.plot(x_downsampled, y_downsampled, pen=signal_pen, name=curve_name) + + self.ROI_region = pg.LinearRegionItem(values=time_region, movable=True, brush=pg.mkBrush(0, 0, 255, 100), pen=pg.mkPen(width=4)) + self.ROI_region.setBounds([0, x[-1]]) + self.addItem(self.ROI_region) + self.getViewBox().setLimits(xMin=0, xMax=x[-1]) + + # Связываем изменение региона навигатора с обновлением области просмотра основного графика + self.ROI_region.sigRegionChanged.connect(lambda: self._sync_main_plot_with_navigator(main_plot, self.ROI_region)) + main_plot.sigXRangeChanged.connect(lambda _, plot=main_plot, region=self.ROI_region: self._sync_navigator_with_main(main_plot=plot, region=region)) + + \ No newline at end of file