How to use pyqtgraph's Graphics Items in PySide application

1,899 views
Skip to first unread message

Joschka

unread,
Jul 24, 2012, 11:48:25 AM7/24/12
to pyqt...@googlegroups.com
Hi,

first of all I would like to thank all contributors for their efforts, I'm impressed by the speed of pyqtgraph's examples and really interested to try some of its features in my application.

In my existing PySide application I display a live image from a camera as a QGraphicsPixmapItem in a QGraphicsScene. Now, I want to display some overlays (sharpness measure etc.) on top of this item using pyqtgraph. A simple plot of a grid of crosses is already working using the following code (excerpt is taken from a class method and cannot be executed on its own):

from matplotlib import cm
import pyqtgraph as pq

# [...]
# just the plotting part:
plot_item = pg.PlotItem()
# These are lists of values
x, y, sharpness_values = sharpness.sharpness_grid_to_arrays(
    self._sharpness_grid)
colormap = cm.get_cmap("RdYlGn")
marker_colors = colormap(sharpness_values)
color_tuples = []
for color in marker_colors:
    color = color * 255.
    # Each color is a list: [R, G, B, A]
    color_tuples.append(tuple(color))
plot = plot_item.plot(x=x, y=y, pen=None, symbol='+', symbolSize=10,
     symbolPen=color_tuples)   
# Method is called periodically for every image, keep track of plots
# and remove them using self._scene.removeItem(...)
self._plot_items.append(plot)
# self._scene is a PySide.QtGui.QGraphicsScene object
self._scene.addItem(plot)

This works and displays the plot just fine. However, I receive the following error after each update of the plot:

Traceback (most recent call last):
File "C:\Python27\lib\site-packages\pyqtgraph\graphicsItems\GraphicsObject.py", line 19, in itemChange
self._updateView()
File "C:\Python27\lib\site-packages\pyqtgraph\graphicsItems\GraphicsItem.py", line 382, in _updateView
view.sigRangeChanged.connect(self.viewRangeChanged)
AttributeError: 'GraphicsView' object has no attribute 'sigRangeChanged'

I think this might be caused by the fact, that I don't use pyqtgraph.ViewBox as a container. Does anybody have any experience on how to combine a PySide QGraphicsScene and pyqtgraph plots? Should I integrate my QGraphicsPixmapItem into a pyqtgraph.GraphicsScene?  I would prefer to stick with the PySide QGraphicsScene as we already have written some UI code for region selection and I'm not sure if the view code will work with pyqtgraph's objects without modification. Later, we could migrate to pyqtgraph's ROI objects but first I want to evaluate the plot possibilities and processing speed in some real applications.

Another thing that I would like to integrate is a grid as in the example "ROIExamples.py" (bottom right corner), but I don't know which object to create and add to my scene.
Any pointers or suggestions are appreciated.

Thanks in advance and best regards

Joschka

Luke Campagnola

unread,
Jul 27, 2012, 2:16:46 PM7/27/12
to pyqt...@googlegroups.com
Hi Joschka,

Sorry for the delay in responding; I'm out of town at the moment. What you are trying to do--use pyqtgraph's graphics items in the absence of GraphicsView and GraphicsScene--is something I had originally envisioned would be possible with the library, but over time I came to depend more and more on the services provided in GraphicsView and GraphicsScene. It is still sotr-of possible to do what you want (as you have seen), but you can expect to run into a few bugs. 

See further responses below..

On Tue, Jul 24, 2012 at 11:48 AM, Joschka <j...@lfb.rwth-aachen.de> wrote:
In my existing PySide application I display a live image from a camera as a QGraphicsPixmapItem in a QGraphicsScene. Now, I want to display some overlays (sharpness measure etc.) on top of this item using pyqtgraph. A simple plot of a grid of crosses is already working using the following code (excerpt is taken from a class method and cannot be executed on its own): 

from matplotlib import cm
import pyqtgraph as pq

# [...]
# just the plotting part:
plot_item = pg.PlotItem()
# These are lists of values
x, y, sharpness_values = sharpness.sharpness_grid_to_arrays(
    self._sharpness_grid)
colormap = cm.get_cmap("RdYlGn")
marker_colors = colormap(sharpness_values)
color_tuples = []
for color in marker_colors:
    color = color * 255.
    # Each color is a list: [R, G, B, A]
    color_tuples.append(tuple(color))
plot = plot_item.plot(x=x, y=y, pen=None, symbol='+', symbolSize=10,
     symbolPen=color_tuples)

Just a note about this--it is not necessary to create a PlotItem for this purpose. You can instead just create pyqtgraph.PlotDataItem instances using the same arguments.
 
# Method is called periodically for every image, keep track of plots
# and remove them using self._scene.removeItem(...)
self._plot_items.append(plot)
# self._scene is a PySide.QtGui.QGraphicsScene object
self._scene.addItem(plot)

This works and displays the plot just fine. However, I receive the following error after each update of the plot:

Traceback (most recent call last):
File "C:\Python27\lib\site-packages\pyqtgraph\graphicsItems\GraphicsObject.py", line 19, in itemChange
self._updateView()
File "C:\Python27\lib\site-packages\pyqtgraph\graphicsItems\GraphicsItem.py", line 382, in _updateView
view.sigRangeChanged.connect(self.viewRangeChanged)
AttributeError: 'GraphicsView' object has no attribute 'sigRangeChanged'

I presume 'GraphicsView' is a class of your making and not pyqtgraph.GraphicsView (because the latter does have sigRangeChanged) ? It is not absolutely necessary to use a ViewBox, but if you do not want to use the pyqtgraph.GraphicsView widget, you will probably need to reimplement some of its functionality. The main issue is that, in order to keep the size of the symbols constant when the view is scaled, the PlotDataItem must be informed that the view has changed. 

We might be able to find a simpler solution for your application if you can tell me a bit more about how you are using the GraphicsView. Most importantly, do you have a way to scale the view? If not, then the plot never needs to know if the view range has changed, and it should be simple enough to just remove this dependency from GraphicsItem.
 
I think this might be caused by the fact, that I don't use pyqtgraph.ViewBox as a container. Does anybody have any experience on how to combine a PySide QGraphicsScene and pyqtgraph plots? Should I integrate my QGraphicsPixmapItem into a pyqtgraph.GraphicsScene?  I would prefer to stick with the PySide QGraphicsScene as we already have written some UI code for region selection and I'm not sure if the view code will work with pyqtgraph's objects without modification. Later, we could migrate to pyqtgraph's ROI objects but first I want to evaluate the plot possibilities and processing speed in some real applications.

pyqtgraph.GraphicsScene provides a variety of services that are not available in QGraphicsScene. Most importantly, it implements a system of mouse events used throughout pyqtgraph for mouse interaction. Unfortunately Qt's mouse event system was not really capable of the behavior I wanted. There is a lot of documentation in the source for GraphicsScene that describes those changes. 

I would definitely recommend using pyqtgraph's GraphicsScene if possible. If you find that this causes problems for the code you already have written, then let me know and I'll see if it can be fixed from my end.
 
Another thing that I would like to integrate is a grid as in the example "ROIExamples.py" (bottom right corner), but I don't know which object to create and add to my scene.

This is pyqtgraph.GridItem, but it is pretty unlikely to work properly without being inside either a ViewBox or pyqtgraph.GraphicsView for the same reason I described above.

Luke

Joschka

unread,
Aug 21, 2012, 3:13:56 AM8/21/12
to pyqt...@googlegroups.com
Hi Luke,

thanks for your response, it seems my email updates were disabled and your post did not show up in the RSS feed, so I totally missed it until now, sorry!

On Friday, July 27, 2012 8:16:46 PM UTC+2, Luke Campagnola wrote:
I presume 'GraphicsView' is a class of your making and not pyqtgraph.GraphicsView (because the latter does have sigRangeChanged) ? It is not absolutely necessary to use a ViewBox, but if you do not want to use the pyqtgraph.GraphicsView widget, you will probably need to reimplement some of its functionality. The main issue is that, in order to keep the size of the symbols constant when the view is scaled, the PlotDataItem must be informed that the view has changed. 

It is indeed a custom class based on a standard QGraphicsView . I read in the docs that you extended the standard graphics classes to enable mouse control in plots etc. but as I don't use the plot interactively I tried it this way to get a working prototype. I was comparing the possibilities of guiqwt and pyqtgraph in my application and wanted to get a quick preview to estimate the possible speed etc.

We might be able to find a simpler solution for your application if you can tell me a bit more about how you are using the GraphicsView. Most importantly, do you have a way to scale the view? If not, then the plot never needs to know if the view range has changed, and it should be simple enough to just remove this dependency from GraphicsItem.

My application displays a live image from a camera and allows zooming, its implementation uses Qt's scale() method on QGraphicsView object(s) (the application provides an optional split view of the scene).

I would definitely recommend using pyqtgraph's GraphicsScene if possible. If you find that this causes problems for the code you already have written, then let me know and I'll see if it can be fixed from my end.

Thank you for your offer. When I look into this I will let you know if we succeded in using pyqtgraph's GraphicsScene.
 
Another thing that I would like to integrate is a grid as in the example "ROIExamples.py" (bottom right corner), but I don't know which object to create and add to my scene.

This is pyqtgraph.GridItem, but it is pretty unlikely to work properly without being inside either a ViewBox or pyqtgraph.GraphicsView for the same reason I described above.

 Ok, this confirms my first impressions, I will try it once we use pyqtgraph's graphics classes.

Best regards

Joschka
Reply all
Reply to author
Forward
0 new messages