Получение ошибки рекурсии при соединении линейногорегионита pyqtgraph с осью плотита - PullRequest
0 голосов
/ 12 июня 2018

Я пытаюсь сделать что-то похожее на то, что сделано в примере с pyqtgraph 'Crosshair / Mouse Interaction'.По сути, я хочу подключить элемент линейной области на одном графике к оси X на другом графике.затем на одном графике будут отображаться данные, которые находятся в линейном региональном элементе, и вы можете увеличивать и уменьшать масштаб, изменяя линейный региональный элемент и наоборот.

Моя проблема заключается в том, что происходит сбой при:

RecursionError: максимальная глубина рекурсии превышена при вызове объекта Python

Вот код из примера, если вы хотите попробовать его, чтобы дать вам представление о том, что я хочу сделать ...

"""
Demonstrates some customized mouse interaction by drawing a crosshair that follows 
the mouse.


"""
import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore
from pyqtgraph.Point import Point

#generate layout
app = QtGui.QApplication([])
win = pg.GraphicsWindow()
win.setWindowTitle('pyqtgraph example: crosshair')
label = pg.LabelItem(justify='right')
win.addItem(label)
p1 = win.addPlot(row=1, col=0)
p2 = win.addPlot(row=2, col=0)

region = pg.LinearRegionItem()
region.setZValue(10)
# Add the LinearRegionItem to the ViewBox, but tell the ViewBox to exclude this 
# item when doing auto-range calculations.
p2.addItem(region, ignoreBounds=True)

#pg.dbg()
p1.setAutoVisible(y=True)


#create numpy arrays
#make the numbers large to show that the xrange shows data from 10000 to all the way 0
data1 = 10000 + 15000 * pg.gaussianFilter(np.random.random(size=10000), 10) + 3000 * np.random.random(size=10000)
data2 = 15000 + 15000 * pg.gaussianFilter(np.random.random(size=10000), 10) + 3000 * np.random.random(size=10000)

p1.plot(data1, pen="r")
p1.plot(data2, pen="g")

p2.plot(data1, pen="w")

def update():
    region.setZValue(10)
    minX, maxX = region.getRegion()
    p1.setXRange(minX, maxX, padding=0)    

region.sigRegionChanged.connect(update)

def updateRegion(window, viewRange):
    rgn = viewRange[0]
    region.setRegion(rgn)

p1.sigRangeChanged.connect(updateRegion)

region.setRegion([1000, 2000])

#cross hair
vLine = pg.InfiniteLine(angle=90, movable=False)
hLine = pg.InfiniteLine(angle=0, movable=False)
p1.addItem(vLine, ignoreBounds=True)
p1.addItem(hLine, ignoreBounds=True)


vb = p1.vb

def mouseMoved(evt):
    pos = evt[0]  ## using signal proxy turns original arguments into a tuple
    if p1.sceneBoundingRect().contains(pos):
        mousePoint = vb.mapSceneToView(pos)
        index = int(mousePoint.x())
        if index > 0 and index < len(data1):
            label.setText("<span style='font-size: 12pt'>x=%0.1f,   <span style='color: red'>y1=%0.1f</span>,   <span style='color: green'>y2=%0.1f</span>" % (mousePoint.x(), data1[index], data2[index]))
        vLine.setPos(mousePoint.x())
        hLine.setPos(mousePoint.y())



proxy = pg.SignalProxy(p1.scene().sigMouseMoved, rateLimit=60, slot=mouseMoved)
#p1.scene().sigMouseMoved.connect(mouseMoved)


## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
    import sys
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()

Если вы не хотите читать все это, линейный регионит и плотитем связаны между собой линиями ...

def update():
    region.setZValue(10)
    minX, maxX = region.getRegion()
    p1.setXRange(minX, maxX, padding=0)    

region.sigRegionChanged.connect(update)

def updateRegion(window, viewRange):
    rgn = viewRange[0]
    region.setRegion(rgn)

p1.sigRangeChanged.connect(updateRegion)


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

Когда вы запустите его, он потерпит крах, если вы отрегулируете linearregionitem,или если вы измените ось plotA.Если вы закомментируете одну из строк 'connect', программа будет работать (наполовину).

import pyqtgraph as pg
import sys

# PyQt5 includes
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication


class MyApplicationWindow(QtWidgets.QMainWindow):

    def __init__(self):
        super().__init__()
        self.__buildUI()


    def __buildUI(self):

        plotWidget = pg.GraphicsLayoutWidget()

        self.PlotA = pg.PlotItem()
        self.PlotA.setXRange(10, 20)


        self.PlotB = pg.PlotItem()
        self.PlotB.setXRange(0, 100)


        self.lri = pg.LinearRegionItem()
        self.lri.setRegion((10, 20))
        self.PlotB.addItem(self.lri)

        # The following two connections set up a recursive loop
        self.lri.sigRegionChanged.connect(self.update)
        self.PlotA.sigRangeChanged.connect(self.update_lri)

        plotWidget.addItem(self.PlotA)
        plotWidget.nextRow()
        plotWidget.addItem(self.PlotB)

        self.setCentralWidget(plotWidget)

        self.show()


    def update(self):
        minX, maxX = self.lri.getRegion()
        self.PlotA.setXRange(minX, maxX)


    def update_lri(self, window, viewRange):
        A_xrange = viewRange[0]
        self.lri.setRegion(A_xrange)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    widget = MyApplicationWindow()
    sys.exit(app.exec_())

Что происходит?Может кто-нибудь сказать мне, как заставить это работать?Это в Python 3.6

1 Ответ

0 голосов
/ 20 июня 2018

+ 1 для доказательства хорошего MVCE .Это позволило мне немного поэкспериментировать, и я нашел проблему.Без него невозможно было бы решить.

При обновлении диапазона x графика вы должны установить отступ на ноль.Поэтому измените метод update на:

def update(self):
    minX, maxX = self.lri.getRegion()
    self.PlotA.setXRange(minX, maxX, padding=0)

Как правило, с помощью QT эти бесконечные циклы сигнала предотвращаются только путем обновления переменной (и выдачи соответствующего сигнала), когда новое значение отличается от старого значения.Где-то в Qt / PyQtGraph эта проверка также выполняется.Но так как ваше заполнение не равно нулю, новый xrange будет немного больше старого xrange каждую итерацию, и цикл не заканчивается.

Кстати, в Python принято, чтобы имена переменных начиналисьс символом нижнего регистра и именами классов с верхним регистром.Я рекомендую переименовать self.PlotA в self.plotA.Это делает ваш код более читабельным для других программистов Python.Также это даст лучшую подсветку синтаксиса здесь при переполнении стека.

...