Подход PyQtGraph с накоплением графиков

Я хотел бы создать виджет, который отображает несколько сигналов времени друг над другом. Сигналы имеют одну и ту же ось времени, но разные оси значений. Оси времени должны быть пользовательского типа. Оси времени должны быть связаны.

Весь виджет должен отображаться в макете QHBox рядом с QListWidget с элементом с флажком для каждого сигнала, который позволяет пользователю включать или отключать отдельные графики.

В настоящее время у меня есть наполовину работающее решение, но я думаю, что делаю что-то неправильно на концептуальном уровне. Я не могу заставить autoSIprefix и метку для оси значений работать, и появляются странные плавающие оси, которых не должно быть.

Мой текущий виджет с плавающими осями слева и отсутствующими метками осей значений:

Мой текущий виджет с плавающими осями слева и отсутствующими метками осей значений

class MultiPlotWidget(QWidget):
    def __init__(self, parent, data_frame):
        super().__init__(parent)

        # Data
        self._df = data_frame
        self._grouped_data = self._grouped_data()
        # everything is enabled by default
        self._enabled_parameters = set(self._grouped_data.keys())
        self._parameter_name_map = lambda name: name

        self._plot_items = self._make_plot_items(self._grouped_data)

        # Plot widget
        self._fig_sa = QScrollArea(self)
        self._fig = pg.GraphicsLayoutWidget(self._fig_sa)
        self._fig.setMinimumSize(QSize(400, len(self._enabled_parameters) * 200))
        self._fig_sa.setWidgetResizable(True)
        self._fig_sa.setWidget(self._fig)

        # Side widget
        self._sw = SideWidget(self, sorted(self._enabled_parameters))
        self._sw.parameter_state_change.connect(self._parameter_state_change_action)

        # Layout
        h_layout = QHBoxLayout()
        h_layout.addWidget(self._fig_sa)
        h_layout.addWidget(self._sw)

        self.setLayout(h_layout)

        self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)

    def data(self):
        return self._df

    def set_parameter_name_map(self, pnm):
        self._parameter_name_map = pnm
        self._plot_items = self._make_plot_items(self._grouped_data)
        self._sw.set_parameter_name_map(pnm)

    def _grouped_data(self):
        """Regroup columns of self._df into a dict with groups with common
        name but different suffix e.g. self._df has columns ["foo/a",
        "foo/b", "foo/c"] then this function returns a dict {"foo": {"a": column
        foo/a , "b": column foo/b, "c": column foo/c}}

        """
        grouped = {}
        for col in self._df.columns:
            parts = col
            name = col
            suffix = DES
            if len(parts) == 2:
                name, suffix = parts
            if name not in grouped: grouped[name] = {}
            grouped[name].update({suffix: self._df[col].as_matrix()})

        return grouped

    def _make_plot_items(self, grouped_data):
        plot_items = {}

        last_vb = None
        for group_name in self._enabled_parameters:
            group_cols = grouped_data[group_name]
            ts_name = self._parameter_name_map(group_name)

            date_axis = DateAxisItem(self._df.index.to_series(), "bottom")

            pi = pg.PlotItem(axisItems={"bottom": date_axis# , "left": value_axis
                                    })
            pi.setLabel("left", ts_name, unit="m")

            vb = pi.getViewBox()

            pi.setTitle(ts_name)
            pi.showGrid(x=True, y=True, alpha=0.5)
            value_axis = pi.getAxis("left")
            value_axis.enableAutoSIPrefix()
            value_axis.setLabel(text=ts_name, unit="m")
            value_axis.showLabel(show=True)

            colormap = {DES: pg.hsvColor(0, 0, 1),
                        ADV: pg.hsvColor(0, 1, 1),
                        FAV: pg.hsvColor(0.33, 1, 1)}
            for suffix, col in group_cols.items():
                vb.setLimits(xMin=0, xMax=len(col)-1)
                pi.plot(col, name=suffix, antialias=True,
                        pen={"color": colormap.get(suffix, colormap[DES])})

            # # Only show legend if more than one curve per plot is
            # # present
            # if len(group_cols.items()) > 1:
            #     pi.addLegend()

            if last_vb is not None: # Link all time axes together
                last_vb.setXLink(vb)
                vb.setXLink(last_vb)
            last_vb = vb

            plot_items[group_name] = pi

        return plot_items

    def draw(self):
        self._fig.setMinimumSize(QSize(400, len(self._enabled_parameters) * 220))

        # Remove all items
        row = 0
        while True:
            try:
                item = self._fig.getItem(row, 0)
                # for child_item in item.allChildItems():
                #     item.removeItem(child_item)
                self._fig.removeItem(item)
                row += 1
            except Exception: # Thats exactly what pyqtgraph throws
                break

        # Insert the enabled plot items
        self._fig.clear()
        for group_name in sorted(self._enabled_parameters):
            self._fig.addItem(self._plot_items[group_name])
            self._fig.nextRow()

    def _parameter_state_change_action(self, tpl):
        """Handles enabling and disabling the display of time series when they
        are ticked or unticked in the side widget.

        """
        p_name, p_enabled = tpl
        if p_enabled:
            self._enabled_parameters.add(p_name)
        else:
            self._enabled_parameters.remove(p_name)

        self.draw()

Я внимательно просмотрел документацию и примеры, но не нашел ничего подходящего. Не могли бы вы дать мне подсказку о том, как реализовать функции, которые я хочу, «правильным» способом? Большое спасибо!


person callcc    schedule 20.10.2015    source источник


Ответы (1)


1) Плавающая ось

Это известная ошибка в PlotItem.py (PyQtGraph 0.9.10). Она будет исправлена ​​в более поздних версиях. Исправленный код уже доступен на GitHub https://github.com/pyqtgraph/pyqtgraph/blob/develop/pyqtgraph/graphicsItems/PlotItem/PlotItem.py. Извлечение репозитория и повторная установка исправили это для меня.

2) Единицы СИ -

Вы можете добавить автообновление единиц СИ в PlotItem, используя метод setLabels().

yourPlotItem.setLabels(left = ('Amplitude','V'))

Это установит «В» в качестве вашей единицы для левой оси, и она изменится на мВ, кВ и т. Д. В зависимости от масштабирования.

person JaqenTheMan    schedule 27.01.2016