Issue
I need to select and get data of two graphics from plots, I found a example, where it is created a custom viewbox and then create a plot like that pw = pg.PlotWidget(viewBox=vb), however I don't know how to do it when we have the plot as a Qt Creator promoted pyqtgraph widget. Below is the example that I found in a forum (link: https://groups.google.com/forum/#!topic/pyqtgraph/pTrem1RCKSw) Here is the code (works perfectly)
import numpy as np
import pyqtgraph as pg
from pyqtgraph.Point import Point
from pyqtgraph.graphicsItems.ItemGroup import ItemGroup
from pyqtgraph.Qt import QtGui, QtCore
from matplotlib.mlab import inside_poly
from pyqtgraph.graphicsItems import ScatterPlotItem
class ChildGroup(ItemGroup):
sigItemsChanged = QtCore.Signal()
def __init__(self, parent):
ItemGroup.__init__(self, parent)
# excempt from telling view when transform changes
self._GraphicsObject__inform_view_on_change = False
def itemChange(self, change, value):
ret = ItemGroup.itemChange(self, change, value)
if change == self.ItemChildAddedChange or change == self.ItemChildRemovedChange:
self.sigItemsChanged.emit()
return ret
class MyViewBox(pg.ViewBox):
def mouseDragEvent(self, ev):
if ev.button() == QtCore.Qt.RightButton:
ev.ignore()
else:
pg.ViewBox.mouseDragEvent(self, ev)
ev.accept()
pos = ev.pos()
if ev.button() == QtCore.Qt.RightButton:
if ev.isFinish():
self.rbScaleBox.hide()
self.ax = QtCore.QRectF(Point(ev.buttonDownPos(ev.button())), Point(pos))
self.ax = self.childGroup.mapRectFromParent(self.ax)
self.Coords = self.ax.getCoords()
self.getdataInRect()
self.changePointsColors()
else:
self.updateScaleBox(ev.buttonDownPos(), ev.pos())
def getdataInRect(self):
# Get the data from the Graphicsitem
self.getDataItem()
x = self.dataxy[0]
y = self.dataxy[1]
# Rect Edges
Xbl = (self.Coords[0],self.Coords[1]) # bottom left
Xbr = (self.Coords[2],self.Coords[1]) # bottom right
Xtr = (self.Coords[2],self.Coords[3]) # top right
Xtl = (self.Coords[0],self.Coords[3]) # top left
#Make a list of [(x0,y0),(x1,y1) ...]
self.xy = list()
for i in x:
tmp = (x[i],y[i])
self.xy.append(tmp)
self.insideIndex = inside_poly(self.xy,[Xbl, Xbr, Xtr, Xtl])
def getDataItem(self):
self.ObjItemList = pg.GraphicsScene.items(self.scene(),self.ax)
self.dataxy = self.ObjItemList[0].listDataItems()[0].getData()
def changePointsColors(self):
print(self.xy)
print(self.insideIndex)
app = QtGui.QApplication([])
mw = QtGui.QMainWindow()
mw.resize(800,500)
mw.show()
vb = MyViewBox()
pw = pg.PlotWidget(viewBox=vb)
a = np.array([0,1,2,3,4,5,6,7,8,9,10])
b = np.array([0,1,2,3,4,5,6,7,8,9,10])
curve0 = pw.plot(a,b, clickable=True, symbol = '+')
mw.setCentralWidget(pw)
# 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_()
How could I adapt the previous code to the PlotWidget "Plot1"?
class MyApp(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
pg.setConfigOption('background', 'w')
QtWidgets.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
self.Plot1.plotItem.showGrid(True, True, 0.7)
self.Plot1.setLabel('left', 'q1')
self.Plot1.setLabel('bottom', 'Time', units='s')
self.Plot1.setTitle(title='q1')
pen = pg.mkPen({'color': "FF0000", 'width': 2})
pen1 = pg.mkPen({'color': "00FF00", 'width': 2})
self.Plot1.addLegend()
self.q1z = self.Plot1.plot(pen = pen, name = 'Trace 1')
self.q1k = self.Plot1.plot(pen = pen1, name = 'Trace 2')
Here the file Sample.ui
could someone help me?
Solution
The solution is to create a class that inherits from PlotWidget and has a viewbox to MyViewBox and then promote that widget:
plotwidget.py
import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore
try:
from matplotlib.mlab import inside_poly
except ImportError:
# https://matplotlib.org/3.1.0/api/api_changes.html
# mlab.inside_poly has been removed in matplotlib 3.1.0
from matplotlib.path import Path
def inside_poly(points, verts):
poly = Path(verts)
return [idx for idx, p in enumerate(points) if poly.contains_point(p)]
class ChildGroup(pg.ItemGroup):
sigItemsChanged = QtCore.Signal()
def __init__(self, parent):
super(ChildGroup, self).__init__(parent)
# excempt from telling view when transform changes
self._GraphicsObject__inform_view_on_change = False
def itemChange(self, change, value):
ret = ItemGroup.itemChange(self, change, value)
if change == self.ItemChildAddedChange or change == self.ItemChildRemovedChange:
self.sigItemsChanged.emit()
return ret
class MyViewBox(pg.ViewBox):
def mouseDragEvent(self, ev):
if ev.button() == QtCore.Qt.RightButton:
ev.ignore()
else:
pg.ViewBox.mouseDragEvent(self, ev)
ev.accept()
pos = ev.pos()
if ev.button() == QtCore.Qt.RightButton:
if ev.isFinish():
self.rbScaleBox.hide()
self.ax = QtCore.QRectF(
pg.Point(ev.buttonDownPos(ev.button())), pg.Point(pos)
)
self.ax = self.childGroup.mapRectFromParent(self.ax)
self.Coords = self.ax.getCoords()
self.getdataInRect()
self.changePointsColors()
else:
self.updateScaleBox(ev.buttonDownPos(), ev.pos())
def getdataInRect(self):
# Get the data from the Graphicsitem
self.getDataItem()
x = self.dataxy[0]
y = self.dataxy[1]
# Rect Edges
Xbl = (self.Coords[0], self.Coords[1]) # bottom left
Xbr = (self.Coords[2], self.Coords[1]) # bottom right
Xtr = (self.Coords[2], self.Coords[3]) # top right
Xtl = (self.Coords[0], self.Coords[3]) # top left
# Make a list of [(x0,y0),(x1,y1) ...]
self.xy = list()
for i in x:
tmp = (x[i], y[i])
self.xy.append(tmp)
self.insideIndex = inside_poly(self.xy, [Xbl, Xbr, Xtr, Xtl])
def getDataItem(self):
self.ObjItemList = pg.GraphicsScene.items(self.scene(), self.ax)
self.dataxy = self.ObjItemList[0].listDataItems()[0].getData()
def changePointsColors(self):
print(self.xy)
print(self.insideIndex)
class MyPlotWidget(pg.PlotWidget):
def __init__(self, parent=None):
super(MyPlotWidget, self).__init__(parent, viewBox=MyViewBox())
Sample.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>487</width>
<height>368</height>
</rect>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>86</red>
<green>86</green>
<blue>86</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>86</red>
<green>86</green>
<blue>86</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>86</red>
<green>86</green>
<blue>86</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>86</red>
<green>86</green>
<blue>86</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>30</number>
</property>
<property name="topMargin">
<number>40</number>
</property>
<property name="rightMargin">
<number>40</number>
</property>
<property name="bottomMargin">
<number>30</number>
</property>
<item>
<widget class="MyPlotWidget" name="Plot1">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="backgroundBrush">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>MyPlotWidget</class>
<extends>QGraphicsView</extends>
<header>plotwidget</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
pyuic5 Sample.ui -o sample.py -x
main.py
from PyQt5 import QtWidgets
import pyqtgraph as pg
from sample import Ui_Dialog
class MyApp(QtWidgets.QDialog, Ui_Dialog):
def __init__(self, parent=None):
super(MyApp, self).__init__(parent)
pg.setConfigOption("background", "w")
self.setupUi(self)
self.Plot1.plotItem.showGrid(True, True, 0.7)
self.Plot1.setLabel("left", "q1")
self.Plot1.setLabel("bottom", "Time", units="s")
self.Plot1.setTitle(title="q1")
pen = pg.mkPen({"color": "FF0000", "width": 2})
pen1 = pg.mkPen({"color": "00FF00", "width": 2})
self.Plot1.addLegend()
self.q1z = self.Plot1.plot(pen=pen, name="Trace 1")
self.q1k = self.Plot1.plot(pen=pen1, name="Trace 2")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MyApp()
w.show()
sys.exit(app.exec_())
├── main.py
├── plotwidget.py
├── sample.py
└── Sample.ui
Answered By - eyllanesc
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.