mapToView vs mapToScene vs...?

2,909 views
Skip to first unread message

Victoria Price

unread,
Nov 1, 2012, 7:00:08 PM11/1/12
to pyqt...@googlegroups.com
Hi, so here's what I've done:  taken a numpy array and displayed it within an ImageItem, within a PlotItem.  In the real world, the data corresponds to roughly 2m x 12m.  I have scaled the pixels appropriately, and the image displays correctly with regards to the values on the axes.  What I'm having a difficult time with is getting the scene position to be accurate when I record mouse click coordinates.  What I'm not sure is how to use the map to view/from view/to scene/from scene etc to get the appropriate coordinates.  
Here is the basic code for the image (self.p1 is a PlotItem):

self.p1.vb.scaleBy((10.28/512,2.486/96))
self.image=pg.ImageView(view=self.p1)

 image=scipy.ndimage.filters.maximum_filter(frame.data, size=5)
 self.image.setImage(image, scale=((10.28/512),(2.486/96)))
 self.p1.vb.setXRange(0,2)
 self.p1.vb.setYRange(0,14)


if obj is self.p1 and event.type() == event.GraphicsSceneMousePress:
            if event.button()==Qt.LeftButton:
                pos=event.scenePos()
                x=((pos.x()*(2.486/96))-1)
                y=(pos.y()*(10.28/512))
                self.x=QTableWidgetItem('%0.01f'% x)
                self.y=QTableWidgetItem('%0.01f'% y)
 

I added the scaling again in the x/y pos because it still didn't seem to work in the scaling.... I've attached a screen cap, as well.

Thank you-- I hope this is somewhat clear!
Untitled.png

Luke Campagnola

unread,
Nov 1, 2012, 7:40:10 PM11/1/12
to pyqt...@googlegroups.com
On Thu, Nov 1, 2012 at 7:00 PM, Victoria Price <victoria...@gmail.com> wrote:
Hi, so here's what I've done:  taken a numpy array and displayed it within an ImageItem, within a PlotItem.  In the real world, the data corresponds to roughly 2m x 12m.  I have scaled the pixels appropriately, and the image displays correctly with regards to the values on the axes.  What I'm having a difficult time with is getting the scene position to be accurate when I record mouse click coordinates.  What I'm not sure is how to use the map to view/from view/to scene/from scene etc to get the appropriate coordinates.  

First, you might want to read about coordinate systems in QGraphicsView:

If you understand that, then the crucial bit of information you need is this: your data (in this case the image) lives in the coordinate system inside the ViewBox (self.p1.vb) and this coordinate system is the "View" in all of the mapTo/From methods. So when you have a position in scene coordinates such as event.scenePos(), to get the corresponding data coordinates you should use self.p1.vb.mapSceneToView(event.scenePos()). The resulting position would be expressed in meters and should correspond to the values in the PlotItem axes. If you wanted to know the image pixel coordinates that you clicked on, you can ask the image to do that mapping for you: self.image.imageItem.mapFromScene(event.scenePos()).
 
Here is the basic code for the image (self.p1 is a PlotItem):

self.p1.vb.scaleBy((10.28/512,2.486/96))
self.image=pg.ImageView(view=self.p1)

 image=scipy.ndimage.filters.maximum_filter(frame.data, size=5)
 self.image.setImage(image, scale=((10.28/512),(2.486/96)))
 self.p1.vb.setXRange(0,2)
 self.p1.vb.setYRange(0,14)


if obj is self.p1 and event.type() == event.GraphicsSceneMousePress:
            if event.button()==Qt.LeftButton:
                pos=event.scenePos()
                x=((pos.x()*(2.486/96))-1)
                y=(pos.y()*(10.28/512))
                self.x=QTableWidgetItem('%0.01f'% x)
                self.y=QTableWidgetItem('%0.01f'% y)

Question about the last section of this code: it appears you are overriding an event handling method somewhere. Can you tell me which method and on which object? 
I ask because it looks like you are not calling the superclass event handler, which could prevent some other mouse-related behavior from working correctly (this may or may not be a problem for you).

Luke


Victoria Price

unread,
Nov 1, 2012, 8:04:06 PM11/1/12
to pyqt...@googlegroups.com
To be honest... I'm not sure about the overriding.  I had written that following an example I had found online regarding making sure the event only occurs in self.p1, and seeing as the mapping hasn't changed anything, I think that's where my problem is...

Thanks for putting up with my silly questions-- I've sort of hit the ground running (or flailing) with this job and I really appreciate the guidance.  

Victoria Price

unread,
Nov 1, 2012, 8:11:11 PM11/1/12
to pyqt...@googlegroups.com
Here's the code for the event filter:

def eventFilter(self, obj, event):
        """
        determines which ImageView (master or slave) the mouse is clicked in and
        records mouse coordinates accordingly
        """
        
        if obj is self.p1 and event.type() == event.GraphicsSceneMousePress:
            if event.button()==Qt.LeftButton:
                self.image.imageItem.mapFromScene(event.scenePos())
                position=event.scenePos()
                x=((position.x()*(2.486/96))-1)
                y=(position.y()*(10.28/512))
                self.x=QTableWidgetItem('%0.01f'% x)
                self.y=QTableWidgetItem('%0.01f'% y)

                row=self.coordinates.rowCount()
        
                self.coordinates.insertRow(row)
                self.coordinates.setItem(row,0,self.x)
                self.coordinates.setItem(row,1,self.y)

                self.label.setText("x=%0.01f,y=%0.01f" %(x,y))
return super(ImageViewer, self).eventFilter(obj, event)

Luke Campagnola

unread,
Nov 1, 2012, 8:19:48 PM11/1/12
to pyqt...@googlegroups.com
Ok, this code looks fine to me--you are calling the superclass event filter at the very last line, so this should not interfere with anything else.
Let me know if you need more explanation on the coordinate systems / mapping issue.

Luke

Victoria Price

unread,
Nov 1, 2012, 8:29:13 PM11/1/12
to pyqt...@googlegroups.com
Do you think the issue could be somewhere in the link between the PlotItem and ImageView?  If I remove the scale from the self.image.setImage(), it alters the scale of the axes but not the coordinates displayed upon click.  Any ideas?

Luke Campagnola

unread,
Nov 1, 2012, 8:48:43 PM11/1/12
to pyqt...@googlegroups.com
On Thu, Nov 1, 2012 at 8:29 PM, Victoria Price <victoria...@gmail.com> wrote:
Do you think the issue could be somewhere in the link between the PlotItem and ImageView?  If I remove the scale from the self.image.setImage(), it alters the scale of the axes but not the coordinates displayed upon click.  Any ideas?

Sorry, I missed something important in your last message: the map methods return the mapped position, they do not modify the point directly. So you need: 

position = self.image.imageItem.mapFromScene(event.scenePos()) .

victoria.e.price

unread,
Nov 1, 2012, 8:50:46 PM11/1/12
to pyqt...@googlegroups.com
Brilliant!  Thank you!

Victoria Price

unread,
Nov 26, 2012, 3:43:45 PM11/26/12
to pyqt...@googlegroups.com
Actually, I have one more issue-- 
 The coordinates work beautifully if there is no image loaded.  Once the image is loaded, the scale goes away (the proper range is still displayed on the axes, but the coordinates change)...any ideas?
Thank you!

Luke Campagnola

unread,
Nov 28, 2012, 10:53:09 AM11/28/12
to pyqt...@googlegroups.com
On Mon, Nov 26, 2012 at 3:43 PM, Victoria Price <victoria...@gmail.com> wrote:
Actually, I have one more issue-- 
 The coordinates work beautifully if there is no image loaded.  Once the image is loaded, the scale goes away (the proper range is still displayed on the axes, but the coordinates change)...any ideas?

I noticed you're doing some manual transformation in your code:

                x=((position.x()*(2.486/96))-1)
                y=(position.y()*(10.28/512))

Is it possible this is responsible? Ideally, you should never need to transform coordinates manually; find the correct mapTo / mapFrom methods to use.

Luke

Victoria Price

unread,
Nov 30, 2012, 10:07:07 AM11/30/12
to pyqt...@googlegroups.com
I have actually gotten rid of that, to simply the pos.x and pos.y, once I figured out the mapping.  The problem is that once the image is loaded, the coordinates match those of the image (i.e. a 512x96 array) rather than the scale of the View Box, so something is not mapping correctly...

Luke Campagnola

unread,
Nov 30, 2012, 1:31:58 PM11/30/12
to pyqt...@googlegroups.com
On Fri, Nov 30, 2012 at 10:07 AM, Victoria Price <victoria...@gmail.com> wrote:
I have actually gotten rid of that, to simply the pos.x and pos.y, once I figured out the mapping.  The problem is that once the image is loaded, the coordinates match those of the image (i.e. a 512x96 array) rather than the scale of the View Box, so something is not mapping correctly...

Correct--see my previous message:

So when you have a position in scene coordinates such as event.scenePos(), to get the corresponding data coordinates you should use self.p1.vb.mapSceneToView(
event.scenePos()). The resulting position would be expressed in meters and should correspond to the values in the PlotItem axes. If you wanted to know the image pixel coordinates that you clicked on, you can ask the image to do that mapping for you: self.image.imageItem.mapFromScene(event.scenePos()).
 
Luke
Reply all
Reply to author
Forward
0 new messages