B
    ]t\                 @   s  d Z ddlZddlZddlmZ ddlm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mZ ddlmZ ddlmZ ddlmZ dd	lmZ dd
l
mZ dZ dd ZdGddZ!dHddZ"G dd de	j#Z$G dd de$Z%G dd de%Z&G dd de%Z'G dd de$Z(G dd de$Z)G d d! d!e$Z*G d"d# d#e$Z+G d$d% d%e$Z,G d&d' d'e,Z-G d(d) d)e$Z.G d*d+ d+e	j#eZ/G d,d- d-e0Z1G d.d/ d/e1Z2G d0d1 d1e1Z3e4d2krddl5m6Z7 e78d3Z9e9:  e7;d4Z<e= Z>e?d5@d6d6d7 ZAe.eAfd8ddd9e>ZBe<CeB eBDd: e.eAfd8ddd9e>ZEe/eEd;d<d=d>d?d@e=dAdBdCde=dDdEdF
ZFe<CeF e7G  e7H  dS )Ia  
The OffsetBox is a simple container artist. The child artist are meant
to be drawn at a relative position to its parent.  The [VH]Packer,
DrawingArea and TextArea are derived from the OffsetBox.

The [VH]Packer automatically adjust the relative postisions of their
children, which should be instances of the OffsetBox. This is used to
align similar artists together, e.g., in legend.

The DrawingArea can contain any Artist as a child. The
DrawingArea has a fixed width and height. The position of children
relative to the parent is fixed.  The TextArea is contains a single
Text instance. The width and height of the TextArea instance is the
width and height of the its child text.
    N)BboxBboxBaseTransformedBbox)FontProperties)FancyBboxPatchFancyArrowPatch)rcParams)	docstring)	BboxImage)bbox_artist)_AnnotationBaseFc              O   s   t rt| | d S )N)DEBUGmbbox_artist)argskwargs r   3lib/python3.7/site-packages/matplotlib/offsetbox.pyr   +   s    r   fixedc       	         s6  t |  \}}|dkrZtdg fdd|D  }|dd }|dkrR|d   }||fS |dkr|dkrnd}t|dkr|t| t|d   nd tdg fd	d|D  }|dd }||fS |d
kr$t|}|dkr|  t| }n|t| |  |  tt| }||fS td|f dS )a  
    Geiven a list of (width, xdescent) of each boxes, calculate the
    total width and the x-offset positions of each items according to
    *mode*. xdescent is analogous to the usual descent, but along the
    x-direction. xdescent values are currently ignored.

    *wd_list* : list of (width, xdescent) of boxes to be packed.
    *sep* : spacing between boxes
    *total* : Intended total length. None if not used.
    *mode* : packing mode. 'fixed', 'expand', or 'equal'.
    r   r   c                s   g | ]}|  qS r   r   ).0w)sepr   r   
<listcomp>E   s    z'_get_packed_offsets.<locals>.<listcomp>Nexpand   c                s   g | ]}|  qS r   r   )r   r   )r   r   r   r   T   s    ZequalzUnknown mode : %s)zipnpZcumsumlensummaxarange
ValueError)	wd_listZtotalr   modeZw_listZd_listZoffsets_offsetsZmaxhr   )r   r   _get_packed_offsets4   s0    
r%   baselinec                s    dkrt dd | D  |dkr^t dd | D }t dd | D }||  dd | D }nj|d	krzd
}dd | D }nN|dkrd
} fdd| D }n.|dkrd
} fdd| D }ntd|f  ||fS )a)  
    Given a list of (height, descent) of each boxes, align the boxes
    with *align* and calculate the y-offsets of each boxes.
    total width and the offset positions of each items according to
    *mode*. xdescent is analogous to the usual descent, but along the
    x-direction. xdescent values are currently ignored.

    *hd_list* : list of (width, xdescent) of boxes to be aligned.
    *sep* : spacing between boxes
    *height* : Intended total length. None if not used.
    *align* : align mode. 'baseline', 'top', 'bottom', or 'center'.
    Nc             s   s   | ]\}}|V  qd S )Nr   )r   hdr   r   r   	<genexpr>t   s    z'_get_aligned_offsets.<locals>.<genexpr>r&   c             s   s   | ]\}}|| V  qd S )Nr   )r   r'   r(   r   r   r   r)   w   s    c             s   s   | ]\}}|V  qd S )Nr   )r   r'   r(   r   r   r   r)   x   s    c             S   s   g | ]\}}d qS )g        r   )r   r'   r(   r   r   r   r   z   s    z(_get_aligned_offsets.<locals>.<listcomp>)lefttopg        c             S   s   g | ]\}}|qS r   r   )r   r'   r(   r   r   r   r   }   s    )rightZbottomc                s   g | ]\}} | | qS r   r   )r   r'   r(   )heightr   r   r      s    centerc                s    g | ]\}} | d  | qS )g      ?r   )r   r'   r(   )r-   r   r   r      s    zUnknown Align mode : %s)r   r!   )hd_listr-   alignheight_descentZdescentr$   r   )r-   r   _get_aligned_offsetse   s$    r2   c                   s   e Zd ZdZ fddZdd Zejjj	dd Zdd	 Z
d
d Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Z  ZS )	OffsetBoxz
    The OffsetBox is a simple container artist. The child artist are meant
    to be drawn at a relative position to its parent.
    c                s(   t  j|| | d g | _d| _d S )NF)r   r   )super__init__Zset_clip_on	_children_offset)selfr   r   )	__class__r   r   r5      s    
zOffsetBox.__init__c             C   s.   t j| | x|  D ]}|| qW dS )z^
        Set the figure

        accepts a class:`~matplotlib.figure.Figure` instance
        N)martistArtist
set_figureget_children)r8   figcr   r   r   r<      s    zOffsetBox.set_figurec             C   s4   t jj| | x|  D ]}|d k	r||_qW d S )N)r:   r;   axesfsetr=   )r8   axr?   r   r   r   r@      s    zOffsetBox.axesc             C   s4   x*|   D ]}||\}}|r
||fS q
W di fS )NF)r=   contains)r8   
mouseeventr?   abr   r   r   rC      s
    zOffsetBox.containsc             C   s   || _ d| _dS )a>  
        Set the offset.

        Parameters
        ----------
        xy : (float, float) or callable
            The (x,y) coordinates of the offset in display units.
            A callable must have the signature::

                def offset(width, height, xdescent, ydescent, renderer) -> (float, float)
        TN)r7   stale)r8   xyr   r   r   
set_offset   s    zOffsetBox.set_offsetc             C   s"   t | jr| |||||S | jS )zC
        Get the offset

        accepts extent of the box
        )callabler7   )r8   widthr-   xdescentydescentrendererr   r   r   
get_offset   s    zOffsetBox.get_offsetc             C   s   || _ d| _dS )z6
        Set the width

        accepts float
        TN)rK   rG   )r8   rK   r   r   r   	set_width   s    zOffsetBox.set_widthc             C   s   || _ d| _dS )z7
        Set the height

        accepts float
        TN)r-   rG   )r8   r-   r   r   r   
set_height   s    zOffsetBox.set_heightc             C   s   dd | j D S )z?
        Return a list of visible artists it contains.
        c             S   s   g | ]}|  r|qS r   )get_visible)r   r?   r   r   r   r      s    z2OffsetBox.get_visible_children.<locals>.<listcomp>)r6   )r8   r   r   r   get_visible_children   s    zOffsetBox.get_visible_childrenc             C   s   | j S )z7
        Return a list of artists it contains.
        )r6   )r8   r   r   r   r=      s    zOffsetBox.get_childrenc             C   s   t dd S )N )	Exception)r8   rN   r   r   r   get_extent_offsets   s    zOffsetBox.get_extent_offsetsc             C   s    |  |\}}}}}||||fS )z@
        Return with, height, xdescent, ydescent of box
        )rV   )r8   rN   r   r'   xdydr$   r   r   r   
get_extent   s    zOffsetBox.get_extentc       	      C   sD   |  |\}}}}}| |||||\}}tj|| || ||S )z8
        get the bounding box in display space.
        )rV   rO   mtransformsr   from_bounds)	r8   rN   r   r'   rW   rX   r$   pxpyr   r   r   get_window_extent   s    zOffsetBox.get_window_extentc             C   s   |  |\}}}}}| |||||\}}x>t|  |D ],\}	\}
}|	||
 || f |	| q:W t| |dtddd d| _dS )zm
        Update the location of children if necessary and draw them
        to the given *renderer*.
        Fg        )pad)fillpropsN)	rV   rO   r   rS   rI   drawr   dictrG   )r8   rN   rK   r-   rL   rM   r$   r\   r]   r?   oxoyr   r   r   rb      s    zOffsetBox.draw)__name__
__module____qualname____doc__r5   r<   r:   r;   r@   setterrC   rI   rO   rP   rQ   rS   r=   rV   rY   r^   rb   __classcell__r   r   )r9   r   r3      s   

		r3   c                   s   e Zd Zd fdd	Z  ZS )
PackerBaseNc                s8   t    || _|| _|| _|| _|| _|| _|| _dS )a  
        Parameters
        ----------
        pad : float, optional
            Boundary pad.

        sep : float, optional
            Spacing between items.

        width : float, optional

        height : float, optional
           Width and height of the container box, calculated if
           `None`.

        align : str, optional
            Alignment of boxes. Can be one of ``top``, ``bottom``,
            ``left``, ``right``, ``center`` and ``baseline``

        mode : str, optional
            Packing mode.

        Notes
        -----
        *pad* and *sep* need to given in points and will be scale with
        the renderer dpi, while *width* and *height* need to be in
        pixels.
        N)	r4   r5   r-   rK   r   r_   r#   r0   r6   )r8   r_   r   rK   r-   r0   r#   children)r9   r   r   r5     s    
zPackerBase.__init__)NNNNNNN)rf   rg   rh   r5   rk   r   r   )r9   r   rl     s     rl   c                   s*   e Zd ZdZd	 fdd	Zdd Z  ZS )
VPackerz
    The VPacker has its children packed vertically. It automatically
    adjust the relative positions of children in the drawing time.
    Nr&   r   c          	      s   t  ||||||| dS )ap  
        Parameters
        ----------
        pad : float, optional
            Boundary pad.

        sep : float, optional
            Spacing between items.

        width : float, optional

        height : float, optional

            width and height of the container box, calculated if
            `None`.

        align : str, optional
            Alignment of boxes.

        mode : str, optional
            Packing mode.

        Notes
        -----
        *pad* and *sep* need to given in points and will be scale with
        the renderer dpi, while *width* and *height* need to be in
        pixels.
        N)r4   r5   )r8   r_   r   rK   r-   r0   r#   rm   )r9   r   r   r5   B  s    zVPacker.__init__c                s$    d}| j| }| j| }| jdk	rZx0|  D ]$}t|tr2|jdkr2|| j q2W  fdd|  D }dd |D }dd |D }t	|| j| j
\}}	}
dd |D }t|| j|| j\}}|d	d |D  }||d
  }|| }|| }|d|  |d|  |	| || tt|
|fS )zN
        update offset of childrens and return the extents of the box
        g      ?Nr   c                s   g | ]}|  qS r   )rY   )r   r?   )rN   r   r   r   q  s   z.VPacker.get_extent_offsets.<locals>.<listcomp>c             S   s$   g | ]\}}}}||||| fqS r   r   )r   r   r'   rW   rX   r   r   r   r   s  s    c             S   s   g | ]\}}}}||fqS r   r   )r   r   r'   rW   rX   r   r   r   r   u  s    c             S   s   g | ]\}}}}||fqS r   r   )r   r   r'   rW   rX   r   r   r   r   z  s    c             S   s   g | ]\}}}}|qS r   r   )r   r   r'   rW   rX   r   r   r   r   ~  s    r      )points_to_pixelsr_   r   rK   rS   
isinstancerl   r#   rP   r2   r0   r%   r-   listr   )r8   rN   dpicorr_   r   r?   whd_listr"   rK   rL   xoffsets	pack_listr-   Z	yoffsets_yoffsetsrM   r   )rN   r   rV   c  s0    




zVPacker.get_extent_offsets)NNNNr&   r   N)rf   rg   rh   ri   r5   rV   rk   r   r   )r9   r   rn   =  s
     rn   c                   s*   e Zd ZdZd	 fdd	Zdd Z  ZS )
HPackerz
    The HPacker has its children packed horizontally. It automatically
    adjusts the relative positions of children at draw time.
    Nr&   r   c          	      s   t  ||||||| dS )aW  
        Parameters
        ----------
        pad : float, optional
            Boundary pad.

        sep : float, optional
            Spacing between items.

        width : float, optional

        height : float, optional
           Width and height of the container box, calculated if
           `None`.

        align : str
           Alignment of boxes.

        mode : str
           Packing mode.

        Notes
        -----
        *pad* and *sep* need to given in points and will be scale with
        the renderer dpi, while *width* and *height* need to be in
        pixels.
        N)r4   r5   )r8   r_   r   rK   r-   r0   r#   rm   )r9   r   r   r5     s    zHPacker.__init__c                s2    d}| j| }| j| } fdd|  D }|sNd| d| ||g fS | jdkrtdd |D }tdd |D }|| }n| jd|  }d	d |D }	t|	| j| j\}}}
d
d |D }t|| j	|| j
\}}|dd |D  }|d d }|| }|d|  |d|  || || tt||
fS )zM
        update offset of children and return the extents of the box
        g      ?c                s   g | ]}|  qS r   )rY   )r   r?   )rN   r   r   r     s   z.HPacker.get_extent_offsets.<locals>.<listcomp>ro   Nc             s   s   | ]\}}}}|| V  qd S )Nr   )r   r   r'   rW   rX   r   r   r   r)     s    z-HPacker.get_extent_offsets.<locals>.<genexpr>c             s   s   | ]\}}}}|V  qd S )Nr   )r   r   r'   rW   rX   r   r   r   r)     s    c             S   s   g | ]\}}}}||fqS r   r   )r   r   r'   rW   rX   r   r   r   r     s    c             S   s   g | ]\}}}}||fqS r   r   )r   r   r'   rW   rX   r   r   r   r     s    c             S   s   g | ]\}}}}|qS r   r   )r   r   r'   rW   rX   r   r   r   r     s    r   )rp   r_   r   rS   r-   r   r2   r0   r%   rK   r#   rr   r   )r8   rN   rs   r_   r   rt   r1   rM   r-   r/   rw   rv   rK   Z	xoffsets_ru   rL   r   )rN   r   rV     s2    





zHPacker.get_extent_offsets)NNNNr&   r   N)rf   rg   rh   ri   r5   rV   rk   r   r   )r9   r   rx     s
     rx   c                   s@   e Zd Zd fdd	Zdd Zdd Zdd	d
Zdd Z  ZS )	PaddedBoxNFc          	      s^   t    || _|g| _tdddddddd| _| jjdd	d
 |dk	rT| j| || _dS )z
        *pad* : boundary pad

        .. note::
          *pad* need to given in points and will be
          scale with the renderer dpi, while *width* and *height*
          need to be in pixels.
        )g        g        g      ?r   kr   T)rH   rK   r-   	facecolor	edgecolormutation_scalesnapsquarer   )r_   N)	r4   r5   r_   r6   r   patchset_boxstyleupdate
_drawFrame)r8   childr_   
draw_frameZpatch_attrs)r9   r   r   r5     s    


zPaddedBox.__init__c             C   sT   | d}| j| }| jd |\}}}}|d|  |d|  || || dgfS )zN
        update offset of childrens and return the extents of the box
        g      ?r   ro   )r   r   )rp   r_   r6   rY   )r8   rN   rs   r_   r   r'   rW   rX   r   r   r   rV     s    

zPaddedBox.get_extent_offsetsc             C   s   |  |\}}}}}| |||||\}}x4t|  |D ]"\}	\}
}|	||
 || f q:W | | x|  D ]}	|	| qtW d| _dS )zm
        Update the location of children if necessary and draw them
        to the given *renderer*.
        FN)rV   rO   r   rS   rI   r   rb   rG   )r8   rN   rK   r-   rL   rM   r$   r\   r]   r?   rd   re   r   r   r   rb     s    
zPaddedBox.drawc             C   s4   | j |j|j|j|j |r*| j | d| _d S )NT)r   
set_boundsx0y0rK   r-   set_mutation_scalerG   )r8   bboxfontsizer   r   r   update_frame  s
    zPaddedBox.update_framec             C   s*   |  |}| | | jr&| j| d S )N)r^   r   r   r   rb   )r8   rN   r   r   r   r   r   !  s    

zPaddedBox.draw_frame)NFN)N)	rf   rg   rh   r5   rV   rb   r   r   rk   r   r   )r9   r   ry     s
   
ry   c                   s|   e Zd ZdZd fdd	Zedd Zejdd Zd	d
 Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Z  ZS )DrawingAreaz
    The DrawingArea can contain any Artist as a child. The DrawingArea
    has a fixed width and height. The position of children relative to
    the parent is fixed. The children can be clipped at the
    boundaries of the parent.
            Fc                sX   t    || _|| _|| _|| _|| _t | _	| j	
  | j	dd t | _dS )z
        *width*, *height* : width and height of the container box.
        *xdescent*, *ydescent* : descent of the box in x- and y-direction.
        *clip* : Whether to clip the children
        r   N)r4   r5   rK   r-   rL   rM   _clip_childrenrZ   Affine2Doffset_transformclear	translatedpi_transform)r8   rK   r-   rL   rM   Zclip)r9   r   r   r5   2  s    


zDrawingArea.__init__c             C   s   | j S )zl
        If the children of this DrawingArea should be clipped
        by DrawingArea bounding box.
        )r   )r8   r   r   r   clip_childrenH  s    zDrawingArea.clip_childrenc             C   s   t || _d| _d S )NT)boolr   rG   )r8   valr   r   r   r   P  s    
c             C   s   | j | j S )zf
        Return the :class:`~matplotlib.transforms.Transform` applied
        to the children
        )r   r   )r8   r   r   r   get_transformU  s    zDrawingArea.get_transformc             C   s   dS )z+
        set_transform is ignored.
        Nr   )r8   tr   r   r   set_transform\  s    zDrawingArea.set_transformc             C   s0   || _ | j  | j|d |d  d| _dS )z
        Set the offset of the container.

        Parameters
        ----------
        xy : (float, float)
            The (x,y) coordinates of the offset in display units.
        r   r   TN)r7   r   r   r   rG   )r8   rH   r   r   r   rI   b  s    	
zDrawingArea.set_offsetc             C   s   | j S )z1
        return offset of the container.
        )r7   )r8   r   r   r   rO   q  s    zDrawingArea.get_offsetc             C   s8   |  |\}}}}|  \}}tj|| || ||S )z8
        get the bounding box in display space.
        )rY   rO   rZ   r   r[   )r8   rN   r   r'   rW   rX   rd   re   r   r   r   r^   w  s    zDrawingArea.get_window_extentc             C   s.   | d}| j| | j| | j| | j| fS )z@
        Return with, height, xdescent, ydescent of box
        g      ?)rp   rK   r-   rL   rM   )r8   rN   dpi_corr   r   r   rY     s    
zDrawingArea.get_extentc             C   sP   | j | | s"||   | jdk	r4| j|_| j}|dk	rL|| dS )z?Add any :class:`~matplotlib.artist.Artist` to the container boxN)r6   appendZis_transform_setr   r   r@   figurer<   )r8   rE   r>   r   r   r   
add_artist  s    
zDrawingArea.add_artistc          	   C   s   | d}| j  | j|| ttddgd| jg| j	| jg| j	dgg| 
 }x4| jD ]*}| jr|js|js|| || q`W t| |dtddd d| _dS )z#
        Draw the children
        g      ?r   Fg        )r_   )r`   ra   N)rp   r   r   ZscalerZ   ZTransformedPathmpathZPathr-   rK   r   r6   r   ZclipboxZ	_clippathZset_clip_pathrb   r   rc   rG   )r8   rN   r   Ztpathr?   r   r   r   rb     s    




zDrawingArea.draw)r   r   F)rf   rg   rh   ri   r5   propertyr   rj   r   r   rI   rO   r^   rY   r   rb   rk   r   r   )r9   r   r   *  s    		r   c               @   sz   e Zd ZdZdddZdd Zdd	 Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd ZdS )TextAreaz
    The TextArea is contains a single Text instance. The text is
    placed at (0,0) with baseline+left alignment. The width and height
    of the TextArea instance is the width and height of the its child
    text.
    NTc             C   s   |dkri }d|krd|d< t jdd|f|| _t|  | jg| _t | _| j	  | j
dd t | _| j| j| j  || _|| _dS )a  
        Parameters
        ----------
        s : str
            a string to be displayed.

        textprops : `~matplotlib.font_manager.FontProperties`, optional

        multilinebaseline : bool, optional
            If `True`, baseline for multiline text is adjusted so that
            it is (approximatedly) center-aligned with singleline
            text.

        minimumdescent : bool, optional
            If `True`, the box has a minimum descent of "p".
        Nvar&   r   )mtextZText_textr3   r5   r6   rZ   r   r   r   r   _baseline_transformr   _multilinebaseline_minimumdescent)r8   s	textpropsZmultilinebaselineminimumdescentr   r   r   r5     s    






zTextArea.__init__c             C   s   | j | d| _dS )z&Set the text of this area as a string.TN)r   set_textrG   )r8   r   r   r   r   r     s    zTextArea.set_textc             C   s
   | j  S )z5Returns the string representation of this area's text)r   get_text)r8   r   r   r   r     s    zTextArea.get_textc             C   s   || _ d| _dS )z
        Set multilinebaseline .

        If True, baseline for multiline text is
        adjusted so that it is (approximatedly) center-aligned with
        singleline text.
        TN)r   rG   )r8   r   r   r   r   set_multilinebaseline  s    zTextArea.set_multilinebaselinec             C   s   | j S )z)
        get multilinebaseline .
        )r   )r8   r   r   r   get_multilinebaseline  s    zTextArea.get_multilinebaselinec             C   s   || _ d| _dS )z
        Set minimumdescent .

        If True, extent of the single line text is adjusted so that
        it has minimum descent of "p"
        TN)r   rG   )r8   r   r   r   r   set_minimumdescent  s    zTextArea.set_minimumdescentc             C   s   | j S )z%
        get minimumdescent.
        )r   )r8   r   r   r   get_minimumdescent  s    zTextArea.get_minimumdescentc             C   s   dS )z+
        set_transform is ignored.
        Nr   )r8   r   r   r   r   r   
  s    zTextArea.set_transformc             C   s0   || _ | j  | j|d |d  d| _dS )z
        Set the offset of the container.

        Parameters
        ----------
        xy : (float, float)
            The (x,y) coordinates of the offset in display units.
        r   r   TN)r7   r   r   r   rG   )r8   rH   r   r   r   rI     s    	
zTextArea.set_offsetc             C   s   | j S )z1
        return offset of the container.
        )r7   )r8   r   r   r   rO     s    zTextArea.get_offsetc             C   s8   |  |\}}}}|  \}}tj|| || ||S )z8
        get the bounding box in display space.
        )rY   rO   rZ   r   r[   )r8   rN   r   r'   rW   rX   rd   re   r   r   r   r^   %  s    zTextArea.get_window_extentc             C   s   | j | j j \}}|jd| j jdd\}}}| j |\}}}	|j|j }
}|d d }| j  t	|dkr| j
rd| d||   }| jd|	|  |}	n,t|| ||	 }|  rt|	|}	||	 }|
|d|	fS )	NZlpF)ismathr   r   r   g      ?g        )r   Zis_math_textZget_text_width_height_descentZ_fontpropertiesZ_get_layoutrK   r-   r   r   r   r   r   r   r   )r8   rN   Z
clean_liner   _Zh_Zd_r   infor(   r   r'   lineZd_newZh_dr   r   r   rY   -  s     

zTextArea.get_extentc             C   s,   | j | t| |dtddd d| _dS )z#
        Draw the children
        Fg        )r_   )r`   ra   N)r   rb   r   rc   rG   )r8   rN   r   r   r   rb   M  s    zTextArea.draw)NNT)rf   rg   rh   ri   r5   r   r   r   r   r   r   r   rI   rO   r^   rY   rb   r   r   r   r   r     s      
(
 r   c               @   sX   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd ZdS )AuxTransformBoxaX  
    Offset Box with the aux_transform. Its children will be
    transformed with the aux_transform first then will be
    offseted. The absolute coordinate of the aux_transform is meaning
    as it will be automatically adjust so that the left-lower corner
    of the bounding box of children will be set to (0,0) before the
    offset transform.

    It is similar to drawing area, except that the extent of the box
    is not predetermined but calculated from the window extent of its
    children. Furthermore, the extent of the children will be
    calculated in the transformed coordinate.
    c             C   sJ   || _ t|  t | _| j  | jdd t | _| j  d S )Nr   )	aux_transformr3   r5   rZ   r   r   r   r   ref_offset_transform)r8   r   r   r   r   r5   f  s    



zAuxTransformBox.__init__c             C   s$   | j | ||   d| _dS )z?Add any :class:`~matplotlib.artist.Artist` to the container boxTN)r6   r   r   r   rG   )r8   rE   r   r   r   r   t  s    zAuxTransformBox.add_artistc             C   s   | j | j | j S )zf
        Return the :class:`~matplotlib.transforms.Transform` applied
        to the children
        )r   r   r   )r8   r   r   r   r   z  s    
zAuxTransformBox.get_transformc             C   s   dS )z+
        set_transform is ignored.
        Nr   )r8   r   r   r   r   r     s    zAuxTransformBox.set_transformc             C   s0   || _ | j  | j|d |d  d| _dS )z
        Set the offset of the container.

        Parameters
        ----------
        xy : (float, float)
            The (x,y) coordinates of the offset in display units.
        r   r   TN)r7   r   r   r   rG   )r8   rH   r   r   r   rI     s    	
zAuxTransformBox.set_offsetc             C   s   | j S )z1
        return offset of the container.
        )r7   )r8   r   r   r   rO     s    zAuxTransformBox.get_offsetc             C   s8   |  |\}}}}|  \}}tj|| || ||S )z8
        get the bounding box in display space.
        )rY   rO   rZ   r   r[   )r8   rN   r   r'   rW   rX   rd   re   r   r   r   r^     s    z!AuxTransformBox.get_window_extentc                s|   | j  }| j  | j    fdd| jD }tj|}| j|j	 |j
  | j j| }| j | |j|jddfS )Nc                s   g | ]}|  qS r   )r^   )r   r?   )rN   r   r   r     s    z.AuxTransformBox.get_extent.<locals>.<listcomp>g        )r   Z	to_valuesr   r   r6   rZ   r   unionr   r   r   Zmatrix_from_valuesZ
set_matrixrK   r-   )r8   rN   Z_offZbboxesZubZmtxr   )rN   r   rY     s    


zAuxTransformBox.get_extentc             C   s:   x| j D ]}|| qW t| |dtddd d| _dS )z#
        Draw the children
        Fg        )r_   )r`   ra   N)r6   rb   r   rc   rG   )r8   rN   r?   r   r   r   rb     s    zAuxTransformBox.drawN)rf   rg   rh   ri   r5   r   r   r   rI   rO   r^   rY   rb   r   r   r   r   r   X  s   	r   c                   s   e Zd ZdZdZdddddddd	d
dd
Zd) fdd	Zdd Zdd Zdd Z	dd Z
dd Zd*ddZdd  Zd+d!d"Zd,d#d$Zd%d& Zd'd( Z  ZS )-AnchoredOffsetboxa7  
    An offset box placed according to the legend location
    loc. AnchoredOffsetbox has a single child. When multiple children
    is needed, use other OffsetBox class to enclose them.  By default,
    the offset box is anchored against its parent axes. You may
    explicitly specify the bbox_to_anchor.
       r   ro                  	   
   )
zupper rightz
upper leftz
lower leftzlower rightr,   zcenter leftzcenter rightzlower centerzupper centerr.   皙?      ?NTc	       
   	      s  t  jf |	 | || | | t|trjy| j| }W n, tk
rh   td|d	| jf Y nX || _
|| _|| _|dkrttd d| _n6t|trtf || _d|kr| jtd  n|| _tdddd	d
| j dd| _| jjddd || _dS )a  
        loc is a string or an integer specifying the legend location.
        The valid location codes are::

        'upper right'  : 1,
        'upper left'   : 2,
        'lower left'   : 3,
        'lower right'  : 4,
        'right'        : 5, (same as 'center right', for back-compatibility)
        'center left'  : 6,
        'center right' : 7,
        'lower center' : 8,
        'upper center' : 9,
        'center'       : 10,

        pad : pad around the child for drawing a frame. given in
          fraction of fontsize.

        borderpad : pad between offsetbox frame and the bbox_to_anchor,

        child : OffsetBox instance that will be anchored.

        prop : font property. This is only used as a reference for paddings.

        frameon : draw a frame box if True.

        bbox_to_anchor : bbox to anchor. Use self.axes.bbox if None.

        bbox_transform : with which the bbox_to_anchor will be transformed.

        z4Unrecognized location "%s". Valid locations are
	%s
z
	Nzlegend.fontsize)sizer   )g        g        g      ?r   rz   T)rH   rK   r-   r{   r|   r}   r~   r   r   )r_   )r4   r5   set_bbox_to_anchor	set_childrq   strcodesKeyErrorr!   joinloc	borderpadr_   r   r   proprc   Zset_sizer   get_size_in_pointsr   r   r   )
r8   r   r_   r   r   r   frameonbbox_to_anchorZbbox_transformr   )r9   r   r   r5     s4    %



zAnchoredOffsetbox.__init__c             C   s    || _ |dk	r| j|_d| _dS )zset the child to be anchoredNT)_childr@   rG   )r8   r   r   r   r   r   %  s    zAnchoredOffsetbox.set_childc             C   s   | j S )zreturn the child)r   )r8   r   r   r   	get_child,  s    zAnchoredOffsetbox.get_childc             C   s   | j gS )zreturn the list of children)r   )r8   r   r   r   r=   0  s    zAnchoredOffsetbox.get_childrenc             C   sT   |   |\}}}}|| j }| j| }|d|  |d|  || || fS )zq
        return the extent of the artist. The extent of the child
        added with the pad is returned
        ro   )r   rY   rp   r   r   r_   )r8   rN   r   r'   rW   rX   r   r_   r   r   r   rY   4  s    
zAnchoredOffsetbox.get_extentc             C   s6   | j dkr| jjS | j}|dkr&| j S t| j |S dS )zB
        return the bbox that the legend will be anchored
        N)_bbox_to_anchorr@   r   _bbox_to_anchor_transformr   )r8   	transformr   r   r   get_bbox_to_anchor?  s    
z$AnchoredOffsetbox.get_bbox_to_anchorc             C   s   |dkst |tr|| _nZyt|}W n$ tk
rJ   tdt| Y nX |dkrh|d |d ddg}tj| | _|| _	d| _
dS )aF  
        set the bbox that the child will be anchored.

        *bbox* can be a Bbox instance, a list of [left, bottom, width,
        height], or a list of [left, bottom] where the width and
        height will be assumed to be zero. The bbox will be
        transformed to display coordinate by the given transform.
        NzInvalid argument for bbox : %sro   r   r   T)rq   r   r   r   	TypeErrorr!   r   r   r[   r   rG   )r8   r   r   lr   r   r   r   M  s    	z$AnchoredOffsetbox.set_bbox_to_anchorc             C   sJ   |  | | |\}}}}| |||||\}}t|| || ||S )z8
        get the bounding box in display space.
        )_update_offset_funcrY   rO   r   r[   )r8   rN   r   r'   rW   rX   rd   re   r   r   r   r^   f  s    
z#AnchoredOffsetbox.get_window_extentc             C   s4   |dkr| | j }|| fdd}| | dS )zs
        Update the offset func which depends on the dpi of the
        renderer (because of the padding).
        Nc             S   sH   t dd| |}|j| }| }	||j||	|\}
}|
| || fS )Nr   )r   r[   r   r   _get_anchored_bboxr   )r   r'   rW   rX   rN   r   r8   r   r   r   r   r   r   r   r   r7   x  s    

z6AnchoredOffsetbox._update_offset_func.<locals>._offset)rp   r   r   rI   )r8   rN   r   r7   r   r   r   r   o  s
    z%AnchoredOffsetbox._update_offset_funcc             C   s.   | j |j|j|j|j |r*| j | d S )N)r   r   r   r   rK   r-   r   )r8   r   r   r   r   r   r     s    zAnchoredOffsetbox.update_framec       
      C   s   |   sdS || j }| || | jrP| |}| || | j	| | 
|\}}}}| |||||\}}	|  ||	f |  	| d| _dS )zdraw the artistNF)rR   rp   r   r   r   r   r^   r   r   rb   rY   rO   r   rI   rG   )
r8   rN   r   r   rK   r-   rL   rM   r\   r]   r   r   r   rb     s    
zAnchoredOffsetbox.drawc             C   s   |t ddkstt d\}}}}}	}
}}}}}|d|d|d|	d|
d|d|d|d	|d
|di
}|| }|| }|j||d}|j|jfS )z{
        return the position of the bbox anchored at the parentbbox
        with the loc code, with the borderpad.
        r      ZNEZNWZSWZSEEWSNC)	container)rangeAssertionErrorZpaddedZanchoredr   r   )r8   r   r   Z
parentbboxr   ZBESTZURZULZLLZLRRZCLZCRZLCZUCr   Zanchor_coefsr?   r   Zanchored_boxr   r   r   r     s     z$AnchoredOffsetbox._get_anchored_bbox)r   r   NNTNN)N)N)N)rf   rg   rh   ri   zorderr   r5   r   r   r=   rY   r   r   r^   r   r   rb   r   rk   r   r   )r9   r   r     s6      D
	

r   c                   s"   e Zd ZdZd fdd	Z  ZS )AnchoredTextz&
    AnchoredOffsetbox with Text.
    皙?      ?Nc       	         sn   |dkri }ddddh}|t |@ r.td t||dd| _| jj }t j|f||| j|d	| dS )
a  
        Parameters
        ----------
        s : string
            Text.

        loc : str
            Location code.

        pad : float, optional
            Pad between the text and the frame as fraction of the font
            size.

        borderpad : float, optional
            Pad between the frame and the axes (or *bbox_to_anchor*).

        prop : dictionary, optional, default: None
            Dictionary of keyword parameters to be passed to the
            `~matplotlib.text.Text` instance contained inside AnchoredText.

        Notes
        -----
        Other keyword parameters of `AnchoredOffsetbox` are also
        allowed.
        NZhaZhorizontalalignmentr   ZverticalalignmentzSMixing horizontalalignment or verticalalignment with AnchoredText is not supported.F)r   r   )r_   r   r   r   )	setwarningswarnr   Ztxtr   Zget_fontpropertiesr4   r5   )	r8   r   r   r_   r   r   r   Z	badkwargsfp)r9   r   r   r5     s    
zAnchoredText.__init__)r   r   N)rf   rg   rh   ri   r5   rk   r   r   )r9   r   r     s   r   c            	   @   s^   e Zd ZdddZdd	 Zd
d Zdd Zdd Zdd Zdd Z	dd Z
dd Zdd ZdS )OffsetImager   N      @FTc             K   sV   t |  |
| _tf | j|||||||	d|| _| jg| _| | | | d S )N)r   cmapnorminterpolationorigin
filternorm	filterradresample)	r3   r5   _dpi_corr
   r^   imager6   set_zoomset_data)r8   arrzoomr   r   r   r   r   r   r   r   r   r   r   r   r5     s    



zOffsetImage.__init__c             C   s$   t || _| j| j d| _d S )NT)r   Zasarray_datar   r   rG   )r8   r   r   r   r   r     s    zOffsetImage.set_datac             C   s   | j S )N)r   )r8   r   r   r   get_data  s    zOffsetImage.get_datac             C   s   || _ d| _d S )NT)_zoomrG   )r8   r   r   r   r   r     s    zOffsetImage.set_zoomc             C   s   | j S )N)r   )r8   r   r   r   get_zoom  s    zOffsetImage.get_zoomc             C   s   | j S )z1
        return offset of the container.
        )r7   )r8   r   r   r   rO   .  s    zOffsetImage.get_offsetc             C   s   | j gS )N)r   )r8   r   r   r   r=   4  s    zOffsetImage.get_childrenc             C   s8   |  |\}}}}|  \}}tj|| || ||S )z8
        get the bounding box in display space.
        )rY   rO   rZ   r   r[   )r8   rN   r   r'   rW   rX   rd   re   r   r   r   r^   7  s    zOffsetImage.get_window_extentc       	      C   s^   | j r|d}nd}|  }|  }|jd d \}}|| | || |  }}||ddfS )Ng      ?ro   r   )r   rp   r   r   shape)	r8   rN   r   r   dataZnyZnxr   r'   r   r   r   rY   ?  s    zOffsetImage.get_extentc             C   s   | j | d| _dS )z#
        Draw the children
        FN)r   rb   rG   )r8   rN   r   r   r   rb   L  s    zOffsetImage.draw)	r   NNNNr   r   FT)rf   rg   rh   r5   r   r   r   r   rO   r=   r^   rY   rb   r   r   r   r   r     s$           
r   c               @   s   e Zd ZdZdZdd Zejd"d
dZe	dd Z
e
jdd Z
e	dd Zejdd Zdd Zdd Zdd Zd#ddZd$ddZdd Zdd Zd d! ZdS )%AnnotationBboxzD
    Annotation-like class, but with offsetbox instead of Text.
    r   c             C   s   d| j d | j d f S )NzAnnotationBbox(%g,%g)r   r   )rH   )r8   r   r   r   __str__[  s    zAnnotationBbox.__str__Nr  T皙?g      ?g      ?c          	   K   s   t jj| f| tj| |||d || _|| _| | |dkrH|| _n|| _|dkr^|| _n|| _|dk	r| j	dd| _
td| j| _nd| _
d| _|	| _tdddd	d
| j dd| _| jjd|d |
r| jjf |
 || _dS )ao  
        *offsetbox* : OffsetBox instance

        *xycoords* : same as Annotation but can be a tuple of two
           strings which are interpreted as x and y coordinates.

        *boxcoords* : similar to textcoords as Annotation but can be a
           tuple of two strings which are interpreted as x and y
           coordinates.

        *box_alignment* : a tuple of two floats for a vertical and
           horizontal alignment of the offset box w.r.t. the *boxcoords*.
           The lower-left corner is (0.0) and upper-right corner is (1.1).

        other parameters are identical to that of Annotation.
        )xycoordsannotation_clipNrelpos)g      ?g      ?r   r   r   r   )g        g        g      ?r   rz   T)rH   rK   r-   r{   r|   r}   r~   r   )r_   )r	  r
  )r:   r;   r5   r   	offsetbox
arrowpropsset_fontsizexybox	boxcoordspop_arrow_relposr   arrow_patch_box_alignmentr   r   r   r   r   r   r   )r8   r  rH   r  r  r  r   r_   r  Zbox_alignment	bboxpropsr  r   r   r   r   r   r5   ^  s<    

zAnnotationBbox.__init__c             C   s   | j S )N)r  )r8   r   r   r   xyann  s    zAnnotationBbox.xyannc             C   s   || _ d| _d S )NT)r  rG   )r8   r  r   r   r   r    s    c             C   s   | j S )N)r  )r8   r   r   r   	anncoords  s    zAnnotationBbox.anncoordsc             C   s   || _ d| _d S )NT)r  rG   )r8   Zcoordsr   r   r   r    s    c             C   s   | j |\}}||fS )N)r  rC   )r8   eventr   Ztinfor   r   r   rC     s    zAnnotationBbox.containsc             C   s"   | j | jg}| jr|| j |S )N)r  r   r  r   )r8   rm   r   r   r   r=     s    zAnnotationBbox.get_childrenc             C   s4   | j d k	r| j | | j| tj| | d S )N)r  r<   r  r:   r;   )r8   r>   r   r   r   r<     s    
zAnnotationBbox.set_figurec             C   s&   |dkrt d }t|d| _d| _dS )z(
        set fontsize in points
        Nzlegend.fontsize)r   T)r   r   r   rG   )r8   r   r   r   r   r    s    zAnnotationBbox.set_fontsizec             C   s
   | j  S )z+
        return fontsize in points
        )r   r   )r8   r   r   r   r   get_fontsize  s    zAnnotationBbox.get_fontsizec             C   sF   |  |}| || ||  }| j| | jrB| j| dS )zQ
        Update the pixel positions of the annotated point and the text.
        N)_get_position_xy_update_position_xyboxrp   r  r   r   r  )r8   rN   xy_pixelr}   r   r   r   update_positions  s    
zAnnotationBbox.update_positionsc             C   s  | j \}}t| jtrT| j\}}| ||||\}}| ||||\}	}
||
 }}n| |||| j\}}| j|\}}}}| j\}}| j|||  | |||  | f | j	|}| j
|j|j|j|j |\}}|| }}| jr|| }}| j }| j}|j|j|d   }|j|j|d   }| j||f||f | j }|d|}||}| j| |d| j
}| j| dS )z`
        Update the pixel positions of the annotation text and the arrow
        patch.
        r   r   r}   patchAN)r  rq   r  tupleZ_get_xyr  rY   r  rI   r^   r   r   r   r   rK   r-   r  copyr  r  Zset_positionsr   r   r  rp   r   Z
set_patchA)r8   rN   r  xyZxcoordZycoordZx1Zy1Zx2Zy2Zox0Zoy0r   r'   rW   rX   Z_fwZ_fhr   Zox1Zoy1r   r   r(   r  Zfsr}   r  r   r   r   r    s8    


(




z%AnnotationBbox._update_position_xyboxc             C   s   |dk	r|| _ |  sdS | |}| ||s4dS | | | jdk	rt| jjdkrh| jdk	rh| j| j_| j| | jr| j	| | j
| d| _dS )zN
        Draw the :class:`Annotation` object to the given *renderer*.
        NF)Z	_rendererrR   r  Z	_check_xyr  r  r   rb   r   r   r  rG   )r8   rN   r  r   r   r   rb   *  s     



zAnnotationBbox.draw)
Nr  NTr  Nr  NNN)N)N)rf   rg   rh   ri   r   r  r	   Zdedent_interpdr5   r   r  rj   r  rC   r=   r<   r  r  r  r  rb   r   r   r   r   r  U  s2           @



<r  c               @   sj   e Zd ZdZdddZdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd ZdS )DraggableBasea.  
    helper code for a draggable artist (legend, offsetbox)
    The derived class must override following two method.

      def save_offset(self):
          pass

      def update_offset(self, dx, dy):
          pass

    *save_offset* is called when the object is picked for dragging and it
    is meant to save reference position of the artist.

    *update_offset* is called during the dragging. dx and dy is the pixel
     offset from the point where the mouse drag started.

    Optionally you may override following two methods.

      def artist_picker(self, artist, evt):
          return self.ref_artist.contains(evt)

      def finalize_offset(self):
          pass

    *artist_picker* is a picker method that will be
     used. *finalize_offset* is called when the mouse is released. In
     current implementation of DraggableLegend and DraggableAnnotation,
     *update_offset* places the artists simply in display
     coordinates. And *finalize_offset* recalculate their position in
     the normalized axes coordinate and set a relavant attribute.
    Fc             C   s`   || _ d| _| j jj| _|o"| jj| _| jd| j}| jd| j}|	| j
 ||g| _d S )NFZ
pick_eventZbutton_release_event)
ref_artist
got_artistr   canvasZsupports_blit	_use_blitmpl_connecton_pick
on_releaseZ
set_pickerartist_pickercids)r8   r#  use_blitZc2Zc3r   r   r   r5   h  s    zDraggableBase.__init__c             C   s@   |   r<| jr<|j| j }|j| j }| || | j  d S )N)	_check_still_parentedr$  r   mouse_xr!  mouse_yupdate_offsetr%  rb   )r8   evtdxdyr   r   r   	on_motionu  s
    zDraggableBase.on_motionc             C   sh   |   rd| jrd|j| j }|j| j }| || | j| j	 | j
| j
jj | j| j
jj d S )N)r-  r$  r   r.  r!  r/  r0  r%  Zrestore_region
backgroundr#  rb   r   _cachedRendererblitr   )r8   r1  r2  r3  r   r   r   on_motion_blit|  s    zDraggableBase.on_motion_blitc             C   s   |   r|j| jkr|jj| _|jj| _d| _| j	r| j
d | j  | j| jjj| _| j| jjj | j| jjj | jd| j| _n| jd| j| _|   d S )NTZmotion_notify_event)r-  artistr#  rD   r   r.  r!  r/  r$  r&  set_animatedr%  rb   Zcopy_from_bboxr   r   r5  r6  r7  r'  r8  _c1r4  save_offset)r8   r1  r   r   r   r(    s     



zDraggableBase.on_pickc             C   s@   |   r<| jr<|   d| _| j| j | jr<| jd d S )NF)	r-  r$  finalize_offsetr%  mpl_disconnectr;  r&  r#  r:  )r8   r  r   r   r   r)    s    zDraggableBase.on_releasec             C   s    | j jd kr|   dS dS d S )NFT)r#  r   
disconnect)r8   r   r   r   r-    s    z#DraggableBase._check_still_parentedc             C   sL   x| j D ]}| j| qW y
| j}W n tk
r:   Y nX | j| dS )zdisconnect the callbacksN)r+  r%  r>  r;  AttributeError)r8   ZcidZc1r   r   r   r?    s    
zDraggableBase.disconnectc             C   s   | j |S )N)r#  rC   )r8   r9  r1  r   r   r   r*    s    zDraggableBase.artist_pickerc             C   s   d S )Nr   )r8   r   r   r   r<    s    zDraggableBase.save_offsetc             C   s   d S )Nr   )r8   r2  r3  r   r   r   r0    s    zDraggableBase.update_offsetc             C   s   d S )Nr   )r8   r   r   r   r=    s    zDraggableBase.finalize_offsetN)F)rf   rg   rh   ri   r5   r4  r8  r(  r)  r-  r?  r*  r<  r0  r=  r   r   r   r   r"  G  s   
		r"  c               @   s.   e Zd ZdddZdd Zdd Zdd	 Zd
S )DraggableOffsetBoxFc             C   s   t j| ||d || _d S )N)r,  )r"  r5   r  )r8   r#  r  r,  r   r   r   r5     s    zDraggableOffsetBox.__init__c             C   sN   | j }|jj}||\}}}}||||||}|\| _| _| j | d S )N)r  r   r6  rY   rO   offsetbox_xoffsetbox_yrI   )r8   r  rN   r   r'   rW   rX   offsetr   r   r   r<    s    zDraggableOffsetBox.save_offsetc             C   s$   | j | | j| f}| j| d S )N)rB  rC  r  rI   )r8   r2  r3  loc_in_canvasr   r   r   r0    s    z DraggableOffsetBox.update_offsetc       
      C   s>   | j }|jj}||\}}}}|j\}}|| || f}	|	S )N)r  r   r6  rY   r7   )
r8   r  rN   r   r'   rW   rX   rd   re   rE  r   r   r   get_loc_in_canvas  s    
z$DraggableOffsetBox.get_loc_in_canvasN)F)rf   rg   rh   r5   r<  r0  rF  r   r   r   r   rA    s   
rA  c               @   s&   e Zd Zd	ddZdd Zdd ZdS )
DraggableAnnotationFc             C   s   t j| ||d || _d S )N)r,  )r"  r5   
annotation)r8   rH  r,  r   r   r   r5     s    zDraggableAnnotation.__init__c             C   s"   | j }| |j\| _| _d S )N)rH  r   r   r  rd   re   )r8   annr   r   r   r<    s    zDraggableAnnotation.save_offsetc             C   s.   | j }|  | j| | j| f|_d S )N)rH  r   invertedr   rd   re   r  )r8   r2  r3  rI  r   r   r   r0    s    z!DraggableAnnotation.update_offsetN)F)rf   rg   rh   r5   r<  r0  r   r   r   r   rG    s   
rG  __main__r   y         g      p@ro   )r   r   r   )d   rO  )g      ?g      ?)   rP  r  zoffset pointsTg?roundr!  )ZboxstyleZfcz->)Z
arrowstyle)r  r  r  r   r_   r  r   r  )r   )r&   )Iri   r   Znumpyr   Zmatplotlib.transformsZ
transformsrZ   Zmatplotlib.artistr9  r:   Zmatplotlib.texttextr   Zmatplotlib.pathpathr   r   r   r   Zmatplotlib.font_managerr   Zmatplotlib.patchesr   r   Z
matplotlibr   r	   Zmatplotlib.imager
   r   r   r   r   r%   r2   r;   r3   rl   rn   rx   ry   r   r   r   r   r   r   r  objectr"  rA  rG  rf   Zmatplotlib.pyplotZpyplotZpltr   r>   ZclfZsubplotrB   rc   r   r    ZreshaperE   Zmyimager   rI   Zmyimage2rI  rb   Zshowr   r   r   r   <module>   s   	
1
% ,LNS  +n y.i s{






