set ROI attributes during runtime - fix position and scale programmatically

453 views
Skip to first unread message

Cho

unread,
Jul 25, 2016, 8:22:00 AM7/25/16
to pyqtgraph
Hi,

I have a question regarding ROIs. I have an image with a ROI which is movable by the user. Upon clicking a "save ROI" button I wish to save the ROI to do some analysis with it. In principle I want to display the saved ROI in the image but make it fixed in position and size so that it cannot be altered by the user anymore. Here's how I thought how I would go about doing that:

-> make a copy of the current movable and scalable ROI
-> change attributes of that copy; fix size and position
-> add copy to the plot

  def saveROI(self):      
      copyROI
= self._ROI   #make copy of user-draggable ROI
#      copyROI.setProperty("movable", False) #doesn't seem to work
      copyROI
.setZValue(10)  # make sure ROI is drawn above image
      copyROI
.translatable = False   #fix position
      copyROI
.removeHandle(0)    #disable scaling
     
self._Plot.addItem(copyROI)

However, this will overwrite the user-draggable ROI (self._ ROI) and only display the copy. I think the ROI object must have some index so basically it is overwritten by the copy?
To overcome this I could get all the relevant data from the user-ROI and build fixed ROI from that but it seems kinda ugly (lots of if statments to handle the different ROI shapes etc.). It would be much nicer to create a copy and just alter some attributes on the fly. Is this possible?

On a side note, could someone explain to me how one uses the .setProperty method correctly?

Thanks a lot, Chris

Cho

unread,
Jul 26, 2016, 9:34:47 AM7/26/16
to pyqtgraph
So I found out about Python variables just being pointers so I guess the problem lies in the line:


copyROI = self._ROI   #make copy of user-draggable ROI

However copy.copy or copy.deepcopy throws a bunch of errors that I don't quiet understand (I guess an instance of a class cannot be copied with all the arguments being real copies as well).

So I resorted to generating new ROIs from the ground up which I tried to circumvent in the first place. Now new problems arise...Here's a code snippet:

if self.ROI_comboBox.currentText()=="Rectangle":
 copyROI
= pg.RectROI([self._ROIXPos, self._ROIYPos], [self._ROISizeX, self._ROISizeY],
           pen
=pg.mkPen(color=self._ROIList_PenItems[index],width=1),removable=True)
elif self.ROI_comboBox.currentText()=="Circle":  
 copyROI
= pg.CircleROI([self._ROIXPos, self._ROIYPos], [self._ROISizeX,
 
self._ROISizeY],pen=pg.mkPen(color=self._ROIList_PenItems[index],width=1),removable=True)
       
       
        copyROI
.setZValue(100)  # make sure ROI is drawn above image
        copyROI
.translatable = False
        handle
= copyROI.getHandles()
!!!!!!  copyROI.removeHandle(handle[0])     #this line throws an error that NoneType doesn't have a method removeItem
        handle
[0].disconnectROI(copyROI)
       
print("Get handles: ",copyROI.getHandles())
       
print("Handle[0]: ",handle[0])
       
print("type(copyROI): ",type(copyROI))
       
self._P1.addItem(copyROI)  


So basically I create a ROI of type determined by a user selection widget (rectangle or circle). I can see the automatically created handle object (when creating a rect ROI) just fine. However when I try to remove it to effectively disable scaling it throws an error that an object of NoneType doesn't have a method of removeItem. It's strange because in the snippet I posted in the first post the method .removeHandle(0) works fine on the auto-created handle of a rect ROI object. Whats causing this?

I got a dirty workaround now which you can see in the above snippet namely I disconnect the handle from the ROI of interest. It thus becomes disabled and scaling becomes impossible. Just what I wanted however the handle is still visible which I would like to avoid.

Any help is greatly appreciated, Chris


dew

unread,
Jul 20, 2017, 2:26:58 PM7/20/17
to pyqtgraph

You have to add the roi to the image so that it can be identified as current scene.
Example:

self.imv.addItem(copyROI)
handles =
copyROI.getHandles()
for index, item in enumerate(handles):
   
copyROI.removeHandle(item)

where imv is the ImageView
Reply all
Reply to author
Forward
0 new messages