Is there a selection widget?

2,509 views
Skip to first unread message

pyqtgraphuser

unread,
Mar 31, 2012, 10:22:08 AM3/31/12
to pyqt...@googlegroups.com
Is there a selection widget that I can add to a plot window. Here is the flow I need to implement:

When the user (presses some key [maybe ctrl]. It can't be the mouse click button since that already controls zoom) and moves the mouse, One vertical infinite line appears and as the mouse gets moved the region selected by the mouse gets highlighted. When the key is released a handler is called with the selected x, y (in data points) coordinates of the selected region. Using this, I would open another pyqtgraph window with more detailed charts for the selected region. 


megan kratz

unread,
Mar 31, 2012, 11:46:27 AM3/31/12
to pyqt...@googlegroups.com
On Sat, Mar 31, 2012 at 10:22 AM, pyqtgraphuser <webus...@gmail.com> wrote:
Is there a selection widget that I can add to a plot window. Here is the flow I need to implement:

When the user (presses some key [maybe ctrl]. It can't be the mouse click button since that already controls zoom) and moves the mouse, One vertical infinite line appears and as the mouse gets moved the region selected by the mouse gets highlighted. When the key is released a handler is called with the selected x, y (in data points) coordinates of the selected region. Using this, I would open another pyqtgraph window with more detailed charts for the selected region. 


What you want sounds a lot like a LinearRegionItem. I don't think there are methods yet for adding them to the plot using the mouse in the way you described, but aside from that they can do what you're describing. Once a LinearRegionItem is added to a plot, it is movable with the mouse, so you can still adjust it's position that way.

For an example of how to use a LinearRegionItem to select data in one plot to be re-plotted in another plot see pyqtgraph/examples/Plotting.py, particularly plots 8 & 9 (line 73 -86). This file can be run on it's own to give you a sense of how LinearRegionItems act.

Cheers,

Megan

Luke Campagnola

unread,
Mar 31, 2012, 9:21:18 PM3/31/12
to pyqt...@googlegroups.com
On Sat, Mar 31, 2012 at 11:46, megan kratz <megan...@gmail.com> wrote:

On Sat, Mar 31, 2012 at 10:22 AM, pyqtgraphuser <webus...@gmail.com> wrote:
Is there a selection widget that I can add to a plot window. Here is the flow I need to implement:

When the user (presses some key [maybe ctrl]. It can't be the mouse click button since that already controls zoom) and moves the mouse, One vertical infinite line appears and as the mouse gets moved the region selected by the mouse gets highlighted. When the key is released a handler is called with the selected x, y (in data points) coordinates of the selected region. Using this, I would open another pyqtgraph window with more detailed charts for the selected region. 


What you want sounds a lot like a LinearRegionItem.

I'll agree with Megan and add that you would need to extend the mouseDragEvent method for the plot's ViewBox to implement this functionality. Here's a simple example (use ctrl-drag to set the region):

import pyqtgraph as pg
from PyQt4 import QtCore
pw = pg.plot()
lr = pg.LinearRegionItem()
lr.hide()
pw.addItem(lr)
vb = pw.plotItem.vb  ## get the viewbox from the plot item

def drag(ev):
    global vb, lr
    if (ev.button() == QtCore.Qt.LeftButton) and (ev.modifiers() & QtCore.Qt.ControlModifier):
        lr.show()
        lr.setRegion([vb.mapToView(ev.buttonDownPos()).x(), vb.mapToView(ev.pos()).x()])
        ev.accept()
    else:
        pg.ViewBox.mouseDragEvent(vb, ev)

vb.mouseDragEvent = drag


pyqtgraphuser

unread,
Apr 10, 2012, 5:26:01 AM4/10/12
to pyqtgraph
> I'll agree with Megan and add that you would need to extend the
> mouseDragEvent method for the plot's ViewBox to implement this
> functionality. Here's a simple example (use ctrl-drag to set the region):

Thanks. How would I open the selected region in a completely new plot
window?

Luke Campagnola

unread,
Apr 13, 2012, 4:32:45 PM4/13/12
to pyqt...@googlegroups.com
On Tuesday, April 10, 2012 5:26:01 AM UTC-4, pyqtgraphuser wrote:
Thanks. How would I open the selected region in a completely new plot
window?

This is just a repeat of code you've already used--Create a new plot by any method (pg.plot(), pg.PlotWidget, GraphicsLayout.addPlot, etc.) then plot your data there and set the bounds with the setRange method. 

pyqtgraphuser

unread,
Apr 15, 2012, 8:04:10 AM4/15/12
to pyqt...@googlegroups.com
This is just a repeat of code you've already used--Create a new plot by any method (pg.plot(), pg.PlotWidget, GraphicsLayout.addPlot, etc.) then plot your data there and set the bounds with the setRange method. 

Ok I get it now. here is the example code I have so far. How do I capture a key release event (some way to capture release of the ctrl key) on the viewbox. I tried this and did not work:

def release(ev):
   #somehow capture release 
    win = pg.GraphicsWindow()
    label = pg.LabelItem(justify='right')
    win.addItem(label)
    p1 = win.addPlot(row=1, col=0)
    p1.plot(data1, pen="r")
vb.keyReleaseEvent = release

Full working example as a hack to just demonstrate open a new window:

------------------------------------------------------------------------------------------

import initExample ## Add path to library (just for examples; you do not need this)
import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore
from pyqtgraph.Point import Point

#genearte layout
app = QtGui.QApplication([])
win = pg.GraphicsWindow()
p1 = win.addPlot(row=1, col=0)

data1 = 10000 + 3000 * np.random.random(size=10000)
p1.plot(data1, pen="r")

lr = pg.LinearRegionItem()
lr.hide()
p1.addItem(lr)
vb = p1.vb  ## get the viewbox from the plot item

count = 0
def drag(ev):
    global vb, lr, count
    if (ev.button() == QtCore.Qt.LeftButton) and (ev.modifiers() & QtCore.Qt.ControlModifier):
        lr.show()
        lr.setRegion([vb.mapToView(ev.buttonDownPos()).x(), vb.mapToView(ev.pos()).x()])
        ev.accept()
        count = count + 1
        if count == 40:
            win = pg.GraphicsWindow()
            label = pg.LabelItem(justify='right')
            win.addItem(label)
            p1 = win.addPlot(row=1, col=0)
            p1.plot(data1, pen="r")
    else:
        pg.ViewBox.mouseDragEvent(vb, ev)

vb.mouseDragEvent = drag

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

Luke Campagnola

unread,
Apr 15, 2012, 10:32:05 AM4/15/12
to pyqt...@googlegroups.com
On Sun, Apr 15, 2012 at 08:04, pyqtgraphuser <webus...@gmail.com> wrote:
Ok I get it now. here is the example code I have so far. How do I capture a key release event (some way to capture release of the ctrl key) on the viewbox. I tried this and did not work:

def release(ev):
   #somehow capture release 
    win = pg.GraphicsWindow()
    label = pg.LabelItem(justify='right')
    win.addItem(label)
    p1 = win.addPlot(row=1, col=0)
    p1.plot(data1, pen="r")
vb.keyReleaseEvent = release


Aha.. I have fixed a bug that was preventing the scene from giving keyboard focus to the ViewBox. You can download the latest or just merge in the changes from rev. 80.

From a user interaction perspective, I think it would be more natural to open the window when the mouse is released, rather than the ctrl button (but this is just my preference and either option should work).

Luke

pyqtgraphuser

unread,
Apr 17, 2012, 8:19:06 PM4/17/12
to pyqt...@googlegroups.com
From a user interaction perspective, I think it would be more natural to open the window when the mouse is released, rather than the ctrl button (but this is just my preference and either option should work).


How would I do that? I tried:

vb.mouseReleaseEvent = release

and it does not fire when I release the mouse.  

Luke Campagnola

unread,
Apr 18, 2012, 12:15:50 AM4/18/12
to pyqt...@googlegroups.com
I added some new documentation!

There's also more information about how pyqtgraph's mouse system works with Qt's mouse system (and why there needed to be two mouse systems to begin with):

 

Pedro Paiva

unread,
Jul 8, 2013, 5:47:15 AM7/8/13
to pyqt...@googlegroups.com
Hello, I was trying to implement the code below on a viewBox itself (from a 2D plot, not a regular one)
But I'm failing..., I think the linear region is being displayed below my image and not above... =/
Any suggestions?

Luke Campagnola

unread,
Jul 8, 2013, 10:33:30 AM7/8/13
to pyqt...@googlegroups.com
On Mon, Jul 8, 2013 at 5:47 AM, Pedro Paiva <p3k...@gmail.com> wrote:
Hello, I was trying to implement the code below on a viewBox itself (from a 2D plot, not a regular one)
But I'm failing..., I think the linear region is being displayed below my image and not above... =/
Any suggestions?

All QGraphicsItem subclasses inherit the methods 'zValue' and 'setZValue', which determine the order in which items are drawn. 

Does this solve your problem?


Luke

 

Em domingo, 1 de abril de 2012 02h21min18s UTC+1, Luke Campagnola escreveu:

import pyqtgraph as pg
from PyQt4 import QtCore
pw = pg.plot()
lr = pg.LinearRegionItem()
lr.hide()
pw.addItem(lr)
vb = pw.plotItem.vb  ## get the viewbox from the plot item

def drag(ev):
    global vb, lr
    if (ev.button() == QtCore.Qt.LeftButton) and (ev.modifiers() & QtCore.Qt.ControlModifier):
        lr.show()
        lr.setRegion([vb.mapToView(ev.buttonDownPos()).x(), vb.mapToView(ev.pos()).x()])
        ev.accept()
    else:
        pg.ViewBox.mouseDragEvent(vb, ev)

vb.mouseDragEvent = drag

--
-- [ You are subscribed to pyqt...@googlegroups.com. To unsubscribe, send email to pyqtgraph+...@googlegroups.com ]
---
You received this message because you are subscribed to the Google Groups "pyqtgraph" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyqtgraph+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Pedro Paiva

unread,
Jul 8, 2013, 11:34:51 AM7/8/13
to pyqt...@googlegroups.com

It partially helps... xP
Now it's in front but it's not really a box-region but an infinity one (see image) and is permanent... (if I use .hide() it doesn't show at all)

Here's my code:

    def mouseDragEvent(self, ev):
        if ev.button() == Qt.RightButton:
            ev.ignore()
        else:
#             Make region appear
            region = pg.LinearRegionItem()
            region.setZValue(99)
            self.addItem(region)
            region.setRegion([ self.mapToView(ev.buttonDownPos()).x(), self.mapToView(ev.pos()).x() ])
            pg.ViewBox.mouseDragEvent(self, ev)

with self being a ViewBox

megan kratz

unread,
Jul 8, 2013, 11:52:17 AM7/8/13
to pyqt...@googlegroups.com
LinearRegionItem is meant to be infinite in one direction. For a "box-region", you might try pg.RectROI or QtGui.QGraphicsRectItem.

Luke Campagnola

unread,
Jul 8, 2013, 12:08:51 PM7/8/13
to pyqt...@googlegroups.com
On Mon, Jul 8, 2013 at 11:34 AM, Pedro Paiva <p3k...@gmail.com> wrote:
It partially helps... xP
Now it's in front but it's not really a box-region but an infinity one (see image) and is permanent... (if I use .hide() it doesn't show at all)

Here's my code:

    def mouseDragEvent(self, ev):
        if ev.button() == Qt.RightButton:
            ev.ignore()
        else:
#             Make region appear
            region = pg.LinearRegionItem()
            region.setZValue(99)
            self.addItem(region)
            region.setRegion([ self.mapToView(ev.buttonDownPos()).x(), self.mapToView(ev.pos()).x() ])
            pg.ViewBox.mouseDragEvent(self, ev)

with self being a ViewBox


Perhaps we should back up--what exactly are you trying to achieve with this? If you want to do a 2D region-of-interest analysis, then LinearRegionItem will not help; as you have discovered it is for 1D selection. See pyqtgraph/examples/ROIExamples.py for some 2D analysis tools. If you want to drag a rubber-band to zoom in on the image, then see http://pyqtgraph.org/documentation/graphicsItems/viewbox.html#pyqtgraph.ViewBox.setMouseMode

 

Pedro Paiva

unread,
Jul 10, 2013, 6:07:34 AM7/10/13
to pyqt...@googlegroups.com
hmm... I see...

Well, I was trying to implement that because the RectMode doesn't show the selected region... (I'm currently using RectMode as well)


Another question about ViewBox (sorry if it's not completely related, I just don't think it's appropriate to just go creating new topics all the time... xP)
But how can I identify the items of a ViewBox? With the .allChildren() I can see all of them, but I have multiple ImageItems that I can't keep track of the items themselves (just the data inside as they are loaded by the user) but I would like to change their opacity, zlevel and data itself... (and the same with HistogramLUTItem)

Best regards,
Pedro Paiva

Luke Campagnola

unread,
Jul 10, 2013, 10:53:11 AM7/10/13
to pyqt...@googlegroups.com
On Wed, Jul 10, 2013 at 6:07 AM, Pedro Paiva <p3k...@gmail.com> wrote:
Well, I was trying to implement that because the RectMode doesn't show the selected region... (I'm currently using RectMode as well)

Can you explain this further? Under what circumstances does RectMode not work?

 
Another question about ViewBox (sorry if it's not completely related, I just don't think it's appropriate to just go creating new topics all the time... xP)
But how can I identify the items of a ViewBox? With the .allChildren() I can see all of them, but I have multiple ImageItems that I can't keep track of the items themselves (just the data inside as they are loaded by the user) but I would like to change their opacity, zlevel and data itself... (and the same with HistogramLUTItem)

Sorry, I don't follow. What is wrong with allChildren(), and why can't you keep track of the items? 


Luke

Pedro Paiva

unread,
Jul 10, 2013, 11:57:29 AM7/10/13
to pyqt...@googlegroups.com


Em quarta-feira, 10 de julho de 2013 15h53min11s UTC+1, Luke Campagnola escreveu:
On Wed, Jul 10, 2013 at 6:07 AM, Pedro Paiva <p3k...@gmail.com> wrote:
Well, I was trying to implement that because the RectMode doesn't show the selected region... (I'm currently using RectMode as well)

Can you explain this further? Under what circumstances does RectMode not work?


RectMode doesn't show the area being selected (while dragging the mouse)

 
 
Another question about ViewBox (sorry if it's not completely related, I just don't think it's appropriate to just go creating new topics all the time... xP)
But how can I identify the items of a ViewBox? With the .allChildren() I can see all of them, but I have multiple ImageItems that I can't keep track of the items themselves (just the data inside as they are loaded by the user) but I would like to change their opacity, zlevel and data itself... (and the same with HistogramLUTItem)

Sorry, I don't follow. What is wrong with allChildren(), and why can't you keep track of the items? 


allChildren() returns everything inside a ViewBox and if I have several images in there I didn't know wich is wich...
Now I'm adding a marker in every image as img.setData(0, 'img name') so when I ask for the children I also check img.data(0) to match the name and then find the children I need to work with...

Luke Campagnola

unread,
Jul 10, 2013, 12:40:43 PM7/10/13
to pyqt...@googlegroups.com
On Wed, Jul 10, 2013 at 11:57 AM, Pedro Paiva <p3k...@gmail.com> wrote:


Em quarta-feira, 10 de julho de 2013 15h53min11s UTC+1, Luke Campagnola escreveu:
On Wed, Jul 10, 2013 at 6:07 AM, Pedro Paiva <p3k...@gmail.com> wrote:
Well, I was trying to implement that because the RectMode doesn't show the selected region... (I'm currently using RectMode as well)

Can you explain this further? Under what circumstances does RectMode not work?


RectMode doesn't show the area being selected (while dragging the mouse)

Ah, there's a bug: set the Z-value of the selection rectangle to be very large:

viewbox.rbScaleBox.setZValue(1e9)

Or alternatively, set the Z-value of your image to be lower.
 
 
Another question about ViewBox (sorry if it's not completely related, I just don't think it's appropriate to just go creating new topics all the time... xP)
But how can I identify the items of a ViewBox? With the .allChildren() I can see all of them, but I have multiple ImageItems that I can't keep track of the items themselves (just the data inside as they are loaded by the user) but I would like to change their opacity, zlevel and data itself... (and the same with HistogramLUTItem)

Sorry, I don't follow. What is wrong with allChildren(), and why can't you keep track of the items? 


allChildren() returns everything inside a ViewBox and if I have several images in there I didn't know wich is wich...
Now I'm adding a marker in every image as img.setData(0, 'img name') so when I ask for the children I also check img.data(0) to match the name and then find the children I need to work with...

That is a reasonable solution. We generally don't need to use the clumsy Qt setData methods, though, since this is python and we can set any dynamic attributes we want:  img.name = "...". The reverse approach is to just maintain a dictionary {'name": img} that updates whenever the user adds another image. Or if you have a set of Parameter instances that correspond to the image, you can just set param.image = img. ..but otherwise there is no way for pyqtgraph to keep track of the images for you; all it knows is that you have added images to the view.


Luke

Pedro Paiva

unread,
Jul 10, 2013, 1:05:32 PM7/10/13
to pyqt...@googlegroups.com
Nice! xD
Just saved me a few lines creating dragHLines/dragVLines for the zoom... xD


Thx!
Reply all
Reply to author
Forward
0 new messages