Expanded ROI documentation
This commit is contained in:
parent
37adecc06e
commit
43ec2bcd2c
|
@ -36,8 +36,15 @@ def rectStr(r):
|
|||
return "[%f, %f] + [%f, %f]" % (r.x(), r.y(), r.width(), r.height())
|
||||
|
||||
class ROI(GraphicsObject):
|
||||
"""Generic region-of-interest widget.
|
||||
Can be used for implementing many types of selection box with rotate/translate/scale handles.
|
||||
"""
|
||||
Generic region-of-interest widget.
|
||||
|
||||
Can be used for implementing many types of selection box with
|
||||
rotate/translate/scale handles.
|
||||
ROIs can be customized to have a variety of shapes (by subclassing or using
|
||||
any of the built-in subclasses) and any combination of draggable handles
|
||||
that allow the user to manibulate the ROI.
|
||||
|
||||
|
||||
Signals
|
||||
----------------------- ----------------------------------------------------
|
||||
|
@ -59,6 +66,42 @@ class ROI(GraphicsObject):
|
|||
sigRemoveRequested Emitted when the user selects 'remove' from the
|
||||
ROI's context menu (if available).
|
||||
----------------------- ----------------------------------------------------
|
||||
|
||||
|
||||
Arguments
|
||||
---------------- -----------------------------------------------------------
|
||||
pos (length-2 sequence) Indicates the position of the ROI's
|
||||
origin. For most ROIs, this is the lower-left corner of
|
||||
its bounding rectangle.
|
||||
size (length-2 sequence) Indicates the width and height of the
|
||||
ROI.
|
||||
angle (float) The rotation of the ROI in degrees. Default is 0.
|
||||
invertible (bool) If True, the user may resize the ROI to have
|
||||
negative width or height (assuming the ROI has scale
|
||||
handles). Default is False.
|
||||
maxBounds (QRect, QRectF, or None) Specifies boundaries that the ROI
|
||||
cannot be dragged outside of by the user. Default is None.
|
||||
snapSize (float) The spacing of snap positions used when *scaleSnap*
|
||||
or *translateSnap* are enabled. Default is 1.0.
|
||||
scaleSnap (bool) If True, the width and height of the ROI are forced
|
||||
to be integer multiples of *snapSize* when being resized
|
||||
by the user. Default is False.
|
||||
translateSnap (bool) If True, the x and y positions of the ROI are forced
|
||||
to be integer multiples of *snapSize* when being resized
|
||||
by the user. Default is False.
|
||||
rotateSnap (bool) If True, the ROI angle is forced to a multiple of
|
||||
15 degrees when rotated by the user. Default is False.
|
||||
parent (QGraphicsItem) The graphics item parent of this ROI. It
|
||||
is generally not necessary to specify the parent.
|
||||
pen (QPen or argument to pg.mkPen) The pen to use when drawing
|
||||
the shape of the ROI.
|
||||
movable (bool) If True, the ROI can be moved by dragging anywhere
|
||||
inside the ROI. Default is True.
|
||||
removable (bool) If True, the ROI will be given a context menu with
|
||||
an option to remove the ROI. The ROI emits
|
||||
sigRemoveRequested when this menu action is selected.
|
||||
Default is False.
|
||||
---------------- -----------------------------------------------------------
|
||||
"""
|
||||
|
||||
sigRegionChangeFinished = QtCore.Signal(object)
|
||||
|
@ -117,7 +160,11 @@ class ROI(GraphicsObject):
|
|||
return sc
|
||||
|
||||
def saveState(self):
|
||||
"""Return the state of the widget in a format suitable for storing to disk. (Points are converted to tuple)"""
|
||||
"""Return the state of the widget in a format suitable for storing to
|
||||
disk. (Points are converted to tuple)
|
||||
|
||||
Combined with setState(), this allows ROIs to be easily saved and
|
||||
restored."""
|
||||
state = {}
|
||||
state['pos'] = tuple(self.state['pos'])
|
||||
state['size'] = tuple(self.state['size'])
|
||||
|
@ -125,6 +172,10 @@ class ROI(GraphicsObject):
|
|||
return state
|
||||
|
||||
def setState(self, state, update=True):
|
||||
"""
|
||||
Set the state of the ROI from a structure generated by saveState() or
|
||||
getState().
|
||||
"""
|
||||
self.setPos(state['pos'], update=False)
|
||||
self.setSize(state['size'], update=False)
|
||||
self.setAngle(state['angle'], update=update)
|
||||
|
@ -135,20 +186,31 @@ class ROI(GraphicsObject):
|
|||
h['item'].setZValue(z+1)
|
||||
|
||||
def parentBounds(self):
|
||||
"""
|
||||
Return the bounding rectangle of this ROI in the coordinate system
|
||||
of its parent.
|
||||
"""
|
||||
return self.mapToParent(self.boundingRect()).boundingRect()
|
||||
|
||||
def setPen(self, pen):
|
||||
"""
|
||||
Set the pen to use when drawing the ROI shape.
|
||||
"""
|
||||
self.pen = fn.mkPen(pen)
|
||||
self.currentPen = self.pen
|
||||
self.update()
|
||||
|
||||
def size(self):
|
||||
"""Return the size (w,h) of the ROI."""
|
||||
return self.getState()['size']
|
||||
|
||||
def pos(self):
|
||||
"""Return the position (x,y) of the ROI's origin.
|
||||
For most ROIs, this will be the lower-left corner."""
|
||||
return self.getState()['pos']
|
||||
|
||||
def angle(self):
|
||||
"""Return the angle of the ROI in degrees."""
|
||||
return self.getState()['angle']
|
||||
|
||||
def setPos(self, pos, update=True, finish=True):
|
||||
|
@ -264,21 +326,86 @@ class ROI(GraphicsObject):
|
|||
#self.stateChanged()
|
||||
|
||||
def rotate(self, angle, update=True, finish=True):
|
||||
"""
|
||||
Rotate the ROI by *angle* degrees.
|
||||
|
||||
Also accepts *update* and *finish* arguments (see setPos() for a
|
||||
description of these).
|
||||
"""
|
||||
self.setAngle(self.angle()+angle, update=update, finish=finish)
|
||||
|
||||
def handleMoveStarted(self):
|
||||
self.preMoveState = self.getState()
|
||||
|
||||
def addTranslateHandle(self, pos, axes=None, item=None, name=None, index=None):
|
||||
"""
|
||||
Add a new translation handle to the ROI. Dragging the handle will move
|
||||
the entire ROI without changing its angle or shape.
|
||||
|
||||
Note that, by default, ROIs may be moved by dragging anywhere inside the
|
||||
ROI. However, for larger ROIs it may be desirable to disable this and
|
||||
instead provide one or more translation handles.
|
||||
|
||||
Arguments:
|
||||
------------------- ----------------------------------------------------
|
||||
pos (length-2 sequence) The position of the handle
|
||||
relative to the shape of the ROI. A value of (0,0)
|
||||
indicates the origin, whereas (1, 1) indicates the
|
||||
upper-right corner, regardless of the ROI's size.
|
||||
item The Handle instance to add. If None, a new handle
|
||||
will be created.
|
||||
name The name of this handle (optional). Handles are
|
||||
identified by name when calling
|
||||
getLocalHandlePositions and getSceneHandlePositions.
|
||||
------------------- ----------------------------------------------------
|
||||
"""
|
||||
pos = Point(pos)
|
||||
return self.addHandle({'name': name, 'type': 't', 'pos': pos, 'item': item}, index=index)
|
||||
|
||||
def addFreeHandle(self, pos=None, axes=None, item=None, name=None, index=None):
|
||||
"""
|
||||
Add a new free handle to the ROI. Dragging free handles has no effect
|
||||
on the position or shape of the ROI.
|
||||
|
||||
Arguments:
|
||||
------------------- ----------------------------------------------------
|
||||
pos (length-2 sequence) The position of the handle
|
||||
relative to the shape of the ROI. A value of (0,0)
|
||||
indicates the origin, whereas (1, 1) indicates the
|
||||
upper-right corner, regardless of the ROI's size.
|
||||
item The Handle instance to add. If None, a new handle
|
||||
will be created.
|
||||
name The name of this handle (optional). Handles are
|
||||
identified by name when calling
|
||||
getLocalHandlePositions and getSceneHandlePositions.
|
||||
------------------- ----------------------------------------------------
|
||||
"""
|
||||
if pos is not None:
|
||||
pos = Point(pos)
|
||||
return self.addHandle({'name': name, 'type': 'f', 'pos': pos, 'item': item}, index=index)
|
||||
|
||||
def addScaleHandle(self, pos, center, axes=None, item=None, name=None, lockAspect=False, index=None):
|
||||
"""
|
||||
Add a new scale handle to the ROI. Dragging a scale handle allows the
|
||||
user to change the height and/or width of the ROI.
|
||||
|
||||
Arguments:
|
||||
------------------- ----------------------------------------------------
|
||||
pos (length-2 sequence) The position of the handle
|
||||
relative to the shape of the ROI. A value of (0,0)
|
||||
indicates the origin, whereas (1, 1) indicates the
|
||||
upper-right corner, regardless of the ROI's size.
|
||||
center (length-2 sequence) The center point around which
|
||||
scaling takes place. If the center point has the
|
||||
same x or y value as the handle position, then
|
||||
scaling will be disabled for that axis.
|
||||
item The Handle instance to add. If None, a new handle
|
||||
will be created.
|
||||
name The name of this handle (optional). Handles are
|
||||
identified by name when calling
|
||||
getLocalHandlePositions and getSceneHandlePositions.
|
||||
------------------- ----------------------------------------------------
|
||||
"""
|
||||
pos = Point(pos)
|
||||
center = Point(center)
|
||||
info = {'name': name, 'type': 's', 'center': center, 'pos': pos, 'item': item, 'lockAspect': lockAspect}
|
||||
|
@ -289,11 +416,51 @@ class ROI(GraphicsObject):
|
|||
return self.addHandle(info, index=index)
|
||||
|
||||
def addRotateHandle(self, pos, center, item=None, name=None, index=None):
|
||||
"""
|
||||
Add a new rotation handle to the ROI. Dragging a rotation handle allows
|
||||
the user to change the angle of the ROI.
|
||||
|
||||
Arguments:
|
||||
------------------- ----------------------------------------------------
|
||||
pos (length-2 sequence) The position of the handle
|
||||
relative to the shape of the ROI. A value of (0,0)
|
||||
indicates the origin, whereas (1, 1) indicates the
|
||||
upper-right corner, regardless of the ROI's size.
|
||||
center (length-2 sequence) The center point around which
|
||||
rotation takes place.
|
||||
item The Handle instance to add. If None, a new handle
|
||||
will be created.
|
||||
name The name of this handle (optional). Handles are
|
||||
identified by name when calling
|
||||
getLocalHandlePositions and getSceneHandlePositions.
|
||||
------------------- ----------------------------------------------------
|
||||
"""
|
||||
pos = Point(pos)
|
||||
center = Point(center)
|
||||
return self.addHandle({'name': name, 'type': 'r', 'center': center, 'pos': pos, 'item': item}, index=index)
|
||||
|
||||
def addScaleRotateHandle(self, pos, center, item=None, name=None, index=None):
|
||||
"""
|
||||
Add a new scale+rotation handle to the ROI. When dragging a handle of
|
||||
this type, the user can simultaneously rotate the ROI around an
|
||||
arbitrary center point as well as scale the ROI by dragging the handle
|
||||
toward or away from the center point.
|
||||
|
||||
Arguments:
|
||||
------------------- ----------------------------------------------------
|
||||
pos (length-2 sequence) The position of the handle
|
||||
relative to the shape of the ROI. A value of (0,0)
|
||||
indicates the origin, whereas (1, 1) indicates the
|
||||
upper-right corner, regardless of the ROI's size.
|
||||
center (length-2 sequence) The center point around which
|
||||
scaling and rotation take place.
|
||||
item The Handle instance to add. If None, a new handle
|
||||
will be created.
|
||||
name The name of this handle (optional). Handles are
|
||||
identified by name when calling
|
||||
getLocalHandlePositions and getSceneHandlePositions.
|
||||
------------------- ----------------------------------------------------
|
||||
"""
|
||||
pos = Point(pos)
|
||||
center = Point(center)
|
||||
if pos[0] != center[0] and pos[1] != center[1]:
|
||||
|
@ -301,6 +468,27 @@ class ROI(GraphicsObject):
|
|||
return self.addHandle({'name': name, 'type': 'sr', 'center': center, 'pos': pos, 'item': item}, index=index)
|
||||
|
||||
def addRotateFreeHandle(self, pos, center, axes=None, item=None, name=None, index=None):
|
||||
"""
|
||||
Add a new rotation+free handle to the ROI. When dragging a handle of
|
||||
this type, the user can rotate the ROI around an
|
||||
arbitrary center point, while moving toward or away from the center
|
||||
point has no effect on the shape of the ROI.
|
||||
|
||||
Arguments:
|
||||
------------------- ----------------------------------------------------
|
||||
pos (length-2 sequence) The position of the handle
|
||||
relative to the shape of the ROI. A value of (0,0)
|
||||
indicates the origin, whereas (1, 1) indicates the
|
||||
upper-right corner, regardless of the ROI's size.
|
||||
center (length-2 sequence) The center point around which
|
||||
rotation takes place.
|
||||
item The Handle instance to add. If None, a new handle
|
||||
will be created.
|
||||
name The name of this handle (optional). Handles are
|
||||
identified by name when calling
|
||||
getLocalHandlePositions and getSceneHandlePositions.
|
||||
------------------- ----------------------------------------------------
|
||||
"""
|
||||
pos = Point(pos)
|
||||
center = Point(center)
|
||||
return self.addHandle({'name': name, 'type': 'rf', 'center': center, 'pos': pos, 'item': item}, index=index)
|
||||
|
@ -329,6 +517,9 @@ class ROI(GraphicsObject):
|
|||
return h
|
||||
|
||||
def indexOfHandle(self, handle):
|
||||
"""
|
||||
Return the index of *handle* in the list of this ROI's handles.
|
||||
"""
|
||||
if isinstance(handle, Handle):
|
||||
index = [i for i, info in enumerate(self.handles) if info['item'] is handle]
|
||||
if len(index) == 0:
|
||||
|
@ -338,7 +529,8 @@ class ROI(GraphicsObject):
|
|||
return handle
|
||||
|
||||
def removeHandle(self, handle):
|
||||
"""Remove a handle from this ROI. Argument may be either a Handle instance or the integer index of the handle."""
|
||||
"""Remove a handle from this ROI. Argument may be either a Handle
|
||||
instance or the integer index of the handle."""
|
||||
index = self.indexOfHandle(handle)
|
||||
|
||||
handle = self.handles[index]['item']
|
||||
|
@ -349,20 +541,17 @@ class ROI(GraphicsObject):
|
|||
self.stateChanged()
|
||||
|
||||
def replaceHandle(self, oldHandle, newHandle):
|
||||
"""Replace one handle in the ROI for another. This is useful when connecting multiple ROIs together.
|
||||
*oldHandle* may be a Handle instance or the index of a handle."""
|
||||
#print "========================="
|
||||
#print "replace", oldHandle, newHandle
|
||||
#print self
|
||||
#print self.handles
|
||||
#print "-----------------"
|
||||
"""Replace one handle in the ROI for another. This is useful when
|
||||
connecting multiple ROIs together.
|
||||
|
||||
*oldHandle* may be a Handle instance or the index of a handle to be
|
||||
replaced."""
|
||||
index = self.indexOfHandle(oldHandle)
|
||||
info = self.handles[index]
|
||||
self.removeHandle(index)
|
||||
info['item'] = newHandle
|
||||
info['pos'] = newHandle.pos()
|
||||
self.addHandle(info, index=index)
|
||||
#print self.handles
|
||||
|
||||
def checkRemoveHandle(self, handle):
|
||||
## This is used when displaying a Handle's context menu to determine
|
||||
|
@ -373,7 +562,10 @@ class ROI(GraphicsObject):
|
|||
|
||||
|
||||
def getLocalHandlePositions(self, index=None):
|
||||
"""Returns the position of a handle in ROI coordinates"""
|
||||
"""Returns the position of handles in the ROI's coordinate system.
|
||||
|
||||
The format returned is a list of (name, pos) tuples.
|
||||
"""
|
||||
if index == None:
|
||||
positions = []
|
||||
for h in self.handles:
|
||||
|
@ -383,6 +575,10 @@ class ROI(GraphicsObject):
|
|||
return (self.handles[index]['name'], self.handles[index]['pos'])
|
||||
|
||||
def getSceneHandlePositions(self, index=None):
|
||||
"""Returns the position of handles in the scene coordinate system.
|
||||
|
||||
The format returned is a list of (name, pos) tuples.
|
||||
"""
|
||||
if index == None:
|
||||
positions = []
|
||||
for h in self.handles:
|
||||
|
@ -392,6 +588,9 @@ class ROI(GraphicsObject):
|
|||
return (self.handles[index]['name'], self.handles[index]['item'].scenePos())
|
||||
|
||||
def getHandles(self):
|
||||
"""
|
||||
Return a list of this ROI's Handles.
|
||||
"""
|
||||
return [h['item'] for h in self.handles]
|
||||
|
||||
def mapSceneToParent(self, pt):
|
||||
|
@ -467,8 +666,6 @@ class ROI(GraphicsObject):
|
|||
self.removeTimer.timeout.connect(lambda: self.sigRemoveRequested.emit(self))
|
||||
self.removeTimer.start(0)
|
||||
|
||||
|
||||
|
||||
def mouseDragEvent(self, ev):
|
||||
if ev.isStart():
|
||||
#p = ev.pos()
|
||||
|
@ -510,56 +707,16 @@ class ROI(GraphicsObject):
|
|||
self.sigClicked.emit(self, ev)
|
||||
else:
|
||||
ev.ignore()
|
||||
|
||||
|
||||
|
||||
|
||||
def cancelMove(self):
|
||||
self.isMoving = False
|
||||
self.setState(self.preMoveState)
|
||||
|
||||
|
||||
#def pointDragEvent(self, pt, ev):
|
||||
### just for handling drag start/stop.
|
||||
### drag moves are handled through movePoint()
|
||||
|
||||
#if ev.isStart():
|
||||
#self.isMoving = True
|
||||
#self.preMoveState = self.getState()
|
||||
|
||||
#self.sigRegionChangeStarted.emit(self)
|
||||
#elif ev.isFinish():
|
||||
#self.isMoving = False
|
||||
#self.sigRegionChangeFinished.emit(self)
|
||||
#return
|
||||
|
||||
|
||||
#def pointPressEvent(self, pt, ev):
|
||||
##print "press"
|
||||
#self.isMoving = True
|
||||
#self.preMoveState = self.getState()
|
||||
|
||||
##self.emit(QtCore.SIGNAL('regionChangeStarted'), self)
|
||||
#self.sigRegionChangeStarted.emit(self)
|
||||
##self.pressPos = self.mapFromScene(ev.scenePos())
|
||||
##self.pressHandlePos = self.handles[pt]['item'].pos()
|
||||
|
||||
#def pointReleaseEvent(self, pt, ev):
|
||||
##print "release"
|
||||
#self.isMoving = False
|
||||
##self.emit(QtCore.SIGNAL('regionChangeFinished'), self)
|
||||
#self.sigRegionChangeFinished.emit(self)
|
||||
|
||||
#def pointMoveEvent(self, pt, ev):
|
||||
#self.movePoint(pt, ev.scenePos(), ev.modifiers())
|
||||
|
||||
|
||||
def checkPointMove(self, handle, pos, modifiers):
|
||||
"""When handles move, they must ask the ROI if the move is acceptable.
|
||||
By default, this always returns True. Subclasses may wish override.
|
||||
"""
|
||||
return True
|
||||
|
||||
|
||||
def movePoint(self, handle, pos, modifiers=QtCore.Qt.KeyboardModifier(), finish=True, coords='parent'):
|
||||
## called by Handles when they are moved.
|
||||
|
@ -804,7 +961,6 @@ class ROI(GraphicsObject):
|
|||
round(pos[1] / snap[1]) * snap[1]
|
||||
)
|
||||
|
||||
|
||||
def boundingRect(self):
|
||||
return QtCore.QRectF(0, 0, self.state['size'][0], self.state['size'][1]).normalized()
|
||||
|
||||
|
@ -871,7 +1027,25 @@ class ROI(GraphicsObject):
|
|||
return bounds, tr
|
||||
|
||||
def getArrayRegion(self, data, img, axes=(0,1), returnMappedCoords=False, **kwds):
|
||||
"""Use the position and orientation of this ROI relative to an imageItem to pull a slice from an array.
|
||||
"""Use the position and orientation of this ROI relative to an imageItem
|
||||
to pull a slice from an array.
|
||||
|
||||
**Arguments**
|
||||
------------------- ----------------------------------------------------
|
||||
data The array to slice from. Note that this array does
|
||||
*not* have to be the same data that is represented
|
||||
in *img*.
|
||||
img (ImageItem or other suitable QGraphicsItem)
|
||||
Used to determine the relationship between the
|
||||
ROI and the boundaries of *data*.
|
||||
axes (length-2 tuple) Specifies the axes in *data* that
|
||||
correspond to the x and y axes of *img*.
|
||||
returnMappedCoords (bool) If True, the array slice is returned along
|
||||
with a corresponding array of coordinates that were
|
||||
used to extract data from the original array.
|
||||
**kwds All keyword arguments are passed to
|
||||
:func:`affineSlice <pyqtgraph.affineSlice>`.
|
||||
------------------- ----------------------------------------------------
|
||||
|
||||
This method uses :func:`affineSlice <pyqtgraph.affineSlice>` to generate
|
||||
the slice from *data* and uses :func:`getAffineSliceParams <pyqtgraph.ROI.getAffineSliceParams>` to determine the parameters to
|
||||
|
@ -1088,7 +1262,18 @@ class ROI(GraphicsObject):
|
|||
|
||||
|
||||
class Handle(UIGraphicsItem):
|
||||
"""
|
||||
Handle represents a single user-interactable point attached to an ROI. They
|
||||
are usually created by a call to one of the ROI.add___Handle() methods.
|
||||
|
||||
Handles are represented as a square, diamond, or circle, and are drawn with
|
||||
fixed pixel size regardless of the scaling of the view they are displayed in.
|
||||
|
||||
Handles may be dragged to change the position, size, orientation, or other
|
||||
properties of the ROI they are attached to.
|
||||
|
||||
|
||||
"""
|
||||
types = { ## defines number of sides, start angle for each handle type
|
||||
't': (4, np.pi/4),
|
||||
'f': (4, np.pi/4),
|
||||
|
@ -1360,6 +1545,22 @@ class TestROI(ROI):
|
|||
|
||||
|
||||
class RectROI(ROI):
|
||||
"""
|
||||
Rectangular ROI subclass with a single scale handle at the top-right corner.
|
||||
|
||||
**Arguments**
|
||||
-------------- -------------------------------------------------------------
|
||||
pos (length-2 sequence) The position of the ROI origin.
|
||||
See ROI().
|
||||
size (length-2 sequence) The size of the ROI. See ROI().
|
||||
centered (bool) If True, scale handles affect the ROI relative to its
|
||||
center, rather than its origin.
|
||||
sideScalers (bool) If True, extra scale handles are added at the top and
|
||||
right edges.
|
||||
**args All extra keyword arguments are passed to ROI()
|
||||
-------------- -------------------------------------------------------------
|
||||
|
||||
"""
|
||||
def __init__(self, pos, size, centered=False, sideScalers=False, **args):
|
||||
#QtGui.QGraphicsRectItem.__init__(self, 0, 0, size[0], size[1])
|
||||
ROI.__init__(self, pos, size, **args)
|
||||
|
@ -1375,6 +1576,22 @@ class RectROI(ROI):
|
|||
self.addScaleHandle([0.5, 1], [0.5, center[1]])
|
||||
|
||||
class LineROI(ROI):
|
||||
"""
|
||||
Rectangular ROI subclass with scale-rotate handles on either side. This
|
||||
allows the ROI to be positioned as if moving the ends of a line segment.
|
||||
A third handle controls the width of the ROI orthogonal to its "line" axis.
|
||||
|
||||
**Arguments**
|
||||
-------------- -------------------------------------------------------------
|
||||
pos1 (length-2 sequence) The position of the center of the ROI's
|
||||
left edge.
|
||||
pos2 (length-2 sequence) The position of the center of the ROI's
|
||||
right edge.
|
||||
width (float) The width of the ROI.
|
||||
**args All extra keyword arguments are passed to ROI()
|
||||
-------------- -------------------------------------------------------------
|
||||
|
||||
"""
|
||||
def __init__(self, pos1, pos2, width, **args):
|
||||
pos1 = Point(pos1)
|
||||
pos2 = Point(pos2)
|
||||
|
@ -1399,6 +1616,13 @@ class MultiRectROI(QtGui.QGraphicsObject):
|
|||
This is generally used to mark a curved path through
|
||||
an image similarly to PolyLineROI. It differs in that each segment
|
||||
of the chain is rectangular instead of linear and thus has width.
|
||||
|
||||
**Arguments**
|
||||
-------------- -------------------------------------------------------------
|
||||
points (list of length-2 sequences) The list of points in the path.
|
||||
width (float) The width of the ROIs orthogonal to the path.
|
||||
**args All extra keyword arguments are passed to ROI()
|
||||
-------------- -------------------------------------------------------------
|
||||
"""
|
||||
sigRegionChangeFinished = QtCore.Signal(object)
|
||||
sigRegionChangeStarted = QtCore.Signal(object)
|
||||
|
@ -1523,6 +1747,18 @@ class MultiLineROI(MultiRectROI):
|
|||
print("Warning: MultiLineROI has been renamed to MultiRectROI. (and MultiLineROI may be redefined in the future)")
|
||||
|
||||
class EllipseROI(ROI):
|
||||
"""
|
||||
Elliptical ROI subclass with one scale handle and one rotation handle.
|
||||
|
||||
|
||||
**Arguments**
|
||||
-------------- -------------------------------------------------------------
|
||||
pos (length-2 sequence) The position of the ROI's origin.
|
||||
size (length-2 sequence) The size of the ROI's bounding rectangle.
|
||||
**args All extra keyword arguments are passed to ROI()
|
||||
-------------- -------------------------------------------------------------
|
||||
|
||||
"""
|
||||
def __init__(self, pos, size, **args):
|
||||
#QtGui.QGraphicsRectItem.__init__(self, 0, 0, size[0], size[1])
|
||||
ROI.__init__(self, pos, size, **args)
|
||||
|
@ -1540,6 +1776,10 @@ class EllipseROI(ROI):
|
|||
p.drawEllipse(r)
|
||||
|
||||
def getArrayRegion(self, arr, img=None):
|
||||
"""
|
||||
Return the result of ROI.getArrayRegion() masked by the elliptical shape
|
||||
of the ROI. Regions outside the ellipse are set to 0.
|
||||
"""
|
||||
arr = ROI.getArrayRegion(self, arr, img)
|
||||
if arr is None or arr.shape[0] == 0 or arr.shape[1] == 0:
|
||||
return None
|
||||
|
@ -1557,12 +1797,25 @@ class EllipseROI(ROI):
|
|||
|
||||
|
||||
class CircleROI(EllipseROI):
|
||||
"""
|
||||
Circular ROI subclass. Behaves exactly as EllipseROI, but may only be scaled
|
||||
proportionally to maintain its aspect ratio.
|
||||
|
||||
**Arguments**
|
||||
-------------- -------------------------------------------------------------
|
||||
pos (length-2 sequence) The position of the ROI's origin.
|
||||
size (length-2 sequence) The size of the ROI's bounding rectangle.
|
||||
**args All extra keyword arguments are passed to ROI()
|
||||
-------------- -------------------------------------------------------------
|
||||
|
||||
"""
|
||||
def __init__(self, pos, size, **args):
|
||||
ROI.__init__(self, pos, size, **args)
|
||||
self.aspectLocked = True
|
||||
#self.addTranslateHandle([0.5, 0.5])
|
||||
self.addScaleHandle([0.5*2.**-0.5 + 0.5, 0.5*2.**-0.5 + 0.5], [0.5, 0.5])
|
||||
|
||||
|
||||
|
||||
class PolygonROI(ROI):
|
||||
## deprecated. Use PloyLineROI instead.
|
||||
|
||||
|
@ -1616,8 +1869,24 @@ class PolygonROI(ROI):
|
|||
return sc
|
||||
|
||||
class PolyLineROI(ROI):
|
||||
"""Container class for multiple connected LineSegmentROIs. Responsible for adding new
|
||||
line segments, and for translation/(rotation?) of multiple lines together."""
|
||||
"""
|
||||
Container class for multiple connected LineSegmentROIs.
|
||||
|
||||
This class allows the user to draw paths of multiple line segments.
|
||||
|
||||
**Arguments**
|
||||
-------------- -------------------------------------------------------------
|
||||
positions (list of length-2 sequences) The list of points in the path.
|
||||
Note that, unlike the handle positions specified in other
|
||||
ROIs, these positions must be expressed in the normal
|
||||
coordinate system of the ROI, rather than (0 to 1) relative
|
||||
to the size of the ROI.
|
||||
closed (bool) if True, an extra LineSegmentROI is added connecting
|
||||
the beginning and end points.
|
||||
**args All extra keyword arguments are passed to ROI()
|
||||
-------------- -------------------------------------------------------------
|
||||
|
||||
"""
|
||||
def __init__(self, positions, closed=False, pos=None, **args):
|
||||
|
||||
if pos is None:
|
||||
|
@ -1730,6 +1999,10 @@ class PolyLineROI(ROI):
|
|||
return p
|
||||
|
||||
def getArrayRegion(self, data, img, axes=(0,1), returnMappedCoords=False, **kwds):
|
||||
"""
|
||||
Return the result of ROI.getArrayRegion(), masked by the shape of the
|
||||
ROI. Values outside the ROI shape are set to 0.
|
||||
"""
|
||||
sl = self.getArraySlice(data, img, axes=(0,1))
|
||||
if sl is None:
|
||||
return None
|
||||
|
@ -1758,6 +2031,14 @@ class PolyLineROI(ROI):
|
|||
class LineSegmentROI(ROI):
|
||||
"""
|
||||
ROI subclass with two freely-moving handles defining a line.
|
||||
|
||||
**Arguments**
|
||||
-------------- -------------------------------------------------------------
|
||||
positions (list of two length-2 sequences) The endpoints of the line
|
||||
segment. Note that, unlike the handle positions specified in
|
||||
other ROIs, these positions must be expressed in the normal
|
||||
coordinate system of the ROI, rather than (0 to 1) relative
|
||||
to the size of the ROI.
|
||||
"""
|
||||
|
||||
def __init__(self, positions=(None, None), pos=None, handles=(None,None), **args):
|
||||
|
@ -1810,8 +2091,13 @@ class LineSegmentROI(ROI):
|
|||
|
||||
def getArrayRegion(self, data, img, axes=(0,1)):
|
||||
"""
|
||||
Use the position of this ROI relative to an imageItem to pull a slice from an array.
|
||||
Since this pulls 1D data from a 2D coordinate system, the return value will have ndim = data.ndim-1
|
||||
Use the position of this ROI relative to an imageItem to pull a slice
|
||||
from an array.
|
||||
|
||||
Since this pulls 1D data from a 2D coordinate system, the return value
|
||||
will have ndim = data.ndim-1
|
||||
|
||||
See ROI.getArrayRegion() for a description of the arguments.
|
||||
"""
|
||||
|
||||
imgPts = [self.mapToItem(img, h['item'].pos()) for h in self.handles]
|
||||
|
|
Loading…
Reference in New Issue
Block a user