U
    cP                     @   sf  d Z ddlZddlZddlZddl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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d0d1 Zd2d3 Zd4d5 Zd6d7 Zd8d9 Z d:d; Z!d<d= Z"d>d?d@dAd>d?dBZ#dCdDdEdFdGdHdIdJdKdLdM
Z$d@dNdOdPdQdRdSdTdUdVdVdWZ%dXdYdZd[Z&dS )]zG
Tools

A module for converting from mpl language to plotly language.

    Nc                 C   s   g }||d | d kf7 }||d | d kf7 }|d dkr|d |d  }| d | d  }||| dk f7 }||d | d kf7 }nT|d dkr|d	 |d  }| d	 | d  }||| dk f7 }||d | d kf7 }t |rd
S dS dS )zCheck if two bars belong in the same collection (bar chart).

    Positional arguments:
    old_bar -- a previously sorted bar dictionary.
    new_bar -- a new bar dictionary that needs to be sorted.

    Zorientation	facecolorvx1x0gư>y0hy1TFN)all)Zold_barZnew_bartestsZ	new_widthZ	old_widthZ
new_heightZ
old_height r   @/tmp/pip-unpacked-wheel-fki0jwev/plotly/matplotlylib/mpltools.pycheck_bar_match   s     r   c                 C   s   |    }|   }|d d |d d k r4dS |d d |d d k rPdS |d d |d d krldS |d d |d d krdS dS d S )Nr   F      T)Zget_window_extentZcorners)Z	inner_objZ	outer_objZinner_cornersZouter_cornersr   r   r   check_corners)   s    r   c                 C   s   | t krt |  S | d}t|dk r*dS tt|d drBdS ddd |D }|dkrdd	}n|d
krrd}n|dkr~d}|S dS )z@Convert mpl line symbol to plotly line symbol and return symbol.,   solidr           c                 S   s   g | ]}|d  qS )Zpxr   ).0xr   r   r   
<listcomp>I   s     z convert_dash.<locals>.<listcomp>z7.4px,3.2pxZdashedz12.8px,3.2px,2.0px,3.2pxdashdotz2.0px,3.3pxZdottedN)DASH_MAPsplitlenmathisclosefloatjoin)Zmpl_dashZ
dash_arrayZdashpxr   r   r   convert_dash8   s    
r    c                 C   s,   | d }t | d }|tkr$t| S d S d S )Nr   r   )tuplePATH_MAP)pathZvertscoder   r   r   convert_pathV   s
    r%   c                 C   sD   t | tr,t }| D ]}|t|g7 }q|S | tkr<t|  S dS dS )z=Convert mpl marker symbol to plotly symbol and return symbol.circleN)
isinstancelistconvert_symbol
SYMBOL_MAP)Z
mpl_symbolsymbolsr   r   r   r)   _   s    
r)   c                    s6    dt t fddtd  d D S )z
    Change a hex color to an rgb tuple

    :param (str|unicode) value: The hex string we want to convert.
    :return: (int, int, int) The red, green, blue int-tuple.

    Example:

        '#FFFFFF' --> (255, 255, 255)

    #c                 3   s(   | ] }t || d    dV  qdS )r      N)intr   ilvvaluer   r   	<genexpr>z   s     zhex_to_rgb.<locals>.<genexpr>r   r   )lstripr   r!   range)r4   r   r2   r   
hex_to_rgbl   s    
r8   c                 C   s:   | dkrdS t | }|dkr&d|S ||f }d|S )a  
    Merge hex color with an alpha (opacity) to get an rgba tuple.

    :param (str|unicode) color: A hex color string.
    :param (float|int) opacity: A value [0, 1] for the 'a' in 'rgba'.
    :return: (int, int, int, float) The rgba color and alpha tuple.

    Nzrgb {}zrgba {})r8   format)colorZopacityZrgb_tupZrgba_tupr   r   r   merge_color_and_opacity}   s    	

r;   c                 C   s   | t krt |  S dS dS )a  Convert mpl vertical alignment word to equivalent HTML word.

    Text alignment specifiers from mpl differ very slightly from those used
    in HTML. See the VA_MAP for more details.

    Positional arguments:
    mpl_va -- vertical mpl text alignment spec.

    N)VA_MAP)Zmpl_var   r   r   
convert_va   s    
r=   c                 C   sX   | d | d | d  g}|d |d  }|d |d  | }|d |d  | }||gS )aH  Map x dimension of current plot to plotly's domain space.

    The bbox used to locate an axes object in mpl differs from the
    method used to locate axes in plotly. The mpl version locates each
    axes in the figure so that axes in a single-plot figure might have
    the bounds, [0.125, 0.125, 0.775, 0.775] (x0, y0, width, height),
    in mpl's figure coordinates. However, the axes all share one space in
    plotly such that the domain will always be [0, 0, 1, 1]
    (x0, y0, x1, y1). To convert between the two, the mpl figure bounds
    need to be mapped to a [0, 1] domain for x and y. The margins set
    upon opening a new figure will appropriately match the mpl margins.

    Optionally, setting margins=0 and simply copying the domains from
    mpl to plotly would place axes appropriately. However,
    this would throw off axis and title labeling.

    Positional arguments:
    mpl_plot_bounds -- the (x0, y0, width, height) params for current ax **
    mpl_max_x_bounds -- overall (x0, x1) bounds for all axes **

    ** these are all specified in mpl figure coordinates

    r   r   r   r   )mpl_plot_boundsZmpl_max_x_boundsZ	mpl_x_domZplotting_widthr   r   r   r   r   convert_x_domain   s
    r?   c                 C   sX   | d | d | d  g}|d |d  }|d |d  | }|d |d  | }||gS )aH  Map y dimension of current plot to plotly's domain space.

    The bbox used to locate an axes object in mpl differs from the
    method used to locate axes in plotly. The mpl version locates each
    axes in the figure so that axes in a single-plot figure might have
    the bounds, [0.125, 0.125, 0.775, 0.775] (x0, y0, width, height),
    in mpl's figure coordinates. However, the axes all share one space in
    plotly such that the domain will always be [0, 0, 1, 1]
    (x0, y0, x1, y1). To convert between the two, the mpl figure bounds
    need to be mapped to a [0, 1] domain for x and y. The margins set
    upon opening a new figure will appropriately match the mpl margins.

    Optionally, setting margins=0 and simply copying the domains from
    mpl to plotly would place axes appropriately. However,
    this would throw off axis and title labeling.

    Positional arguments:
    mpl_plot_bounds -- the (x0, y0, width, height) params for current ax **
    mpl_max_y_bounds -- overall (y0, y1) bounds for all axes **

    ** these are all specified in mpl figure coordinates

    r   r   r   r   )r>   Zmpl_max_y_boundsZ	mpl_y_domZplotting_heightr   r   r   r   r   convert_y_domain   s
    r@   c                 C   sp   | |d d  }|d |d d |d d   }||d d  }|d |d d |d d   }|| || fS )a  Convert mpl display coordinates to plotly paper coordinates.

    Plotly references object positions with an (x, y) coordinate pair in either
    'data' or 'paper' coordinates which reference actual data in a plot or
    the entire plotly axes space where the bottom-left of the bottom-left
    plot has the location (x, y) = (0, 0) and the top-right of the top-right
    plot has the location (x, y) = (1, 1). Display coordinates in mpl reference
    objects with an (x, y) pair in pixel coordinates, where the bottom-left
    corner is at the location (x, y) = (0, 0) and the top-right corner is at
    the location (x, y) = (figwidth*dpi, figheight*dpi). Here, figwidth and
    figheight are in inches and dpi are the dots per inch resolution.

    marginlwidthrbheighttr   )r   yZlayoutZnum_xZden_xZnum_yZden_yr   r   r   display_to_paper   s
      rI   c                 C   s   g g g g f\}}}}|   D ]V}| j}||d  ||d |d   ||d  ||d |d   qt|t|t|t|f\}}}}||f||ffS )as  Return the entire axes space for figure.

    An axes object in mpl is specified by its relation to the figure where
    (0,0) corresponds to the bottom-left part of the figure and (1,1)
    corresponds to the top-right. Margins exist in matplotlib because axes
    objects normally don't go to the edges of the figure.

    In plotly, the axes area (where all subplots go) is always specified with
    the domain [0,1] for both x and y. This function finds the smallest box,
    specified by two points, that all of the mpl axes objects fit into. This
    box is then used to map mpl axes domains to plotly axes domains.

    r   r   r   r   )Zget_axesget_positionboundsappendminmax)ZfigZx_minZx_maxZy_minZy_maxZaxes_objrK   r   r   r   get_axes_bounds   s    
$rO   c                 C   s,   | r|rdS | r|sdS | s$|r$dS dS d S )NZticksFr   )Z
main_spineZmirror_spiner   r   r   get_axis_mirror  s    rP   绽|=c                    st   t | t |krpt | dkrp| dd  }|d d }dd t||D }|d  t fdd|D }|rp S d S )Nr   c                 S   s   g | ]\}}|| qS r   r   )r   s2s1r   r   r   r     s     zget_bar_gap.<locals>.<listcomp>r   c                    s   g | ]}t  | k qS r   )abs)r   ZgapZgap0tolr   r   r     s     )r   zipr	   )Z
bar_startsZbar_endsrW   Zsides1Zsides2Zgapsuniformr   rV   r   get_bar_gap  s    rZ   c                 C   s   t  }| D ]B}|tt|d d t|d d t|d d |d dg7 }q
t  }|D ]}|djf |g7 }qXt|dkr|d S |S d S )Nr      r   r   r   )rD   grE   azrgba({r},{g},{b},{a}))r(   dictr/   r9   r   )Z
color_listZclean_color_listcZplotly_colorsZrgbar   r   r   convert_rgba_array#  s    6r`   c                 C   s:   t  }| D ]}|t|g7 }q
t|dkr2|d S |S d S Nr   r   )r(   r%   r   )Z
path_arraysymbolsr#   r   r   r   convert_path_array2  s    rc   c                 C   s   t | dkr| d S | S d S ra   r   )Zwidth_arrayr   r   r   convert_linewidth_array<  s    re   c                 C   s*   dd | D }t |dkr"|d S |S d S )Nc                 S   s   g | ]}t |qS r   )r   sqrt)r   r,   r   r   r   r   D  s     z&convert_size_array.<locals>.<listcomp>r   r   rd   )Z
size_arraysizer   r   r   convert_size_arrayC  s    rh   c              	   C   sP   t d t| d d t| d t| d d t| d  t| d d d}|S )NZstylesr   pathsZ	linewidthmplobj	edgecolor)alphar   marker	edgewidthZ
markersizerk   )r^   r`   rc   re   rh   Z	get_sizes)propsZmarkerstyler   r   r   get_markerstyle_from_collectionK  s    
	rp   c                 C   s.   t | d d | d d | d d | d d S )z.Find minimum x value from four (x,y) vertices.r   r   r   r   rM   datar   r   r   get_rect_xminX  s    rt   c                 C   s.   t | d d | d d | d d | d d S )z.Find maximum x value from four (x,y) vertices.r   r   r   r   rN   rr   r   r   r   get_rect_xmax]  s    rv   c                 C   s.   t | d d | d d | d d | d d S )z.Find minimum y value from four (x,y) vertices.r   r   r   r   rq   rr   r   r   r   get_rect_yminb  s    rw   c                 C   s.   t | d d | d d | d d | d d S )z.Find maximum y value from four (x,y) vertices.r   r   r   r   ru   rr   r   r   r   get_rect_ymaxg  s    rx   c                 C   s   | j | }|  }|jpd}t|tr@|dkr4d}n|dkr@d}|\}}|dkr^|dkr^d}nd	}| snd	S |jd
 s|d	S |s|rd	S |r|rdS |s|sdS d	S dS )z8Return some spine parameters for the spine, `spine_key`.)outwardr   center)axesg      ?Zzero)rs   r   ry   r   TFrR   N)ZspinesZget_frame_on	_positionr'   strZget_visibleZ
_edgecolor)axZ	spine_keyZspineZax_frame_onpositionZposition_typeamountZspine_frame_liker   r   r   get_spine_visiblel  s.    



r   c                 K   s    | D ]}|d |kr dS qdS )zCA test to decide whether a path is a bar from a vertical bar chart.rj   TFr   )Zbar_containersro   	containerr   r   r   is_bar  s    r   c                  K   sp   | d t | d t| d t| d t| d | d d | d d | d d | d d | d d | d d	 d
S )a  Make an intermediate bar dictionary.

    This creates a bar dictionary which aids in the comparison of new bars to
    old bars from other bar chart (patch) collections. This is not the
    dictionary that needs to get passed to plotly as a data dictionary. That
    happens in PlotlyRenderer in that class's draw_bar method. In other
    words, this dictionary describes a SINGLE bar, whereas, plotly will
    require a set of bars to be passed in a data dictionary.

    rj   rs   stylerl   rk   r   rn   	dasharrayzorder)barr   r   r   r   rl   rk   r   rn   r   r   )rt   rw   rv   rx   )ro   r   r   r   make_bar  s    









r   c              
      s  t  }|dkr|  }n|dkr*|  }nt  S |d | d }|dkrz|d | d d }fdd	td
td
 D  t fdd	td
t d
 D rd
 d  }ntd| t	W n, t
t	fk
r   |d | d |d< Y nX ||d< ||d< d|d< n,|dkr@zP|d | d d |d< |d | d d
 |d | d d  |d< d|d< W n0 t
t	fk
r   t |d | d d}Y nX | j}	|	dkr"|dkrt|d d t|d d
 g|d< n2|dkr>t|d d t|d d
 g|d< nt ddd}td| nt  S | jj}
|dkrd|
krd|d< z2zt|d |
|d< W n tk
r   Y nX W 5 |dd |dd t|d |
|d< X |
dkrd|d< |S ) zPrepare axis obj belonging to axes obj.

    positional arguments:
    ax - the mpl axes instance
    index - the index of the axis in `props`
    ax_type - 'x' or 'y' (for now)
    props - an mplexporter poperties dictionary

    r   rH   r{   scaleZlinear
tickvaluesr   c                    s&   g | ]}t  |  |d    dqS )r      )roundr0   )r   r   r   r     s   zprep_ticks.<locals>.<listcomp>r   c                    s    g | ]} |  |d   kqS )r   r   r0   )dticksr   r   r     s     zF'linear' {0}-axis tick spacing not even, ignoring mpl tick formatting.ntickstick0dtickNZtickmodelog)r   
   xlimr7   ylim)r7   typez3Converted non-base10 {0}-axis log scale to 'linear'ZDateFormatterdater   ZLogFormatterMathtexteZexponentformat)r^   Z	get_xaxisZ	get_yaxisr7   r   r	   warningswarnr9   	TypeError
IndexErrorZget_transformbaser   log10Zget_major_formatter	__class____name__popmpl_dates_to_datestringsKeyError)r~   indexZax_typero   Z	axis_dictZaxisr   r   r   r   	formatterr   )r   r   r   
prep_ticks  s    




$








r   c              	   C   s   t |d d d t|d |d d d d t|d ||d d d t |d d d	 d
d}|t| dd| t |d d d t|d |d d d d t|d ||d d d t |d d d	 d
d}|t| dd| ||fS )Nr{   r   r   r   ZgridZgridOnrK   r   Zfontsize)rg   )r   r7   ZshowgriddomainZsideZtickfontr   r   r   rH   )r^   r(   r?   updater   r@   )r~   ro   Zx_boundsZy_boundsZxaxisZyaxisr   r   r   prep_xy_axis  s&    

r   c                 C   sz   | }|dkrFz&t jdd | D } t j| } W qh   | Y S X n"zt j| } W n   | Y S X dd | D }|S )zConvert matplotlib dates to iso-formatted-like time strings.

    Plotly's accepted format: "YYYY-MM-DD HH:MM:SS" (e.g., 2001-01-01 00:00:00)

    Info on mpl dates: http://matplotlib.org/api/dates_api.html

    ZTimeSeries_DateFormatterc                 S   s   g | ]}|d  d d qS )   <   r   r   r   r   r   r   r   *  s     z,mpl_dates_to_datestrings.<locals>.<listcomp>c                 S   s*   g | ]"}d  | dd dqS ) +r   T)r   	isoformatr   r   r   r   r   r   8  s    )
matplotlibdatesZ	epoch2numZnum2date)r   Zmpl_formatterZ_datesZtime_stingsr   r   r   r     s    
r   r   Zdashr&   r   )z10,0z6,6z2,2z4,4,2,4nonez7.4,3.2o*8r   p1r,   r   ^|)
)
MCr   r   r   r   r   r   r   Z)r   Lr   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   r   )r   r   r   r   r   r   )r   r   r   r   r   )r   r   r   r   )r   r   r   r   )r   r   ztriangle-downztriangle-upztriangle-leftztriangle-rightZsquareZcrossr   ZstarZdiamond)r   r   r   <>r,   r   r   r   DdZmiddleZbottomtop)rz   Zbaseliner   )rQ   )'__doc__r   datetimer   Zmatplotlib.datesr   r   r   r    r%   r)   r8   r;   r=   r?   r@   rI   rO   rP   rZ   r`   rc   re   rh   rp   rt   rv   rw   rx   r   r   r   r   r   r   r   r"   r*   r<   r   r   r   r   <module>   s   	


Y$
