
    em}                    2   d Z ddlZddlmZmZmZmZmZ ddlZ	ddl
mZ ddlmZ ddlmZmZmZ ddlmZ d	d
lmZ d	dlmZ ej*                  j,                  Zg dZd Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d dej@                        Z! G d de!      Z" G d de      Z# G d  d!e#      Z$ G d" d#e      Z% G d$ d%e      Z& G d& d'e&      Z' G d( d)e      Z( G d* d+e&      Z) G d, d-e      Z*y).a  
ROI.py -  Interactive graphics items for GraphicsView (ROI widgets)
Copyright 2010  Luke Campagnola
Distributed under MIT/X11 license. See license.txt for more information.

Implements a series of graphics items which display movable/scalable/rotatable shapes
for use as region-of-interest markers. ROI class automatically handles extraction 
of array data from ImageItems.

The ROI class is meant to serve as the base for more specific types; see several examples
of how to build an ROI at the bottom of the file.
    N)atan2cosdegreeshypotsin   )	functions)Point)QtCoreQtGui	QtWidgets)SRTTransform   )GraphicsObject)UIGraphicsItem)ROITestROIRectROI
EllipseROI	CircleROILineROIMultiLineROIMultiRectROILineSegmentROIPolyLineROICrosshairROITriangleROIc                     d| j                         | j                         | j                         | j                         fz  S )Nz[%f, %f] + [%f, %f])xywidthheight)rs    =/usr/lib/python3/dist-packages/pyqtgraph/graphicsItems/ROI.pyrectStrr%   &   s.     ACCE1335!'')QXXZ#HHH    c                      e Zd ZdZ ej
                  e      Z ej
                  e      Z ej
                  e      Z	 ej
                  e      Z
 ej
                  ee      Z ej
                  e      Z edd      dddddddddddddddddfdZd	 Zd
 Zd ZdGdZd Zd Zd Zd Zd Zd ZdHdZdIdZdIdZdIdZd ZdJdZd ZdKdZ dLdZ!dMdZ"dNdZ#dNdZ$dKdZ%dOd Z&d! Z'd" Z(d# Z)d$ Z*dOd%Z+dOd&Z,d' Z-d( Z.d) Z/d* Z0d+ Z1d, Z2d- Z3d. Z4d/ Z5d0 Z6d1 Z7d2 Z8d3 Z9d4 Z:d5 Z;d6 Z<d7 Z=d8 Z>dPd9Z?dGd:Z@d; ZAd< ZBdOd=ZCd> ZDd? ZEdQd@ZFdRdAZGdRdBZHdRdCZIdD ZJdOdEZKdF ZLy)Sr   aW  
    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 manipulate the ROI.

    Default mouse interaction:

      * Left drag moves the ROI
      * Left drag + Ctrl moves the ROI with position snapping
      * Left drag + Alt rotates the ROI
      * Left drag + Alt + Ctrl rotates the ROI with angle snapping
      * Left drag + Shift scales the ROI
      * Left drag + Shift + Ctrl scales the ROI with size snapping

    In addition to the above interaction modes, it is possible to attach any
    number of handles to the ROI that can be dragged to change the ROI in
    various ways (see the ROI.add____Handle methods).


    ================ ===========================================================
    **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 
                     the ROI's snap angle (default is 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.
    hoverPen         (QPen or argument to mkPen) The pen to use while the
                     mouse is hovering over the ROI shape.
    handlePen        (QPen or argument to mkPen) The pen to use when drawing
                     the ROI handles.
    handleHoverPen   (QPen or argument to mkPen) The pen to use while the mouse
                     is hovering over an ROI handle.
    movable          (bool) If True, the ROI can be moved by dragging anywhere 
                     inside the ROI. Default is True.
    rotatable        (bool) If True, the ROI can be rotated by mouse drag + ALT
    resizable        (bool) If True, the ROI can be resized by mouse drag + 
                     SHIFT
    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.
    ================ ===========================================================
    
    
    
    ======================= ====================================================
    **Signals**
    sigRegionChangeFinished Emitted when the user stops dragging the ROI (or
                            one of its handles) or if the ROI is changed
                            programatically.
    sigRegionChangeStarted  Emitted when the user starts dragging the ROI (or
                            one of its handles).
    sigRegionChanged        Emitted any time the position of the ROI changes,
                            including while it is being dragged by the user.
    sigHoverEvent           Emitted when the mouse hovers over the ROI.
    sigClicked              Emitted when the user clicks on the ROI.
                            Note that clicking is disabled by default to prevent
                            stealing clicks from objects behind the ROI. To 
                            enable clicking, call 
                            roi.setAcceptedMouseButtons(QtCore.Qt.MouseButton.LeftButton). 
                            See QtWidgets.QGraphicsItem documentation for more 
                            details.
    sigRemoveRequested      Emitted when the user selects 'remove' from the 
                            ROI's context menu (if available).
    ======================= ====================================================
    r   g        FN      ?Tc                 x   t        j                  | |
       | j                  t        j                  j
                  j                         t        |      }t        |      }|| _        || _	        || _
        || _        || _        d | _        d| _        d| _        |d}| j!                  |       |d}t#        j$                  |      | _        |d}t#        j$                  |      | _        |d}|| _        g | _        t        dd      t        dd      dd| _        d | _        | j3                  |       | j5                  |       | j7                  |       | j9                  d       d| _        d	| _        || _        || _         || _!        || _"        |	| _#        d
| _$        || _%        || _&        tO        |       | _(        y )NF)   r*   r*   r*   r*   r   )   r*   r*   r   r   )possizeangle
      g      .@))r   __init__setAcceptedMouseButtonsr   QtMouseButtonNoButtonr
   aspectLockedtranslatable	rotatable	resizable	removablemenufreeHandleMovedmouseHoveringsetPenfnmkPenhoverPen	handlePenhandleHoverPenhandlesstate	lastStatesetPossetAnglesetSize	setZValueisMoving
handleSize
invertible	maxBoundssnapSizetranslateSnap
rotateSnaprotateSnapAngle	scaleSnapscaleSnapSizeMouseDragHandlermouseDragHandler)selfr-   r.   r/   rN   rO   rP   rT   rQ   rR   parentpenrB   rC   rD   movabler9   r:   r;   r7   s                       r$   r2   zROI.__init__   s    	f-$$VYY%:%:%C%CDCjT{(#"""	$";!CC$H*'I),!*N,"1QZqaH
CeTr$" *$#"% !1 6r&   c                 "    | j                         S N)	stateCopyrX   s    r$   getStatezROI.getState   s    ~~r&   c                     i }t        | j                  d         |d<   t        | j                  d         |d<   | j                  d   |d<   |S )Nr-   r.   r/   )r
   rF   )rX   scs     r$   r^   zROI.stateCopy   sL    $**U+,5	4::f-.6
jj)7	r&   c                     i }t        | j                  d         |d<   t        | j                  d         |d<   | j                  d   |d<   |S )zReturn 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.r-   r.   r/   )tuplerF   rX   rF   s     r$   	saveStatezROI.saveState   sN     TZZ./edjj01fG,gr&   c                     | j                  |d   d       | j                  |d   d       | j                  |d   |       y)zk
        Set the state of the ROI from a structure generated by saveState() or
        getState().
        r-   Fupdater.   r/   N)rH   rJ   rI   )rX   rF   ri   s      r$   setStatezROI.setState   s@    
 	E%L/U6]51eGnV4r&   c                     t         j                  j                  | |       | j                  D ]  }|d   j                  |dz           y )Nitemr   )r   QGraphicsItemrK   rE   )rX   zhs      r$   rK   zROI.setZValue   sA    ))$2 	%AfI!$	%r&   c                 \    | j                  | j                               j                         S )zs
        Return the bounding rectangle of this ROI in the coordinate system
        of its parent.        
        )mapToParentboundingRectr_   s    r$   parentBoundszROI.parentBounds   s'    
  1 1 34AACCr&   c                 z    t        j                  |i || _        | j                  | _        | j	                          y)z|
        Set the pen to use when drawing the ROI shape.
        For arguments, see :func:`mkPen <pyqtgraph.mkPen>`.
        N)r@   rA   rZ   
currentPenri   )rX   argskwargss      r$   r?   z
ROI.setPen   s-    
 88T,V,((r&   c                 (    | j                         d   S )z!Return the size (w,h) of the ROI.r.   r`   r_   s    r$   r.   zROI.size   s    }}v&&r&   c                 (    | j                         d   S )zjReturn the position (x,y) of the ROI's origin. 
        For most ROIs, this will be the lower-left corner.r-   ry   r_   s    r$   r-   zROI.pos   s     }}u%%r&   c                 (    | j                         d   S )z'Return the angle of the ROI in degrees.r/   ry   r_   s    r$   r/   z	ROI.angle  s    }}w''r&   c                    |dvrt        d      |t        |      }n't        |t              rt        d      t        ||      }|| j                  d<   t
        j                  j                  | |       |r| j                  |       yy)a  Set the position of the ROI (in the parent's coordinate system).
        
        Accepts either separate (x, y) arguments or a single :class:`Point` or
        ``QPointF`` argument. 
        
        By default, this method causes both ``sigRegionChanged`` and
        ``sigRegionChangeFinished`` to be emitted. If *finish* is False, then
        ``sigRegionChangeFinished`` will not be emitted. You can then use 
        stateChangeFinished() to cause the signal to be emitted after a series
        of state changes.
        
        If *update* is False, the state change will be remembered but not processed and no signals 
        will be emitted. You can then use stateChanged() to complete the state change. This allows
        multiple change functions to be called sequentially while minimizing processing overhead
        and repeated signals. Setting ``update=False`` also forces ``finish=False``.
        TFupdate argument must be boolNz3Positional arguments to setPos() must be numerical.r-   finish)		TypeErrorr
   
isinstanceboolrF   r   rm   rH   stateChanged)rX   r-   r    ri   r   s        r$   rH   z
ROI.setPos  s    " &:;;9*C !T" UVVQ-C

5&&tS1V, r&   c                    |dvrt        d      t        |      }|rVt        |d   | j                  z        | j                  z  |d<   t        |d   | j                  z        | j                  z  |d<   |Jt        | j                  d         }|d   dk(  rdn|d   |d<   |d   dk(  rdn|d   |d<   t        |      |z  }|{t        |      }| j                  t        |      | j                  d   z        }| j                  t        |      |z        }	| j                  d   |z   |	z
  }
| j                  |
dd	       | j                          || j                  d<   |r| j                  |
       yy)a|  
        Set the ROI's size.
        
        =============== ==========================================================================
        **Arguments**
        size            (Point | QPointF | sequence) The final size of the ROI
        center          (None | Point) Optional center point around which the ROI is scaled,
                        expressed as [0-1, 0-1] over the size of the ROI.
        centerLocal     (None | Point) Same as *center*, but the position is expressed in the
                        local coordinate system of the ROI
        snap            (bool) If True, the final size is snapped to the nearest increment (see
                        ROI.scaleSnapSize)
        update          (bool) See setPos()
        finish          (bool) See setPos()
        =============== ==========================================================================
        r}   r~   r   r   Nr.   r-   Fri   r   r   )	r   r
   roundrU   rF   rq   rH   prepareGeometryChanger   )rX   r.   centercenterLocalsnapri   r   oldSizecc1newPoss              r$   rJ   zROI.setSize'  su   " &:;;T{DGd&8&889D<N<NNDGDGd&8&889D<N<NNDG"DJJv./G%ajAo71:GAJ%ajAo71:GAJ;''1F6]F  vF1C!CDA!!%-$"67BZZ&*R/FKKuUK;""$!

6V, r&   c                    |dvrt        d      |du r%t        || j                  z        | j                  z  }|| j                  d<   t	        j
                         }|j                  |       |t        |      | j                  d   z  }|Qt        |      }| j                  |      |j                  |      | j                  d   z   z
  }| j                  |d	       | j                  |       |r| j                  |
       yy)a  
        Set the ROI's rotation angle.
        
        =============== ==========================================================================
        **Arguments**
        angle           (float) The final ROI angle in degrees
        center          (None | Point) Optional center point around which the ROI is rotated,
                        expressed as [0-1, 0-1] over the size of the ROI.
        centerLocal     (None | Point) Same as *center*, but the position is expressed in the
                        local coordinate system of the ROI
        snap            (bool) If True, the final ROI angle is snapped to the nearest increment
                        (default is 15 degrees; see ROI.rotateSnapAngle)
        update          (bool) See setPos()
        finish          (bool) See setPos()
        =============== ==========================================================================
        r}   r~   Tr/   Nr.   r-   Frh   r   )r   r   rS   rF   r   
QTransformrotater
   rq   map	translatesetTransformr   )	rX   r/   r   r   r   ri   r   trccs	            r$   rI   zROI.setAngleQ  s    " &:;;4<%$"6"667$:N:NNE#

7
		%-$**V*<<K",K!!+."&&2E

SXHY2YZBNN2eN,"V, r&   c                 V    | j                   d   |z  }| j                  ||||||       y)z
        Resize the ROI by scaling relative to *center*.
        See setPos() for an explanation of the *update* and *finish* arguments.
        r.   )r   r   r   ri   r   N)rF   rJ   )rX   sr   r   r   ri   r   newSizes           r$   scalez	ROI.scalew  s1    
 **V$q(WV4X^gmnr&   c                    t        |      dk(  r|d   }n|}| j                         }|d   |z   |d<   |j                  dd      }|| j                  }|dur| j	                  |d   |      |d<   | j
                  | j                  |      }t        dd      }| j
                  j                         |j                         kD  r/| j
                  j                         |j                         z
  |d<   nY| j
                  j                         |j                         k  r.| j
                  j                         |j                         z
  |d<   | j
                  j                         |j                         kD  r/| j
                  j                         |j                         z
  |d<   nY| j
                  j                         |j                         k  r.| j
                  j                         |j                         z
  |d<   |dxx   |z  cc<   |j                  dd	      }|j                  d
d	      }	| j                  |d   ||	       y)ay  
        Move the ROI to a new position.
        Accepts either (x, y, snap) or ([x,y], snap) as arguments
        If the ROI is bounded and the move would exceed boundaries, then the ROI
        is moved to the nearest acceptable position instead.
        
        *snap* can be:
        
        =============== ==========================================================================
        None (default)  use self.translateSnap and self.snapSize to determine whether/how to snap
        False           do not snap
        Point(w,h)      snap to rectangular grid with spacing (w,h)
        True            snap using self.snapSize (and ignoring self.translateSnap)
        =============== ==========================================================================
           
        Also accepts *update* and *finish* arguments (see setPos() for a description of these).
        r   r   r-   r   NF)r   ri   Tr   r   )lenr^   getrQ   getSnapPositionrO   	stateRectr
   leftrighttopbottomrH   )
rX   rv   kargsptnewStater   r#   dri   r   s
             r$   r   zROI.translate  s   & t9>aBB>>#"5/B.yy&<%%Du"228E?2NHUO>>%x(Aa
A~~""$qvvx/~~**,qvvx7!%%'!'')3~~++-	9!~~!!#aeeg-~~))+aeeg5!&&(188:5~~,,.;!UOq O8T*8T*HUOF6Br&   c                 R    | j                  | j                         |z   ||||       y)a  
        Rotate the ROI by *angle* degrees. 
        
        =============== ==========================================================================
        **Arguments**
        angle           (float) The angle in degrees to rotate
        center          (None | Point) Optional center point around which the ROI is rotated, in
                        the local coordinate system of the ROI
        snap            (bool) If True, the final ROI angle is snapped to the nearest increment
                        (default is 15 degrees; see ROI.rotateSnapAngle)
        update          (bool) See setPos()
        finish          (bool) See setPos()
        =============== ==========================================================================
        )r   r   ri   r   N)rI   r/   )rX   r/   r   r   ri   r   s         r$   r   z
ROI.rotate  s&     	djjl5(d6Z`ar&   c                 d    | j                         | _        | j                  j                  |        y r]   )r`   preMoveStatesigRegionChangeStartedemitr_   s    r$   handleMoveStartedzROI.handleMoveStarted  s$     MMO##((.r&   c                 H    t        |      }| j                  |d||d|      S )a  
        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.
        =================== ====================================================
        tnametyper-   rl   indexr
   	addHandlerX   r-   axesrl   r   r   s         r$   addTranslateHandlezROI.addTranslateHandle  s*    , Cj~~tSdS[`~aar&   c                 L    |t        |      }| j                  |d||d|      S )a  
        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.
        =================== ====================================================
        fr   r   r   r   s         r$   addFreeHandlezROI.addFreeHandle  s/    $ ?*C~~tSdS[`~aar&   c                     t        |      }t        |      }|d||||d}|j                         |j                         k(  rd|d<   |j                         |j                         k(  rd|d<   | j                  ||      S )a  
        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.
        =================== ====================================================
        r   )r   r   r   r-   rl   
lockAspectTxoffyoffr   )r
   r   r    r   )	rX   r-   r   r   rl   r   r   r   infos	            r$   addScaleHandlezROI.addScaleHandle  sw    , CjvcVCQUeop557fhhj DL557fhhj DL~~d%~00r&   c                 `    t        |      }t        |      }| j                  |d|||d|      S )a[  
        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.
        =================== ====================================================
        r#   r   r   r   r-   rl   r   r   rX   r-   r   rl   r   r   s         r$   addRotateHandlezROI.addRotateHandle  s7    ( Cjv~~tSFSV`demr~ssr&   c                     t        |      }t        |      }|d   |d   k(  r|d   |d   k(  rt        d      | j                  |d|||d|      S )a  
        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.
        =================== ====================================================
        r   r   z5Scale/rotate handles cannot be at their center point.srr   r   )r
   	Exceptionr   r   s         r$   addScaleRotateHandlezROI.addScaleRotateHandle,  sb    , Cjvq6VAY3q6VAY#6STT~~tTVTWaefns~ttr&   c                 `    t        |      }t        |      }| j                  |d|||d|      S )a  
        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.
        =================== ====================================================
        rfr   r   r   )rX   r-   r   r   rl   r   r   s          r$   addRotateFreeHandlezROI.addRotateFreeHandleH  s7    , Cjv~~tTVTWaefns~ttr&   c                    d|vs|d   7t        | j                  |d   | j                  | j                  |       }||d<   n|d   }|d   |j	                         |d<   |j                  |d   | j                  d   z         |j                  |        || j                  j                  |       n| j                  j                  ||       |j                  | j                         dz          | j                          |S )Nrl   r   )typrZ   rB   rY   r-   r.   r   )HandlerM   rC   rD   r-   rH   rF   
connectROIrE   appendinsertrK   zValuer   rX   r   r   ro   s       r$   r   zROI.addHandleb  s    f!5tDLdnn $ 3 3DBADLVAE{"eegU	etzz&112 	
T=LL%LLt,	DKKM!O$r&   c                     t        |t              rMt        | j                        D cg c]  \  }}|d   |u s| }}}t	        |      dk(  rt        d      |d   S |S c c}}w )zQ
        Return the index of *handle* in the list of this ROI's handles.
        rl   r   z4Cannot return handle index; not attached to this ROI)r   r   	enumeraterE   r   r   )rX   handleir   r   s        r$   indexOfHandlezROI.indexOfHandlez  se     ff%&/&=X71dfQWAWQXEX5zQ VWW8OM Ys
   A A c                 P   | j                  |      }| j                  |   d   }| j                  j                  |       |j                  |        t	        |j
                        dk(  r/| j                         | j                         j                  |       | j                          y)ztRemove a handle from this ROI. Argument may be either a Handle 
        instance or the integer index of the handle.rl   r   N)	r   rE   popdisconnectROIr   roisscene
removeItemr   )rX   r   r   s      r$   removeHandlezROI.removeHandle  s     ""6*e$V,T"v{{q TZZ\%=JJL##F+r&   c                     | j                  |      }| j                  |   }| j                  |       ||d<   |j                         |d<   | j	                  ||       y)zReplace 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.rl   r-   r   N)r   rE   r   r-   r   )rX   	oldHandle	newHandler   r   s        r$   replaceHandlezROI.replaceHandle  sX     ""9-||E"%  VmmoUt5)r&   c                      yNT )rX   r   s     r$   checkRemoveHandlezROI.checkRemoveHandle  s    
 r&   c                     |.g }| j                   D ]  }|j                  |d   |d   f        |S | j                   |   d   | j                   |   d   fS )zReturns the position of handles in the ROI's coordinate system.
        
        The format returned is a list of (name, pos) tuples.
        r   r-   )rE   r   rX   r   	positionsro   s       r$   getLocalHandlePositionszROI.getLocalHandlePositions  si    
 =I\\ 8  !F)QuX!678LL'/e1DU1KLLr&   c                     |<g }| j                   D ])  }|j                  |d   |d   j                         f       + |S | j                   |   d   | j                   |   d   j                         fS )zReturns the position of handles in the scene coordinate system.
        
        The format returned is a list of (name, pos) tuples.
        r   rl   )rE   r   scenePosr   s       r$   getSceneHandlePositionszROI.getSceneHandlePositions  s}    
 =I\\ D  !F)QvY-?-?-A!BCDLL'/e1DV1L1U1U1WXXr&   c                 F    | j                   D cg c]  }|d   	 c}S c c}w )z6
        Return a list of this ROI's Handles.
        rl   rE   rX   ro   s     r$   
getHandleszROI.getHandles  s      $(<<0a&	000   c                 B    | j                  | j                  |            S r]   )rq   mapFromScene)rX   r   s     r$   mapSceneToParentzROI.mapSceneToParent  s     1 1" 566r&   c                     t         j                  j                  | |       |r%| j                  D ]  }|d   j	                           y | j                  D ]  }|d   j                           y Nrl   )r   rm   setSelectedrE   showhide)rX   r   ro   s      r$   r   zROI.setSelected  s_    ++D!4\\ !&	 ! \\ !&	 !r&   c                    d}|j                         s| j                  r5|j                  t        j                  j
                  j                        rd}t        j                  j
                  j                  t        j                  j
                  j                  t        j                  j
                  j                  fD ]*  }| j                         |z  s|j                  |      s)d}, | j                         r3|j                  t        j                  j
                  j                         |r| j                  d       |j                  t        j                  j
                  j                         |j                  t        j                  j
                  j                         |j                  t        j                  j
                  j                         | j                  j                  |        y | j                  d       y NFT)isExitr8   acceptDragsr   r4   r5   
LeftButtonRightButtonMiddleButtonacceptedMouseButtonsacceptClickscontextMenuEnabledsetMouseHoversigHoverEventr   rX   evhoverbtns       r$   
hoverEventzROI.hoverEvent  sW   yy{  R^^FII4I4I4T4T%U		--88&)):O:O:[:[]c]f]f]r]r]]  A --/#52??3;OE &&(		 5 5 A ABt$OOFII11<<=OOFII11==>OOFII11>>?##D)u%r&   c                 R    | j                   |k(  ry || _         | j                          y r]   )r>   _updateHoverColorrX   r  s     r$   r	  zROI.setMouseHover  s'    &" r&   c                 r    | j                         }| j                  |k7  r|| _        | j                          y y r]   )_makePenru   ri   )rX   rZ   s     r$   r  zROI._updateHoverColor  s.    mmo??c!!DOKKM "r&   c                 J    | j                   r| j                  S | j                  S r]   )r>   rB   rZ   r_   s    r$   r  zROI._makePen  s    == 88Or&   c                     | j                   xs4 | j                  xr& t        | j                  j                               dkD  S Nr   )r;   r<   r   childrenr_   s    r$   r  zROI.contextMenuEnabled  s1    ~~L!Ls4993E3E3G/H1/LLr&   c           	      N   | j                         sy | j                         }| j                         j                  | ||      }|j	                         }|j                  t        j                  t        |j                               t        |j                                            y r]   )r  getMenur   addParentContextMenus	screenPospopupr   QPointintr   r    )rX   r  r<   r-   s       r$   raiseContextMenuzROI.raiseContextMenu  sl    &&(||~zz|11$bAlln

6==SUUWs3557|<=r&   c                    | j                   t        j                         | _         | j                   j                  t	        dd             | j
                  r{t        j                  t	        dd      | j                         }|j                  j                  | j                         | j                   j                  |       || j                   _        | j                   S )Nr   z
Remove ROI)r<   r   QMenusetTitler   r;   r   QAction	triggeredconnectremoveClicked	addActionremAct)rX   r)  s     r$   r  zROI.getMenu  s    99!)DIIIy67~~y'EtyyQ  ((););<		##F+#)		 yyr&   c                 X    t         j                  j                  d| j                         y )Nr   )r   QTimer
singleShot_emitRemoveRequestr_   s    r$   r'  zROI.removeClicked  s      D$;$;<r&   c                 :    | j                   j                  |        y r]   sigRemoveRequestedr   r_   s    r$   r-  zROI._emitRemoveRequest      $$T*r&   c                 :    | j                   j                  |       y r]   )rW   mouseDragEventrX   r  s     r$   r3  zROI.mouseDragEvent  s    ,,R0r&   c                 P   |j                         t        j                  j                  j                  k(  r,| j
                  r |j                          | j                          |j                         t        j                  j                  j                  k(  r2| j                         r"| j                  |       |j                          y | j                         |j                         z  r-|j                          | j                  j                  | |       y |j                          y r]   )buttonr   r4   r5   r  rL   accept
cancelMover  r   r  
sigClickedr   ignorer4  s     r$   mouseClickEventzROI.mouseClickEvent  s    99;&))//;;;IIKOO99;&))//;;;@W@W@Y!!"%IIK&&(299;6IIKOO  r*IIKr&   c                 r    d| _         | j                         | _        | j                  j	                  |        y r   )rL   r`   r   r   r   r_   s    r$   _moveStartedzROI._moveStarted)  s+     MMO##((.r&   c                 J    | j                   r| j                          d| _         y NF)rL   stateChangeFinishedr_   s    r$   _moveFinishedzROI._moveFinished.  s    ==$$&r&   c                 H    d| _         | j                  | j                         y r?  )rL   rj   r   r_   s    r$   r8  zROI.cancelMove3  s    d''(r&   c                      y)zWhen handles move, they must ask the ROI if the move is acceptable.
        By default, this always returns True. Subclasses may wish override.
        Tr   )rX   r   r-   	modifierss       r$   checkPointMovezROI.checkPointMove7  s     r&   c                    |$t         j                  j                  j                  }| j	                         }| j                  |      }| j                  |   }| j                  |d   | j                  d   z        }	t        |      }
|dk(  rn"|dk(  r| j                  |
      }
nt        d      d|v r?|d   }|| j                  d   z  }| j                  |	      |z
  }| j                  |
      |z
  }|d   dk(  rD|t         j                  j                  j                  z  rd	nd }| j                  |
|	z
  |d
       n |d   dk(  r3| j                  |
      }|d   j                  |       ||d<   d	| _        n|d   dk(  rC|d   d   |d   d   k(  rdd<   |d   d   |d   d   k(  rdd<   | j"                  s'|t         j                  j                  j                  z  rVt%        d   | j&                  z        | j&                  z  |d<   t%        |d   | j&                  z        | j&                  z  |d<   |d   s'|t         j                  j                  j(                  z  rj+                        }|d   z
  }|d   dk(  rd|d<   |d   dk(  rd|d<   |z  }|d   dk(  r|d   d   |d<   |d   dk(  r|d   d   |d<   | j,                  s&|d   dk  r|d   d   |d<   |d   dk  r|d   d   |d<   | j.                  r|d   |d<   || j                  d   z  }||z  }| j                  ||z
        | j                  t        dd            z
  }||d<   |d   |z   |d<   | j0                  -| j3                  |      }| j0                  j5                  |      sy | j                  |d   d
       | j7                  |d   d
       ny|d   dv r|d   dk(  rd	| _        | j8                  sy 	 j;                         dk(  sj;                         dk(  ry 	 |d   |j?                  |      z
  }|y | j@                  s'|t         j                  j                  j                  z  r%t%        || jB                  z        | jB                  z  }tE        jF                         }|jI                  |       | j                        |jK                  |      | j                  d   z   z
  }||d<   |d   |z   |d<   | j0                  -| j3                  |      }| j0                  j5                  |      sy | j                  |d   d
       | jM                  |d
       |d   dk(  r|d   j                  | jO                  |
             | j                  |
      |d<   n|d   dk(  r	 j;                         dk(  sj;                         dk(  ry 	 |d   |j?                  |      z
  }|y | j@                  s'|t         j                  j                  j                  z  r%t%        || jB                  z        | jB                  z  }| j.                  s|d   d   |d   d   k7  rw| j                  d   d   |j;                         z  |j;                         z  |d   d<   | j"                  r1t%        |d   d   | jP                  z        | jP                  z  |d   d<   | j.                  s|d   d   |d   d   k7  rw| j                  d   d   |j;                         z  |j;                         z  |d   d<   | j"                  r1t%        |d   d   | jP                  z        | jP                  z  |d   d<   |d   d   dk(  rd|d   d<   |d   d   dk(  rd|d   d<   |d   z  }tE        jF                         }|jI                  |       | j                        |jK                  |      | j                  d   z   z
  }||d<   |d   |z   |d<   | j0                  -| j3                  |      }| j0                  j5                  |      sy | jS                  |d
       | jU                  |       y # t<        $ r Y y w xY w# t<        $ r Y y w xY w)Nr-   r.   rY   r   zKNew point location must be given in either 'parent' or 'scene' coordinates.r   r   r   TF)r   ri   r   rl   r   r   r   r   rh   )r#   r   r   r/   r   r   )+r   r4   KeyboardModifier
NoModifierr^   r   rE   rq   rF   r
   r   r   mapFromParentControlModifierr   rH   r=   rT   r   rU   AltModifierprojrN   r7   rO   r   containsrJ   r9   lengthOverflowErrorr/   rR   rS   r   r   r   r   rI   r   rP   rj   r   )rX   r   r-   rD  r   coordsr   r   ro   p0p1r   cslp0lp1r   r   hsr   s0s1r   r#   angr   r   s                             r$   	movePointzROI.movePoint=  sl    		22==I>>#""6*LLahF);;<3ZXw&&r*Bijj q=(ATZZ''B$$R(2-C$$R(2-CV9%		(B(B(R(RR4Y]DNN2b5tEN:vY#''+FfIV$AeH#'D vY#{1~5!,A{1~5!,A ~~)fii.H.H.X.X"Xs1v(:(::;d>P>PPAs1v(:(::;d>P>PPA 9vyy/I/I/U/U#Uhhsm 5AB!uz1!uz1BhG qzQ%f-a0
qzQ%f-a0
??1:>!)&!1!!4GAJ1:>!)&!1!!4GAJ  $QZ
 TZZ''BWB!!"r'*T-=-=eAqk-JJB  'HV&uo2HUO~~)NN8,~~..q1KKK6LL&)%L8vY+%yD '+$>>::<1$

(9 ): 7#ciin4C{9vyy/I/I/Y/Y#YC$"6"667$:N:NN !!#BIIcN !!"%djj6G)GHB #HW&uo2HUO ~~)NN8,~~..q1KKK6MM#eM, yD &	  !2!22!67--b1%vY$::<1$

(9 ):
 7#ciin4C{9vyy/I/I/Y/Y#YC$"6"667$:N:NN  AhKNahqk$A&*jj&8&;cjjl&JSZZ\&Y #>>*/0@0Cdmm0S*TW[WdWd*dHV$Q'  AhKNahqk$A&*jj&8&;cjjl&JSZZ\&Y #>>*/0@0Cdmm0S*TW[WdWd*dHV$Q'"a'&' #"a'&' #Xf%%B!!#BIIcN!!"%djj6G)GHB #HW&uo2HUO~~)NN8,~~..q1MM(5M1(W ! J ! s$   )&a &a 	aa	a+*a+c                    d}| j                   d}nF| j                         }t        |j                               D ]  }||   | j                   |   k7  sd} | j	                          |rz| j
                  D ]?  }|d   | j                         v s|d   j                  |d   | j                  d   z         A | j                          | j                  j                  |        n'| j                  r| j                  j                  |        d| _        | j                         | _         |r!| j                          | j                          yy)zProcess changes to the state of the ROI.
        If there are any changes, then the positions of handles are updated accordingly
        and sigRegionChanged is emitted. If finish is True, then 
        sigRegionChangeFinished will also be emitted.FNTrl   r-   r.   )rG   r`   listkeysr   rE   
childItemsrH   rF   ri   sigRegionChangedr   r=   r@  informViewBoundsChanged)rX   r   changedrF   kro   s         r$   r   zROI.stateChanged  s%    >>!GMMOE%**,' #8t~~a00"G# 	""$\\ DV9 11fI$$QuX

60B%BCD KKM!!&&t,!!!!&&t,$$$&((* r&   c                 :    | j                   j                  |        y r]   sigRegionChangeFinishedr   r_   s    r$   r@  zROI.stateChangeFinished      $$))$/r&   c                    t        j                  dd|d   d   |d   d         }t        j                         }|j	                  |d           |j                  |      }|j                  |d   d   |d   d   |d   d   |d   d         S )Nr   r.   r   r/   r-   )r   QRectFr   r   r   mapRectadjusted)rX   rF   r#   r   s       r$   r   zROI.stateRect  s    MM!Qfa 0%-2BC
		5>/"JJqMzz%,q/5<?E%LOUSX\Z[_]]r&   c                     ||du r.| j                   |S t        | j                   | j                         }t        t        |d   |d   z        |d   z  t        |d   |d   z        |d   z        S )NTr   r   )rP   r
   r   )rX   r-   r   s      r$   r   zROI.getSnapPosition  s{    
 <44<}}$
6D#a&47"#d1g-#a&47"#d1g-
 	
r&   c                     t        j                  dd| j                  d   d   | j                  d   d         j                         S Nr   r.   r   )r   rh  rF   
normalizedr_   s    r$   rr   zROI.boundingRect(  s<    }}Q4::f#5a#8$**V:LQ:OP[[]]r&   c                    t        j                  dd| j                  d   d   | j                  d   d         j                         }|j	                  t
        j                  j                  j                         |j                  | j                         |j                  |j                         |j                                |j                  |j                         |j!                                |j#                  dddd       y rm  )r   rh  rF   rn  setRenderHintr   QPainter
RenderHintAntialiasingr?   ru   r   r   r   r   r!   r"   drawRectrX   poptwidgetr#   s        r$   paintz	ROI.paint+  s    MM!Q

6 21 5tzz&7I!7LMXXZ	11>>?	!	AFFHaeeg&		188:&	

1aAr&   c           
         |j                   |d      |j                   |d      f}	 | j                         t        j                  |j                               z  }|j                  }|dk(  rM|j                  t        |d         |j                         z  t        |d         |j                         z         nL|j                  t        |d         |j                         z  t        |d         |j                         z         |j                  | j                               }|dk(  r.|j                  t        j                   dd|d   |d               }	n-|j                  t        j                   dd|d   |d               }	t#        t%        |	j'                         |	j)                                     t#        dt+        |	j'                         |	j)                               z         ft#        t%        |	j-                         |	j/                                     t#        dt+        |	j-                         |	j/                               z         ff}
|dk(  r|
ddd   }
|rHt1        d      g|j2                  z  }t1        |
d    ||d   <   t1        |
d    ||d   <   t5        |      |fS |
|fS # t        j
                  j
                  j                  $ r Y yw xY w)aX  Return a tuple of slice objects that can be used to slice the region
        from *data* that is covered by the bounding rectangle of this ROI.
        Also returns the transform that maps the ROI into data coordinates.
        
        If returnSlice is set to False, the function returns a pair of tuples with the values that would have 
        been used to generate the slice objects. ((ax0Start, ax0Stop), (ax1Start, ax1Stop))
        
        If the slice cannot be computed (usually because the scene/transforms are not properly
        constructed yet), then the method returns None.
        r   r   N	row-major)shapesceneTransformr@   invertQTransformnplinalgLinAlgError	axisOrderr   floatr!   r"   ri  rr   intersectedr   rh  r  minr   r   maxr   r   slicendimrd   )rX   dataimgr   returnSlicedShaper   r  
dataBounds	intBoundsboundssls               r$   getArraySlicezROI.getArraySlice5  sq    **T!W%tzz$q'':;	$$&)<)<S=O=O=Q)RRB
 MM	#HHU6!9%		3U6!95E

5TUHHU6!9%		3U6!95E

5TU ZZ 1 1 34
 #"..v}}Q6!9fUVi/XYI"..v}}Q6!9fUVi/XYI Y^^%y'89:C#innFVXaXgXgXiBj@j<klY%%'9:C#iFVFVFXZcZgZgZiBj@j<kl
 #DbD\F+*B+BtAwK+BtAwK9b= 2:E yy++ 		s   4J( ('KKc                    |j                  dd      }| j                  ||||      \  }}}	|j                  d|      }
|j                  d|      }|j                  d|	      }|st        j                  |f|
|||d|}|S d|d	<   t        j                  |f|
|||d|\  }}t        j                  |j                         |      }||fS )
a  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, y) axes of *img*. If the
                            image's axis order is set to
                            'row-major', then the axes are instead specified in
                            (y, x) order.
        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 pass to :func:`affineSlice <pyqtgraph.affineSlice>`.
        
        If *returnMappedCoords* is True, then the method returns a tuple (result, coords) 
        such that coords is the set of coordinates used to interpolate values from the original
        data, mapped into the parent coordinate system of the image. This is useful, when slicing
        data from images that have been transformed, for determining the location of each value
        in the sliced data.
        
        All extra keyword arguments are passed to :func:`affineSlice <pyqtgraph.affineSlice>`.
        fromBoundingRectF)r  r}  vectorsorigin)r}  r  r  r   TreturnCoords)r   getAffineSliceParamsr@   affineSlicetransformCoordinates	transform)rX   r  r  r   returnMappedCoordskwdsfromBR_shape_vectors_originr}  r  r  rgnresultrP  mappeds                    r$   getArrayRegionzROI.getArrayRegionj  s    J ,e4 %)$=$=dC`f$=$g!' &)((9h/(G,!..fUGFY]faefCJ#'D ^^DqwW]dhqlpqNFF ,,S]]_fEF6>!r&   c                 <   |r t        j                  | ||||fddi|\  }}nt        j                  | ||||fddi|}|j                  dk(  r3| j                  |j                  |d      |j                  |d            }n>| j                  |j                  |d      |j                  |d            }|j
                  }dg|j                  z  }	|j                  |d      |	|d   <   |j                  |d      |	|d   <   |j                  |	      }|r||z  fS ||z  S )z
        Return the result of :meth:`~pyqtgraph.ROI.getArrayRegion`, masked by
        the shape of the ROI. Values outside the ROI shape are set to 0.

        See :meth:`~pyqtgraph.ROI.getArrayRegion` for a description of the
        arguments.
        r  Tz	col-majorr   r   )r   r  r  renderShapeMaskr}  Tr  reshape)
rX   r  r  r   r  r  slicedmappedCoordsmaskr}  s
             r$    _getArrayRegionForArbitraryShapez$ROI._getArrayRegionForArbitraryShape  sL    #&#5#5dC'9$ZLP$ZTX$Z FL ''dC'9ZLPZTXZF ==K'''T!W(=v||DQRG?TUD''T!W(=v||DQRG?TUD66D diid1g.d1gd1g.d1g||E"D=,..D= r&   c           	         | j                         |j                         urt        d      |j                  | j                  |t	        j
                  dd                  }|j                  | j                  |t	        j
                  dd                  |z
  }|j                  | j                  |t	        j
                  dd                  |z
  }t        |j                         |j                               }t        |j                         |j                               }	d|z  }
d|	z  }|j                         |
z  |j                         |
z  f|j                         |z  |j                         |z  ff}|du r| j                         j                         | j                         j                         f}|j                  | j                  || j                         j                                     }|j                         |j                         f}n/| j                  d   }|j                         |j                         f}t        |d   |
z        t        |d   |z        g}|j                  dk(  r|ddd	   }|ddd	   }|||fS )
a  
        Returns the parameters needed to use :func:`affineSlice <pyqtgraph.affineSlice>`
        (shape, vectors, origin) to extract a subset of *data* using this ROI 
        and *img* to specify the subset.
        
        If *fromBoundingRect* is True, then the ROI's bounding rectangle is used
        rather than the shape of the ROI.
        
        See :func:`getArrayRegion <pyqtgraph.ROI.getArrayRegion>` for more information.
        z6ROI and target item must be members of the same scene.r   r   r(   Tr.   r{  Nr|  )r   r   	mapToData	mapToItemr   QPointFr   r   r    rr   r!   r"   topLeftrF   absr  )rX   r  r  r   r  r  vxvylvxlvysxsyr  r}  s                 r$   r  zROI.getAffineSliceParams  s    ::<syy{*TUUt~~c6>>!Q3GHI ]]4>>#v~~a/CDEN]]4>>#v~~a/CDENBDDFBDDF#BDDFBDDF# 3Y3YDDF2Irttvby)BDDF2Irttvby+ABt#%%'--/1B1B1D1K1K1MME]]4>>#t7H7H7J7R7R7T#UVFhhj&((*-FJJv&Ehhj&((*-FU1Xb[!3uQx{#34==K'ddmG$B$KEgv%%r&   c                    |dk(  s|dk(  rt        j                  ||ft              S t        j                  ||t        j                  j
                  j                        }|j                  t        j                  j                  j                         t        j                  |      }|j                  t        j                  d             |j!                  t        j"                  d             | j%                         }|j'                         }|j)                  |j+                         |j+                         z  |j-                         |j-                         z         |j/                  |j1                                 |j3                  |       |j5                          t6        j8                  dk(  rdnd}t        j:                  |      d|f   j<                  }|j?                  t              dz  S )	zReturn an array of 0.0-1.0 into which the shape of the item has been drawn.
        
        This can be used to mask array selections.
        r   )dtypeNwlittle   .r*   ) r  emptyr  r   QImageFormatFormat_ARGB32fillr   r4   GlobalColortransparentrq  r?   r@   rA   setBrushmkBrushr}  rr   r   r!   r"   r   r  drawPathendsys	byteorderndarray_from_qimager  astype)	rX   r!   r"   imrv  r}  r  cidxr  s	            r$   r  zROI.renderShapeMask  sS   
 A:188UFO599\\%)<)<)J)JK
		%%112NN2	$ 	

2::c?#

##%	
V\\^+RYY[6==?-JK	V^^%%&	

5	MMX-q1%%b)#d(355{{5!C''r&   c                     || j                   }| j                         }|d   |d<   |d   |d<   t        |      }t        |      }||z  S )zReturn global transformation (rotation angle+translation) required to move 
        from relative state to current state. If relative state isn't specified,
        then we use the state of the ROI when mouse is pressed.r.   r   )r   r`   r   )rX   
relativeTostt1t2s        r$   getGlobalTransformzROI.getGlobalTransform  s[     **J]]_ )0
7j7*%""ur&   c                     | j                         }|d   |d<   t        |      }||z  j                         }|d   |d<   | j                  |       y )Nr.   r   )r`   r   rf   rj   )rX   r   r  s      r$   applyGlobalTransformzROI.applyGlobalTransform  sO    ]]_j7"2g  "[6
br&   T)NTT)NNFTT)NFTT)NNNN)NNNNN)NNNFN)NNNr]   )NTrY   )r   r   T)r  F)M__name__
__module____qualname____doc__r   Signalobjectre  r   r_  r
  r9  r0  r
   r2   r`   r^   rf   rj   rK   rs   r?   r.   r-   r/   rH   rJ   rI   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r	  r  r  r  r   r  r'  r-  r3  r;  r=  rA  r8  rE  rZ  r   r@  r   r   rr   ry  r  r  r  r  r  r  r  r   r&   r$   r   r   )   s   Zx ,fmmF3*V]]62$v}}V,!FMM&)Mvv.J&v.!&q!CE#$t$t#67p 
5%
D'&
(-B(-T$-Lo0Cdb"/b2b,1>t0u8u40

*MY17!&*!M>	=+1/

)n)` +D0^
^3j8"t!@+&Z(. r&   r   c                      e Zd ZdZdej
                  dz  fdej
                  dz  fdddddZ ej                  e	e	      Z
 ej                  e	      Z	 	 ddZd Zd	 Zd
 Zd Zd Zd Zd Zd Zd Zd ZddZd Zd Zd Zd Zd Zd Zy)r   a  
    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.
       )r  r   )   r   )r   r   r   r#   r   r   Nc                    g | _         || _        || _        t        j                  |      | _        t        j                  |      | _        | j
                  | _        | j
                  j                  d       | j
                  j                  d       d| _
        | j                  |   \  | _        | _        | j                          d | _        | j!                         | _        t%        j&                  | |       | j)                  t*        j,                  j.                  j0                         || _        |r3| j)                  t*        j,                  j.                  j4                         | j7                  d       y )Nr   TF)rY      )r   radiusr   r@   rA   rZ   rB   ru   setWidthsetCosmeticrL   typessidesstartAng	buildPathr  	buildMenur<   r   r2   r3   r   r4   r5   r6   	deletabler  rK   )rX   r  r   rZ   rB   rY   r  s          r$   r2   zHandle.__init__9  s   	88C=*((!T"$(JJsO!
DMNN$	V4$$VYY%:%:%C%CD"(()>)>)J)JKrr&   c                 :    | j                   j                  |       y r]   )r   r   rX   rois     r$   r   zHandle.connectROIP  s    		r&   c                 :    | j                   j                  |       y r]   )r   remover  s     r$   r   zHandle.disconnectROIT  s    		r&   c                 *   || _         |rE| j                  | j                         t        j                  j
                  j                  z         y | j                  | j                         t        j                  j
                  j                   z         y r]   )r  r3   r  r   r4   r5   r  )rX   bs     r$   setDeletablezHandle.setDeletableW  sg    (()B)B)DvyyG\G\GhGh)hi(()B)B)D		H]H]HiHiGi)ijr&   c                 :    | j                   j                  |        y r]   r/  r_   s    r$   r'  zHandle.removeClicked^  r1  r&   c                 ,   d}|j                         s|j                  t        j                  j                  j
                        rd}t        j                  j                  j
                  t        j                  j                  j                  t        j                  j                  j                  fD ]*  }| j                         |z  s|j                  |      s)d}, |r| j                  | _        n| j                  | _        | j                          y r   )r  r  r   r4   r5   r  r  r  r  r  rB   ru   rZ   ri   r  s       r$   r  zHandle.hoverEventa  s    yy{~~fii33>>?		--88&)):O:O:[:[]c]f]f]r]r]]  A --/#52??3;OE "mmDO"hhDOr&   c                 P   |j                         t        j                  j                  j                  k(  rA| j
                  r5d| _        | j                  | j                  d       |j                          y | j                         |j                         z  r|j                          |j                         t        j                  j                  j                  k(  r| j                  r| j                  |       | j                  j                  | |       y |j                          y NFTr   )r6  r   r4   r5   r  rL   rZ  startPosr7  r  r  r   r9  r   r:  r4  s     r$   r;  zHandle.mouseClickEventp  s    99;&))//;;;!DMNN4==N6IIK&&(299;6IIKyy{fii33???DNN%%b)OO  r*IIKr&   c                     t        j                         }|j                  t        dd             |j	                  t        dd      | j
                        | _        |S )Nr   r   zRemove handle)r   r"  r#  r   r(  r'  removeAction)rX   r<   s     r$   r  zHandle.buildMenu~  sF     ix01 NN9UO+LdN`N`ar&   c                     | j                   S r]   )r<   r_   s    r$   r  zHandle.getMenu  s    yyr&   c           	           j                         j                    j                         |      }t         fd j                  D              } j
                  j                  |       |j                         }|j                  t        j                  t        |j                               t        |j                                            y )Nc              3   @   K   | ]  }|j                          y wr]   )r   ).0r#   rX   s     r$   	<genexpr>z*Handle.raiseContextMenu.<locals>.<genexpr>  s     I!A//5Is   )r   r  r  allr   r  
setEnabledr  r  r   r  r  r   r    )rX   r  r<   removeAllowedr-   s   `    r$   r   zHandle.raiseContextMenu  s    zz|11$K ItyyII$$]3lln

6==SUUWs3557|<=r&   c                    |j                         t        j                  j                  j                  k7  ry |j                          |j                         rV| j                  r!| j                  D ]  }|j                           d| _        | j                  | _        | j                          n|j                         rt| j                  D ]  }|j                           d| _        | j                         | _        | j                         |j#                         z
  | _        | j&                  | _        | j                  rQ|j                         | j$                  z   }| j&                  | _        | j)                  ||j+                         d       y y r  )r6  r   r4   r5   r  r7  isFinishrL   r   r@  rZ   ru   ri   isStartr   r   r  buttonDownScenePoscursorOffsetrB   rZ  rD  )rX   r  r#   r-   s       r$   r3  zHandle.mouseDragEvent  s    99;&))//:::
		 ;;=}} ,A))+,!DM"hhDOKKMZZ\YY &##%& DM MMODM $"2G2G2I ID"mmDO==++-$"3"33C"mmDONN3uN= r&   c                     |$t         j                  j                  j                  }| j                  D ]  }|j                  | ||      r y  | j                  D ]  }|j                  | |||d        y )Nr   )r   rP  )r   r4   rG  rH  r   rE  rZ  )rX   r-   rD  r   r#   s        r$   rZ  zHandle.movePoint  sr    		22==I 	A##D#y9	
  	MAKKc9VGKL	Mr&   c                    | j                   }t        j                         | _        | j                  }dt
        j                  z  | j                  z  }t        d| j                        D ]a  }|t        |      z  }|t        |      z  }||z  }|dk(  r| j                  j                  ||       F| j                  j                  ||       c | j                  j                          y )Nr   r   )r  r   QPainterPathpathr  r  pir  ranger   r   moveTolineTocloseSubpath)rX   r.   rY  dtr   r   r    s          r$   r  zHandle.buildPath  s    {{&&(	mmY#q$**% 	'As3xAs3xA2ICAv		  A&		  A&	' 			 r&   c                     |j                  |j                  j                  d       |j                  | j                         |j                  | j                                y r   )setRenderHintsrr  rs  r?   ru   r  r}  )rX   rv  rw  rx  s       r$   ry  zHandle.paint  s>    	22D9	!	

4::< r&   c                     | j                   5| j                         }|| j                  S || _         | j                          | j                   S r]   )r  generateShaper  r   )rX   r   s     r$   r}  zHandle.shape  sF    ;;""$Ayyy DK&&({{r&   c                 ^    | j                         }| j                         j                         S r]   r}  rr   )rX   rX  s     r$   rr   zHandle.boundingRect  s"    ZZ\zz|((**r&   c                    | j                         }|| j                  | _        y |j                  t	        j
                  dd            |j                  t	        j
                  dd            z
  }t        |j                         |j                               }t        j                  |      }|j                  t	        j
                  dd            }t        j                         }|j                  |j                         |j                                |j                  |       |j                  |j                  | j                              S )Nr   r   )deviceTransformr  r  r   r   r  r   r    r   r@   r  r   r   r   rotateRadians)rX   r  vvadtidevPosr   s          r$   r  zHandle.generateShape  s    !!#:))DKFF6>>!Q'(266&..A2F+GG1335!##% !!"%q+,
VXXZ,
wwrvvdii())r&   c                 \    t        j                  |        d | _        | j                          y r]   )r   viewTransformChangedr  ri   r_   s    r$   r"  zHandle.viewTransformChanged  s     ++D1r&   )N)   r#     r+   NFr   )r  r  r  r  r  r  r  r   r  r  r9  r0  r2   r   r   r  r'  r  r;  r  r  r   r3  rZ  r  ry  r}  rr   r  r"  r   r&   r$   r   r   "  s    	 q\q\E vv.J&v.-<@E.k+>>>	M!!+*$r&   r   c                       e Zd ZdZd Zd Zy)rV   zJImplements default mouse drag behavior for ROI (not for ROI handles).
    c                    || _         d | _        d | _        t        j                  j
                  j                  | _        t        j                  j
                  j                  | _	        t        j                  j
                  j                  | _        t        j                  j
                  j                  | _        d| _        d| _        y )N      ?g)\(?)r  dragMode
startStater   r4   rG  rJ  snapModifierrH  translateModifierrK  rotateModifierShiftModifierscaleModifierrotateSpeed
scaleSpeedr  s     r$   r2   zMouseDragHandler.__init__  s    "II66FF!'!;!;!F!F$ii88DD#YY77EEr&   c                 R   | j                   }|j                         r|j                         t        j                  j
                  j                  k(  r;|j                  d       |j                         }	 || j                   z  }|j                  r|| j                  k(  rd| _        nM|j                  r|| j                  k(  rd| _        n*|j                   r|| j"                  k(  rd| _        nd | _        | j                  ||j%                          |j'                  |j)                               | _        |j-                         | _        |j1                         | j*                  z
  | _        |j5                          n(|j7                          nd | _        |j7                          |j9                         r| j                  |j;                          y |j<                  r| j                  y |j                         | j                  z  rdnd }|j'                  |j1                               }| j                  dk(  r5|| j2                  z   }|j?                  ||j1                         z
  |d       y | j                  dk(  rr| j@                  |jC                         |jE                         z
  jG                         z  }| j.                  d   |z
  }|jI                  ||j)                         |d       y | j                  dk(  rz| jJ                  |jC                         |jE                         z
  jM                          z  }|jO                  tQ        | j.                  d	         |z  |j)                         |d       y y # t        $ r" || j                  z  r|| j                  z  }Y w xY w)
NTr   r   r   F)r   r   r/   )r   r   r   r.   ))r  r  r6  r   r4   r5   r  r   rD  r*  
ValueErrorr8   r+  r(  r9   r,  r:   r.  r=  rq   buttonDownPosr  rf   r)  r-   r	  r7  r:  r  rA  rL   r   r/  r   r  r   rI   r0  r    rJ   r
   )	rX   r  r  modsr   r-   r   diffr/   s	            r$   r3  zMouseDragHandler.mouseDragEvent  s   hh::<yy{fii33>>>%||~2T....D
 ##0F0F(F$/DM]]tt/B/B'B$,DM]]tt/A/A'A$+DM$(DM==,$$&$'OOB4D4D4F$GDM&)mmoDO(+	DMM(AD%IIKIIK $		 ;;=T]]6 ||t}}4):)::toobffh'==K'4,,,FMM&3779,4MF]]h&##r{{}r7L7L7N'N&Q&Q&SSDOOG,t3ELLB,<,<,>TRWLX]]g%??8M8M8O(O'R'R'T&TTDKKdoof56=2K[K[K]dhqvKw &W " 2d/// 1 112s   6M; ;'N&%N&N)r  r  r  r  r2   r3  r   r&   r$   rV   rV     s    	6xr&   rV   c                       e Zd Zd Zy)r   c                 b   t        j                  | ||fi | | j                  ddg       | j                  ddgddg       | j                  ddgddg       | j	                  ddgddg       | j                  ddgddg       | j                  ddgddg       | j                  ddgddg       y )Nr'  r   r   )r   r2   r   r   r   r   rX   r-   r.   rv   s       r$   r2   zTestROI.__init__<  s    T3--c
+QFQF+QFQF+!!1c(S#J7S!HsCj1aVaV,aVaV,r&   Nr  r  r  r2   r   r&   r$   r   r   ;  s    -r&   r   c                       e Zd ZdZddZy)r   a  
    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()
    ============== =============================================================
    
    c                     t        j                  | ||fi | |rddg}nddg}| j                  ddg|       |r3| j                  ddg|d   dg       | j                  ddgd|d   g       y y )Nr'  r   r   )r   r2   r   )rX   r-   r.   centeredsideScalersrv   r   s          r$   r2   zRectROI.__init__X  s    T3--3ZFVFQFF+C6!9c*:;a3q	*:; r&   N)FFr  r  r  r  r2   r   r&   r$   r   r   G  s     
<r&   r   c                       e Zd ZdZd Zy)r   a  
    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()
    ============== =============================================================
    
    c                    t        |      }t        |      }||z
  }|j                         }|j                  t        dd      d      }t        |dz  t        |      z  | dz  t	        |      z        }||z   }t        j                  | |ft        ||      t        |      d| | j                  ddgddg       | j                  ddgddg       | j                  ddgddg       y )Nr   r   radians)units       @)r.   r/   r'  )
r
   rN  r/   r   r   r   r2   r   r   r   )	rX   pos1pos2r!   rv   r   lrar   s	            r$   r2   zLineROI.__init__u  s    T{T{IHHJWWU1a[	W2%(SW$ufRi#b'&9:axT4QeAuoWR[QDQ!!1c(QH5!!1c(QH5S!HsCj1r&   Nr>  r   r&   r$   r   r   d  s     2r&   r   c                       e Zd ZdZ ej
                  e      Z ej
                  e      Z ej
                  e      Z	ddZ
d Zd Zd Zd Zd Zd	 Zdd
ZddZddZy)r   a  
    Chain of rectangular ROIs connected by handles.

    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()
    ============== =============================================================
    Nc                    t         j                  j                  |        || _        || _        g | _        t        |      dk  rt        d      | j                  |d   |d   d       |dd  D ]  }| j                  |        y )Nr   z!Must start with at least 2 pointsr   r   T)	connectToscaleHandle)	r   QGraphicsObjectr2   rZ   roiArgslinesr   r   
addSegment)rX   pointsr!   rZ   rv   rv  s         r$   r2   zMultiRectROI.__init__  s    !!**40
v;??@@ 	q	VAYDI  	AOOA	r&   c                      y r]   r   )rX   rv   s     r$   ry  zMultiRectROI.paint      r&   c                 *    t        j                         S r]   )r   rh  r_   s    r$   rr   zMultiRectROI.boundingRect  s    }}r&   c                    | j                   d   j                  d   d   }| j                   dd  D ]4  }|j                  d   d   }||k(  r|j                  d||z  gddg       6 | j                  j	                  |        y )Nr   r.   r   r(   r'  )r   )rN  rF   r   r_  r   )rX   r  rF  w0s       r$   roiChangedEventzMultiRectROI.roiChangedEvent  s    JJqM'*AB 	3A#BBwGGS!B$KS	G2		3
 	""4(r&   c                 :    | j                   j                  |        y r]   )r   r   r_   s    r$   roiChangeStartedEventz"MultiRectROI.roiChangeStartedEvent  s    ##((.r&   c                 :    | j                   j                  |        y r]   rd  r_   s    r$   roiChangeFinishedEventz#MultiRectROI.roiChangeFinishedEvent  rf  r&   c                 "   | j                  | j                  d   j                         d   j                               g}| j                  D ]A  }|j	                  | j                  |j                         d   j                                      C |S )z9Return the positions of all handles in local coordinates.r   r   )r   rN  r   r   r   )rX   r-   rF  s      r$   getHandlePositionszMultiRectROI.getHandlePositions  sy      A!9!9!;A!>!G!G!IJK 	HAJJt(():)C)C)EFG	H
r&   c                    g }| j                   D ],  } |j                  ||fd|i|}||j                  |       . |j                  dk(  r|ddd   }t	        |D cg c]  }|j
                  |d       c}      }	t        d      g|d   j                  z  }
t        d|	      |
|d   <   |D cg c]  }|t        |
          }}t        j                  ||d         S c c}w c c}w )a@  
        Return the result of :meth:`~pyqtgraph.ROI.getArrayRegion` for each rect
        in the chain concatenated into a single ndarray.

        See :meth:`~pyqtgraph.ROI.getArrayRegion` for a description of the
        arguments.

        Note: ``returnMappedCoords`` is not yet supported for this ROI type.
        r   Nr{  r|  r   r   )axis)rN  r  r   r  r  r}  r  r  rd   r  concatenate)rX   arrr  r   r  rgnsrF  r  r#   msr  s              r$   r  zMultiRectROI.getArrayRegion  s      	A"!""3?$?$?C{KK		 ==K'":DD1q!''$q'"12Dk]T!W\\)Abk47&*+%)++ ~~da11 2 ,s   C!0C&c                    | | j                   d   j                         d   }t        dddgf| | j                  d| j                  }| j                   j                  |       t        |t              rH| j                   d   j                  ddgddg|	       |j                  ||j                         d
       n7| j                   d   j                  ddgddg      }|j                  ||d
       | j                   d   j                  ddgddg      }|j                  ||       |r|j                  ddgddg       d|_        |j                  j                  | j                         |j                   j                  | j"                         |j$                  j                  | j&                         | j                  j)                  |        y)z
        Add a new segment to the ROI connecting from the previous endpoint to *pos*.
        (pos is specified in the parent coordinate system of the MultiRectROI)
        Nr|  r   r   r   r1   )rY   rZ   r   r'  rl   r   )rP  F)rN  r   r   rZ   rM  r   r   r   r   rZ  r   r   r8   r_  r&  rV  r   rX  re  rZ  r   )rX   r-   rK  rJ  newRoiro   s         r$   rO  zMultiRectROI.addSegment  s    

2113A6I UQFN4TXXNN

&! i(JJrN//C1c(/SY	(:(:(<WM

233QHq#hGAQ	': JJrN//C1c(CC  !!3(S#J7#''(<(<=%%--d.H.HI&&..t/J/JK""4(r&   c                    | j                   |   }| j                   j                  |       | j                         j                  |       |j                  j                  | j                         |j                  j                  | j                         |j                  j                  | j                         | j                  j                  |        y)zRemove a segment from the ROI.N)rN  r   r   r   r_  
disconnectrV  r   rX  re  rZ  r   )rX   r   r  s      r$   removeSegmentzMultiRectROI.removeSegment  s    jj

u

$''(<(<=""--d.H.HI##..t/J/JK""4(r&   r]   )Nr  )rd  FN)r|  )r  r  r  r  r   r  r  re  r   r_  r2   ry  rr   rV  rX  rZ  r\  r  rO  ri  r   r&   r$   r   r     so     ,fmmF3*V]]62$v}}V, )/02<")J	)r&   r   c                       e Zd Zd Zy)r   c                 L    t        j                  | g|i | t        d       y )NziWarning: MultiLineROI has been renamed to MultiRectROI. (and MultiLineROI may be redefined in the future))r   r2   printrX   rv   r  s      r$   r2   zMultiLineROI.__init__  s#    d2T2T2yzr&   Nr9  r   r&   r$   r   r     s    {r&   r   c                   6    e Zd ZdZd Zd Zd Zd Zd	dZd Z	y)
r   a  
    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()
    ============== =============================================================
    
    c                     d | _         t        j                  | ||fi | | j                  j	                  | j
                         | j                          y r]   )r  r   r2   r_  r&  
_clearPath_addHandlesr8  s       r$   r2   zEllipseROI.__init__%  sB    	T3--%%doo6r&   c                 \    | j                  ddgddg       | j                  ddgddg       y )Nr(   r'  ?3OP?)r   r   r_   s    r$   rq  zEllipseROI._addHandles+  s5    c3Z#s4/1CDsCjQr&   c                     d | _         y r]   )r  r_   s    r$   rp  zEllipseROI._clearPath/  s	    	r&   c                    | j                         }|j                  t        j                  j                  j
                         |j                  | j                         |j                  |j                         |j                                t        j                  |j                         |j                         z  |j                         |j                         z  dd      }|j                  |       y r  )rr   rp  r   rq  rr  rs  r?   ru   r   r!   r"   r   rh  r   r    drawEllipseru  s        r$   ry  zEllipseROI.paint2  s    	11>>?	!		188:&MM!##%	/1335+;QqA	ar&   Nc                 4   |rt        j                  | ||||fi |\  }}nt        j                  | ||||fi |}|*|j                  |d      dk(  s|j                  |d      dk(  r|r|fS |S |j                  |d      |j                  |d      t        j                  fdf      }|d   |d   kD  r|j
                  }t        |j                        D 	cg c]  \  }}	||v r|	nd }
}}	|j                  |
      }|r||z  fS ||z  S c c}	}w )aV  
        Return the result of :meth:`~pyqtgraph.ROI.getArrayRegion` masked by the
        elliptical shape of the ROI. Regions outside the ellipse are set to 0.

        See :meth:`~pyqtgraph.ROI.getArrayRegion` for a description of the
        arguments.

        Note: ``returnMappedCoords`` is not yet supported for this ROI type.
        r   r   c                 f    t        j                  | dz   dz  z  dz
  |dz   dz  z  dz
        dk  S )Nr'  rC  r   )r  r   )r   r    ro   r  s     r$   <lambda>z+EllipseROI.getArrayRegion.<locals>.<lambda>W  s>    288aead^A5E!C%RSTVRVXYIY+[^_+_ r&   )r   r  r}  r  fromfunctionr  r   r  )rX   r`  r  r   r  r  r  r  r   nr}  ro   r  s              @@r$   r  zEllipseROI.getArrayRegion<  sM    "11$S$2D NHL N3 ##D#sD$6@:>@3;#))DG,1SYYtAw5G15L!L((
IId1gIId1g _bcefagh 7T!W66D4=cii4HISQqqDy!a'II||E":|++: Js    Dc                 ~   | j                   %t        j                         }| j                         }|j	                         }|j                         dz  }|j                         dz  }t        j                  ddt        j                  z  d      }|j                         |t        j                  |      z  z   }|j                         |t        j                  |      z  z   }|j                  |d   |d          t        dt!        |            D ]  }	|j#                  ||	   ||	           || _         | j                   S )NrC  r   r      r   )r  r   r  rr   r   r!   r"   r  linspacer  r   r   r    r   r  r  r   r  )
rX   r  brr   r1r2thetar   r    r   s
             r$   r}  zEllipseROI.shaped  s    99%%'D ""$BYY[FbBr!BKK1ruu9b1E
R"&&-//A
R"&&-//AKK!ad#1c!f% (AaD!A$'(DIyyr&   )Nr  F)
r  r  r  r  r2   rq  rp  ry  r  r}  r   r&   r$   r   r     s'    R&Pr&   r   c                       e Zd ZdZddZd Zy)r   a"  
    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()
    ============== =============================================================
    
    Nc                 j    ||t        d      |dz  |dz  f}t        j                  | ||fddi| y )Nz#Must provide either size or radius.r   r7   T)r   r   r2   )rX   r-   r.   r  rv   s        r$   r2   zCircleROI.__init__  sF    <~ EFF1HfQh'DD#tG$G$Gr&   c                 0    | j                  ddgddg       y )Nrs  r'  )r   r_   s    r$   rq  zCircleROI._addHandles  s    /1CDsCjQr&   NN)r  r  r  r  r2   rq  r   r&   r$   r   r   ~  s    HRr&   r   c                       e Zd ZdZddZddZd Zd Zd Zd Z	dd	Z
d
 ZddZddZddZd Zd Zd Zd Zd Zd Zd Zy)r   ah  
    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()
    ============== =============================================================
    
    Nc                     |ddg}|| _         g | _        t        j                  | |fdddgi| | j	                  |       y rm  )closedsegmentsr   r2   	setPoints)rX   r   r  r-   rv   s        r$   r2   zPolyLineROI.__init__  sF    ;Q%CT33aU3d3y!r&   c                 >   ||| _         | j                          |D ]  }| j                  |        | j                   rdnd}t        |t	        | j
                        dz
        D ]7  }| j                  | j
                  |   d   | j
                  |dz      d          9 y)a?  
        Set the complete sequence of points displayed by this ROI.
        
        ============= =========================================================
        **Arguments**
        points        List of (x,y) tuples specifying handle locations to set.
        closed        If bool, then this will set whether the ROI is closed 
                      (the last point is connected to the first point). If
                      None, then the closed mode is left unchanged.
        ============= =========================================================
        
        Nr|  r   r   rl   )r  clearPointsr   r  r   rE   rO  )rX   rP  r  rv  startr   s         r$   r  zPolyLineROI.setPoints  s      DK 	"Aq!	" kkquc$,,/12 	PAOODLLOF3T\\!A#5Fv5NO	Pr&   c                     t        | j                        dkD  r;| j                  | j                  d   d          t        | j                        dkD  r:yy)z2
        Remove all handles and segments.
        r   rl   N)r   rE   r   r_   s    r$   r  zPolyLineROI.clearPoints  sC     $,,!#dll1of56 $,,!#r&   c                     t         j                  |       }| j                  |d<   | j                         D cg c]  }t	        |j                                c}|d<   |S c c}w Nr  rP  )r   r`   r  r   r
   r-   rX   rF   ro   s      r$   r`   zPolyLineROI.getState  sM    T"++h37??3DEa5>Eh F    Ac                     t         j                  |       }| j                  |d<   | j                         D cg c]  }t	        |j                                c}|d<   |S c c}w r  )r   rf   r  r   rd   r-   r  s      r$   rf   zPolyLineROI.saveState  sM    d#++h37??3DEa5>Eh Fr  c                 b    t         j                  | |       | j                  |d   |d          y )NrP  r  )r  )r   rj   r  re   s     r$   rj   zPolyLineROI.setState  s(    T5!uXuX?r&   c                    t        ||f| j                  | j                  | d      }|| j                  j	                  |       n| j                  j                  ||       |j                  j                  | j                         |j                  t        j                  j                  j                         |j                  | j                         dz          |j                   D ]`  }|d   j#                  d       |d   j                  |d   j%                         t        j                  j                  j                  z         b y )NF)rE   rZ   rB   rY   r[   r   rl   T)_PolyLineSegmentrZ   rB   r  r   r   r9  r&  segmentClickedr3   r   r4   r5   r  rK   r   rE   r  r  )rX   h1h2r   segro   s         r$   rO  zPolyLineROI.addSegment  s    BxTXX&*E;=MM  %MM  ,t223##FII$9$9$D$DEdkkmAo& 	sAfI""4(fI--ai.L.L.NQWQZQZQfQfQqQq.qr	sr&   c                 t    t         j                  | |       | j                  D ]  }|j                  |        y r]   )r   r	  r  setParentHover)rX   r  r   s      r$   r	  zPolyLineROI.setMouseHover  s3    $& 	$AU#	$r&   c                     t         j                  | ||      }|j                  j                  | j                         | j                  d       |S )Nr   Tr   )r   r   r0  r&  r   r   r   s       r$   r   zPolyLineROI.addHandle  sF    MM$EM2	$$T%6%67&r&   c                 R   | |j                  |j                               }n|t        d      |j                  d   d   }| j                  j                  |      }| j                  || j                  |            }| j                  |||dz          |j                  ||       y )Nz,Either an event or a position must be given.r   rl   r   )
rq   r-   r   rE   r  r   r   r   rO  r   )rX   segmentr  r-   r  r   h3s          r$   r  zPolyLineROI.segmentClicked  s    >%%bffh/C[JKK__Q'MM(4+=+=b+ABBac*b"%r&   c                    t         j                  | |       |j                  j                  | j                         |sy |j                  d d  }t        |      dk(  r| j                  |d          njt        |      dkD  r\|d   j                  D cg c]  }|d   	 }}|j                  |       |d   j                  ||d          | j                  |d          | j                  d       y c c}w )Nr   r   rl   Tr   )r   r   r0  rh  r   r   ri  rE   r  r   r   )rX   r   updateSegmentsr  ro   rE   s         r$   r   zPolyLineROI.removeHandle
  s    v&!!,,T->->?;;q>x=Ax{+]Q*21+*=*=>Qqy>G>NN6"QK%%fgaj9x{+&	 ?s   C.c                    |j                   d d  D ]  }|j                  |d           | j                  j                  |       |j                  j                  | j                         | j                         j                  |       y r   )	rE   r   r  r  r9  rh  r  r   r   )rX   r  r   s      r$   ri  zPolyLineROI.removeSegment  si    kk!n 	-FVF^,	-S!!!$"5"56

$r&   c                 z    | j                   rt        | j                        dkD  S t        | j                        dkD  S )Nr  r   )r  r   rE   r   s     r$   r   zPolyLineROI.checkRemoveHandle"  s1    ;;t||$q((t||$q((r&   c                      y r]   r   )rX   rv  rv   s      r$   ry  zPolyLineROI.paint)  rR  r&   c                 >    | j                         j                         S r]   r  r_   s    r$   rr   zPolyLineROI.boundingRect,      zz|((**r&   c                    t        j                         }t        | j                        dk(  r|S |j	                  | j                  d   d   j                                t        t        | j                              D ]1  }|j                  | j                  |   d   j                                3 |j                  | j                  d   d   j                                |S )Nr   rl   )r   r  r   rE   r  r-   r  r  )rX   rv  r   s      r$   r}  zPolyLineROI.shape/  s     t||!H	a(,,./s4<<() 	4AHHT\\!_V,0023	4	a(,,./r&   c                 &     | j                   |i |S r]   r  rm  s      r$   r  zPolyLineROI.getArrayRegion9      4t44dCdCCr&   c                 |    t        j                  | g|i | | j                  D ]  } |j                  |i |  y r]   )r   r?   r  )rX   rv   r  r  s       r$   r?   zPolyLineROI.setPen<  s>    

4'$'$'== 	&CCJJ%%	&r&   )FNr]   r  r  )r  r  r  r  r2   r  r  r`   rf   rj   rO  r	  r   r  r   ri  r   ry  rr   r}  r  r?   r   r&   r$   r   r     se    $	"P27@s$
&'"%)+D&r&   r   c                   Z    e Zd ZdZddZed        Zd Zd Zd Z	d Z
d	 Zd
 Zd ZddZy)r   a  
    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.
    \**args        All extra keyword arguments are passed to ROI()
    ============== =============================================================
    Nc                     |ddg}t        j                  | |ddgfi | t        |      dkD  rt        d      t	        |      D ]  \  }}| j                  |||           y )Nr   r   r   zXLineSegmentROI must be defined by exactly 2 positions. For more points, use PolyLineROI.re  )r   r2   r   r   r   r   )rX   r   r-   rE   rv   r   rv  s          r$   r2   zLineSegmentROI.__init__R  sp    ;Q%CT31..y>Avwwi( 	3DAqqwqz2	3r&   c                 F    | j                   D cg c]  }|d   	 c}S c c}w r   r   r   s     r$   	endpointszLineSegmentROI.endpoints]  s      $(<<0a&	000r   c                 b    | j                   D cg c]  }|d   j                          c}S c c}w r   )rE   r-   )rX   rv  s     r$   
listPointszLineSegmentROI.listPointsb  s$    )-6A&	666s   ,c                     t         j                  |       }| j                         D cg c]  }t        |j	                                c}|d<   |S c c}w NrP  )r   r`   r   r
   r-   r  s      r$   r`   zLineSegmentROI.getStatee  s@    T"37??3DEa5>Eh F    Ac                     t         j                  |       }| j                         D cg c]  }t        |j	                                c}|d<   |S c c}w r  )r   rf   r   rd   r-   r  s      r$   rf   zLineSegmentROI.saveStatej  s@    d#37??3DEa5>Eh Fr  c                 `   t         j                  | |       |d   d   d   |d   d   z   |d   d   d   |d   d   z   g}|d   d   d   |d   d   z   |d   d   d   |d   d   z   g}| j                  | j                         d   |d       | j                  | j                         d   |       y )NrP  r   r-   r   Fr   )r   rj   rZ  r   )rX   rF   rR  p2s       r$   rj   zLineSegmentROI.setStateo  s    T5!Hoa #E%LO3U8_Q5G5J5QV<XY?5Z[Hoa #E%LO3U8_Q5G5J5QV<XY?5Z[t(+R>t(+R0r&   c                 8   |j                  t        j                  j                  j                         |j                  | j                         | j                  d   j                         }| j                  d   j                         }|j                  ||       y )Nr   r   )
rp  r   rq  rr  rs  r?   ru   r  r-   drawLine)rX   rv  rv   r  r  s        r$   ry  zLineSegmentROI.paintv  sj    	11>>?	!^^A""$^^A""$	

2rr&   c                 >    | j                         j                         S r]   r  r_   s    r$   rr   zLineSegmentROI.boundingRect}  r  r&   c                    t        j                         }| j                  d   j                         }| j                  d   j                         }||z
  }|j	                         dk(  r|S | j                  |      d   }||S |dz  }|j                  ||z          |j                  ||z          |j                  ||z
         |j                  ||z
         |j                  ||z          |S )Nr   r   r  )r   r  r  r-   rN  pixelVectorsr  r  )rX   rv  r  r  dhpxvs         r$   r}  zLineSegmentROI.shape  s     ^^A""$^^A""$U99;!H#A&;Hq	C	C	C	C	Cr&   c           
      \   | j                   D cg c]"  }| j                  ||j                               $ }}t        |d   |d   z
        }	t        |d         }
t	        j
                  |ft        |	j                               ft        |	j                               g|
|||d|}|S c c}w )aT  
        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 :meth:`~pyqtgraph.ROI.getArrayRegion` for a description of the
        arguments.
        r   r   )r}  r  r  r   orderr  )	r  r  r-   r
   r@   r  r  rN  norm)rX   r  r  r   r  r  r  ro   imgPtsr   or  s               r$   r  zLineSegmentROI.getArrayRegion  s     9=G1$..aeeg.GG&)fQi'(&)nnT  c#ahhj/);eAFFHoEV_`gksx  HZ  c  ^b  c
 Hs   'B))r  Nr  )r  r   F)r  r  r  r  r2   propertyr  r  r`   rf   rj   ry  rr   r}  r  r   r&   r$   r   r   C  sH    	3 1 17

1+,r&   r   c                   $    e Zd Zd Zd Zd Zd Zy)r  c                 D    d| _         t        j                  | g|i | y r?  )_parentHoveringr   r2   rm  s      r$   r2   z_PolyLineSegment.__init__  s"    $4t4t4r&   c                 R    | j                   |k7  r|| _         | j                          y y r]   )r  r  r  s     r$   r  z_PolyLineSegment.setParentHover  s)    5(#(D ""$ )r&   c                 b    | j                   s| j                  r| j                  S | j                  S r]   )r>   r  rB   rZ   r_   s    r$   r  z_PolyLineSegment._makePen  s&    !5!5== 88Or&   c                     | j                         j                  r3|j                  t        j                  j
                  j                         t        j                  | |      S r]   )	
parentItemr8   r  r   r4   r5   r  r   r  r4  s     r$   r  z_PolyLineSegment.hoverEvent  sC     ??))NN69900;;<((r22r&   N)r  r  r  r2   r  r  r  r   r&   r$   r  r    s    5%3r&   r  c                   0    e Zd ZdZddZd Zd Zd Zd Zy)	r   zzA crosshair ROI whose position is at the center of the crosshairs. By default, it is scalable, rotatable and translatable.Nc                     |ddg}|ddg}d | _         t        j                  | ||fddi| | j                  j	                  | j
                         | j                  t        dd      t        dd             y )Nr   r   r7   T)r  r   r2   r_  r&  
invalidater   r
   )rX   r-   r.   r   s       r$   r2   zCrosshairROI.__init__  ss    <AD;Q%CT3A4A5A%%doo6!!%1+uQ{;r&   c                 2    d | _         | j                          y r]   )r  r   r_   s    r$   r  zCrosshairROI.invalidate  s    ""$r&   c                 >    | j                         j                         S r]   r  r_   s    r$   rr   zCrosshairROI.boundingRect  r  r&   c                    | j                   | j                         d   d   }t        j                         }|j	                  t        d|              |j                  t        d|             |j	                  t        | d             |j                  t        |d             | j                  |      }t        j                         }|j                  d       |j                  |      }| j                  |      | _         | j                   S )Nr.   r   r   r0   )r  r`   r   r  r  r
   r  mapToDeviceQPainterPathStrokerr  createStrokemapFromDevice)rX   r  rv  strokeroutlines        r$   r}  zCrosshairROI.shape  s    ;;]]_V,Q/F""$AHHU1vg&'HHU1f%&HHUF7A&'HHU61%&  #A//1GR **1-G,,W5DK{{r&   c                 h   | j                         d   d   }|j                  t        j                  j                  j
                         |j                  | j                         |j                  t        d|       t        d|             |j                  t        | d      t        |d             y )Nr.   r   r   )
r`   rp  r   rq  rr  rs  r?   ru   r  r
   )rX   rv  rv   r  s       r$   ry  zCrosshairROI.paint  s    (+	11>>?	!	

5VG$eAv&67	

5&!$eFA&67r&   r  )	r  r  r  r  r2   r  rr   r}  ry  r   r&   r$   r   r     s!     E	<%+ 8r&   r   c                       e Zd Zd Zd Zy)RulerROIc                    t        j                  | |g|  | j                  d   d   j                         }| j                  d   d   j                         }|j	                         j                  |      }|j	                         j                  |      }t        |      t        |      z
  }|j                         }|j                  t        dd            }	||z
  }
t        |
j                         |
j                                }d||z   z  |dz  |j                         z  z   }|j                          t        j                  |d      d|	z  z   }|j                  t        j                   |j                         d	z
  |j                         d	z
  d
d
      t        j"                  j$                  j&                  |       y )Nr   rl   r   r'  (   m)suffixz

%0.1f deg2   d   )r   ry  rE   r-   r  r   r
   rN  r/   r    r   resetTransformr@   siFormatdrawTextr   rh  r4   AlignmentFlagAlignCenter)rX   rv  rv   r  r  rR  r  vecrN  r/   pvecpvecTr-   txts                 r$   ry  zRulerROI.paint  sX   T1,t,\\!_V$((*\\!_V$((*[[]r"[[]r"Bi%)#		%1+&Bwdffh	*R"Wo
U\\^ ;;	kk&-0EE	

6==SUUWRZcBFIID[D[DgDgilmr&   c                     t         j                  |       }| j                  t        ddg            }||S d|z  }|j	                  dddd      S )Nr   r   r  i)r   rr   pixelLengthr
   rj  )rX   r#   pxlpxws       r$   rr   zRulerROI.boundingRect	  sR    ''-uaV}-;H3hzz#sB++r&   N)r  r  r  ry  rr   r   r&   r$   r  r    s    n(,r&   r  c                   (    e Zd ZdZd Zd Zd Zd Zy)r   a  
    Equilateral triangle ROI subclass with one scale handle and one rotation handle.
    Arguments
    pos            (length-2 sequence) The position of the ROI's origin.
    size           (float) The length of an edge of the triangle.
    \**args        All extra keyword arguments are passed to ROI()
    ============== =============================================================
    c                    t        j                  | |||gfddi| t        j                  dt        j                  dz  dz  d      }t        j
                  t        j                  |      t        j                  |      f      j                  dz   dz  }t        j                         | _        |D ]-  }| j                  j                  t        j                  |        / | j                  |d   ddg       | j!                  |d	   ddg       y )
Nr7   Tr   r  r  r(   rC  r'  r   )r   r2   r  r~  r  arrayr   r   r  r   	QPolygonFpolyr   r   r  r   r   )rX   r-   r.   rv   angles	verticiesr   s          r$   r2   zTriangleROI.__init__	  s    T3tH4H4HQ	Aq1XXrvvf~rvvf~>?AACG3N	OO%	 	2BIIV^^R01	2Yq\C:6IaL3*5r&   c                 R   | j                         }|j                  t        j                  j                  j
                         |j                  |j                         |j                                |j                  | j                         |j                  | j                         y r]   )rr   rp  r   rq  rr  rs  r   r!   r"   r?   ru   drawPolygonr  )rX   rv  rv   r#   s       r$   ry  zTriangleROI.paint$	  sf    	11>>?		188:&	!	dii r&   c                 X   t        j                         | _        | j                         }t        j                         }|j                  |j                         |j                                | j                  j                  | j                         |j                  | j                        S r]   )r   r  r  rr   r   r   r!   r"   
addPolygonr  r   )rX   r#   r   s      r$   r}  zTriangleROI.shape+	  sq    &&(			188:&		TYY'uuTYYr&   c                 &     | j                   |i |S r]   r  rm  s      r$   r  zTriangleROI.getArrayRegion4	  r  r&   N)r  r  r  r  r2   ry  r}  r  r   r&   r$   r   r   	  s    6! Dr&   r   )+r  r  mathr   r   r   r   r   numpyr   r	   r@   r
   r4   r   r   r   r   r   r   QCoreApplicationr   __all__r%   r   r   r  rV   r   r   r   rL  r   r   r   r   r   r   r  r   r  r   r   r&   r$   <module>r     s2    0 0    ) ) ' * *##--	Iv. vr'O^ OdDxv DxN	-c 	-<c <:2c 2@K)9,, K)\{< {b bLR
 R0i&# i&ZdS dN3~ 34+83 +8\,~ ,<%D# %Dr&   