chode: навигатор вынесен в отдельный класс
This commit is contained in:
parent
93be450da6
commit
05ee548704
@ -58,67 +58,6 @@ class PlotWidget(BasePlotWidget):
|
|||||||
# Notify mediator
|
# Notify mediator
|
||||||
self._mediator.notify(self, widgets_datapack)
|
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,
|
def _add_performance_label(self,
|
||||||
layout: QVBoxLayout,
|
layout: QVBoxLayout,
|
||||||
timings: ChannelTimings,
|
timings: ChannelTimings,
|
||||||
@ -163,7 +102,6 @@ class PlotWidget(BasePlotWidget):
|
|||||||
"""
|
"""
|
||||||
container_widget, container_layout, plot_layout, pyqt_container = self._generate_widget_container()
|
container_widget, container_layout, plot_layout, pyqt_container = self._generate_widget_container()
|
||||||
plotter = PlotItemGenerator(graphic_passport, len(self._plt_channels), self._stage_colors)
|
plotter = PlotItemGenerator(graphic_passport, len(self._plt_channels), self._stage_colors)
|
||||||
|
|
||||||
|
|
||||||
for widget_num, (channel, description) in enumerate(self._plt_channels.items()):
|
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)
|
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)
|
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:
|
if navigator is not None:
|
||||||
plot_layout.addItem(navigator, widget_num+1, 0)
|
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_layout.addWidget(plot_layout)
|
||||||
container_widget.setProperty("pyqt_container", pyqt_container)
|
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)
|
dataframe.loc[point_idxs] = self._shift_data("FE", real_signals, dataframe.loc[point_idxs], lambda x: x + F_comp)
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
|
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))
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user