U
    sVcL                     @  s   d Z ddlmZ ddlmZmZ ddlZddlZddl	m
Z
 ddlm  mZ ddlmZ ddlZddlmZ ddlmZ erddlmZ ejG d	d
 d
ZdddZdd Zdd ZdS )zF
Module consolidating common testing functions for checking plotting.
    )annotations)TYPE_CHECKINGSequenceN)cache_readonly)is_list_like)SeriesAxesc                   @  s   e Zd ZdZdd Zdd Zedd Zedd	 Zd9ddZ	d:ddZ
dd Zd;ddZd<ddddddZdd Zd=ddZdd Zd>d d!Zd?d#d$Zd@d%d&Zd'd( Zd)d* ZdAd,d-ZdBd.d/Zi fd0d1ZdCd3d4Zd5d6 Zd7d8 Zd
S )DTestPlotBasezE
    This is a common base class used for various plotting tests
    c                 C  s   dd l }|  d S Nr   )
matplotlibZ
rcdefaults)selfmpl r   @/tmp/pip-unpacked-wheel-xj8nt62q/pandas/tests/plotting/common.pysetup_method"   s    zTestPlotBase.setup_methodc                 C  s   t   d S N)tmcloser   r   r   r   teardown_method'   s    zTestPlotBase.teardown_methodc                 C  s   dd l m} |S r   )matplotlib.pyplotpyplot)r   pltr   r   r   r   *   s    zTestPlotBase.pltc                 C  s   dd l m} |jS r   )Zmatplotlib.colorscolorsZcolorConverter)r   r   r   r   r   colorconverter0   s    zTestPlotBase.colorconverterNTc                 C  sf   |r|dkrt d| |}|D ]>}|rP| dk	s:t| |  | q"| dks"tq"dS )aQ  
        Check each axes has expected legend labels

        Parameters
        ----------
        axes : matplotlib Axes object, or its list-like
        labels : list-like
            expected legend labels
        visible : bool
            expected legend visibility. labels are checked only when visible is
            True
        Nz-labels must be specified when visible is True)
ValueError_flatten_visible
get_legendAssertionError_check_text_labelsZ	get_texts)r   axeslabelsvisibleaxr   r   r   _check_legend_labels6   s    
z!TestPlotBase._check_legend_labelsc                 C  sT   |r|dkrt d|r@| \}}dd |D }||ksPtn| dksPtdS )aB  
        Check ax has expected legend markers

        Parameters
        ----------
        ax : matplotlib Axes object
        expected_markers : list-like
            expected legend markers
        visible : bool
            expected legend visibility. labels are checked only when visible is
            True
        Nz.Markers must be specified when visible is Truec                 S  s   g | ]}|  qS r   )Z
get_marker).0handler   r   r   
<listcomp>^   s     z5TestPlotBase._check_legend_marker.<locals>.<listcomp>)r   Zget_legend_handles_labelsr   r   )r   r$   Zexpected_markersr#   Zhandles_markersr   r   r   _check_legend_markerM   s    z!TestPlotBase._check_legend_markerc           	      C  s`   |  }|  }t|t|ks$tt||D ]$\}}| }| }t|| q.t  dS )z
        Check each axes has identical lines

        Parameters
        ----------
        xp : matplotlib Axes object
        rs : matplotlib Axes object
        N)	get_lineslenr   zipZ
get_xydatar   assert_almost_equalr   )	r   ZxprsZxp_linesZrs_linesZxplZrslZxpdataZrsdatar   r   r   _check_datac   s    	zTestPlotBase._check_datac                 C  sB   ddl m} t||s$t|s$|g}|D ]}| |ks(tq(dS )a   
        Check each artist is visible or not

        Parameters
        ----------
        collections : matplotlib Artist or its list-like
            target Artist or its list or collection
        visible : bool
            expected visibility
        r   )
CollectionN)matplotlib.collectionsr2   
isinstancer   get_visibler   )r   collectionsr#   r2   patchr   r   r   _check_visiblew   s
    zTestPlotBase._check_visiblezAxes | Sequence[Axes]boolNone)r!   filledreturnc                 C  s2   |  |}|D ]}|jD ]}|j|kstqqdS )z
        Check for each artist whether it is filled or not

        Parameters
        ----------
        axes : matplotlib Axes object, or its list-like
        filled : bool
            expected filling
        N)r   Zpatchesfillr   )r   r!   r;   r$   r7   r   r   r   _check_patches_all_filled   s    

z&TestPlotBase._check_patches_all_filledc                   s*   |  }tt||  fdd|jD S )Nc                   s   g | ]} | qS r   r   r&   vZmappedr   r   r(      s     z3TestPlotBase._get_colors_mapped.<locals>.<listcomp>)uniquedictr.   values)r   Zseriesr   rB   r   rA   r   _get_colors_mapped   s    zTestPlotBase._get_colors_mappedc                 C  s  ddl m}m}m} ddlm} | j}	|dk	r|dk	rR| ||}|dt| }t|t|ksft	t
||D ]d\}
}t|
|r|
 }|	|}n(t|
||frt|
 d }n|
 }|	|}||kspt	qp|dk	r|dk	r| ||}|dt| }t|t|kst	t
||D ]Z\}
}t|
|rH|
 d }n|
 }t|tjrft|}|	|}||ks&t	q&dS )a3  
        Check each artist has expected line colors and face colors

        Parameters
        ----------
        collections : list-like
            list or collection of target artist
        linecolors : list-like which has the same length as collections
            list of expected line colors
        facecolors : list-like which has the same length as collections
            list of expected face colors
        mapping : Series
            Series used for color grouping key
            used for andrew_curves, parallel_coordinates, radviz test
        r   )r2   LineCollectionPolyCollection)Line2DN)r3   r2   rF   rG   Zmatplotlib.linesrH   r   rE   r-   r   r.   r4   Z	get_colorZto_rgbatupleZget_edgecolorZget_facecolornpZndarray)r   r6   Z
linecolorsZ
facecolorsmappingr2   rF   rG   rH   convr7   colorresultexpectedr   r   r   _check_colors   s<    




zTestPlotBase._check_colorsc                 C  s`   t |s| |ks\tnBdd |D }t|t|ks<tt||D ]\}}||ksFtqFdS )a.  
        Check each text has expected labels

        Parameters
        ----------
        texts : matplotlib Text object, or its list-like
            target text, or its list
        expected : str or list-like which has the same length as texts
            expected text label, or its list
        c                 S  s   g | ]}|  qS r   )get_text)r&   tr   r   r   r(      s     z3TestPlotBase._check_text_labels.<locals>.<listcomp>N)r   rQ   r   r-   r.   )r   ZtextsrO   r"   labeler   r   r   r       s    zTestPlotBase._check_text_labelsc           
      C  s  ddl m} | |}|D ]}|dk	s.|dk	rt|j |rH| }n| |jdd }|D ]4}	|dk	r|t|		 | |dk	r`t|	
 | q`|dk	s|dk	rt|j |r| }n| |jdd }|D ]4}	|dk	rt|		 | |dk	rt|	
 | qqdS )a  
        Check each axes has expected tick properties

        Parameters
        ----------
        axes : matplotlib Axes object, or its list-like
        xlabelsize : number
            expected xticks font size
        xrot : number
            expected xticks rotation
        ylabelsize : number
            expected yticks font size
        yrot : number
            expected yticks rotation
        r   )NullFormatterNT)minor)Zmatplotlib.tickerrU   r   r4   xaxisZget_minor_formatterZget_xticklabelsr   r/   Zget_fontsizeZget_rotationyaxisZget_yticklabels)
r   r!   Z
xlabelsizeZxrotZ
ylabelsizeZyrotrU   r$   r"   rS   r   r   r   _check_ticks_props   s*    


zTestPlotBase._check_ticks_propslinearc                 C  s<   |  |}|D ](}|j |ks$t|j |kstqdS )a  
        Check each axes has expected scales

        Parameters
        ----------
        axes : matplotlib Axes object, or its list-like
        xaxis : {'linear', 'log'}
            expected xaxis scale
        yaxis : {'linear', 'log'}
            expected yaxis scale
        N)r   rW   Z	get_scaler   rX   )r   r!   rW   rX   r$   r   r   r   _check_ax_scales(  s    
zTestPlotBase._check_ax_scalesc           	      C  s   ddl m} |dkrd}| |}|dk	rXt||ks:t|D ]}t| dks>tq>|dk	rz| ||}||ksztt|d j	
 tj|tjd dS )a  
        Check expected number of axes is drawn in expected layout

        Parameters
        ----------
        axes : matplotlib Axes object, or its list-like
        axes_num : number
            expected number of axes. Unnecessary axes should be set to
            invisible.
        layout : tuple
            expected layout, (expected number of rows , columns)
        figsize : tuple
            expected figsize. default is matplotlib default
        r   flatten_axesN)g@g333333@)Zdtype)!pandas.plotting._matplotlib.toolsr]   r   r-   r   Zget_children_get_axes_layoutr   Zassert_numpy_array_equalfigureZget_size_inchesrJ   arrayZfloat64)	r   r!   Zaxes_numZlayoutZfigsizer]   Zvisible_axesr$   rN   r   r   r   _check_axes_shape9  s    
zTestPlotBase._check_axes_shapec                 C  sV   t  }t  }|D ]4}|  }||d d  ||d d  qt|t|fS )Nr      )setget_positionZ
get_pointsaddr-   )r   r!   Zx_setZy_setr$   Zpointsr   r   r   r_   ]  s    zTestPlotBase._get_axes_layoutc                 C  s&   ddl m} ||}dd |D }|S )z
        Flatten axes, and filter only visible

        Parameters
        ----------
        axes : matplotlib Axes object, or its list-like

        r   r\   c                 S  s   g | ]}|  r|qS r   )r5   )r&   r$   r   r   r   r(   s  s      z1TestPlotBase._flatten_visible.<locals>.<listcomp>)r^   r]   )r   r!   r]   r   r   r   r   g  s    	zTestPlotBase._flatten_visibler   c                 C  sx   |  |}|D ]d}|j}d}d}|D ]4}t|dd}	t|dd}
|	rL|d7 }|
r$|d7 }q$||ksft||kstqdS )a  
        Check axes has expected number of errorbars

        Parameters
        ----------
        axes : matplotlib Axes object, or its list-like
        xerr : number
            expected number of x errorbar
        yerr : number
            expected number of y errorbar
        r   has_xerrFhas_yerrrc   N)r   
containersgetattrr   )r   r!   ZxerrZyerrr$   ri   Z
xerr_countZ
yerr_countcrg   rh   r   r   r   _check_has_errorbarsv  s    

z!TestPlotBase._check_has_errorbarsc                 C  s  ddl m} t|td}|dkrj|dkr,d}t||| s>t|dkrft|j|sVtt|jtsftn|dkr| |D ]}t||s|tq|dS t|t	stt
| t
|kst| D ]\}}	t|	|| st|dkr|r|	 |kstq|dkrD|r|	j |kstt|	j|s0tt|	jts~tq|dkrz|	d d }
|
j}|r~| |ks~tqtqdS )	at  
        Check box returned type is correct

        Parameters
        ----------
        returned : object to be tested, returned from boxplot
        return_type : str
            return_type passed to boxplot
        expected_keys : list-like, optional
            group labels in subplot case. If not passed,
            the function checks assuming boxplot uses single ax
        check_ax_title : bool
            Whether to check the ax.title is the same as expected_key
            Intended to be checked by calling from ``boxplot``.
            Normal ``plot`` doesn't attach ``ax.title``, it must be disabled.
        r   r   )rC   r!   bothNrC   rm   r!   Zmedians)matplotlib.axesr	   rC   rI   r4   r   r$   linesr   r   sortedkeysitemsZ	get_titler!   )r   Zreturnedreturn_typeZexpected_keysZcheck_ax_titler	   typesrkeyvalueliner!   r   r   r   _check_box_return_type  s>    

z#TestPlotBase._check_box_return_typec                   sf  dd l } fdd}d}|D ]B} jddt| | |d7 }|jddd |jf d	|i| | rnt jddt| | |d7 }|jdd
d |jf |dd| | rt|dkr jddt| | |d7 }|jdd
d |jf d	|i| | st jddt| | |d7 }|jddd |jf |d
d| | stqd S )Nr   c                    sN    j  j }  j  j }tdd | D }tdd |D }|oJ| S )Nc                 s  s   | ]}|j   V  qd S r   Zgridliner5   r&   gr   r   r   	<genexpr>  s     zHTestPlotBase._check_grid_settings.<locals>.is_grid_on.<locals>.<genexpr>c                 s  s   | ]}|j   V  qd S r   rz   r{   r   r   r   r}     s     )r   ZgcarW   Zget_major_ticksrX   all)ZxticksZyticksZxoffZyoffr   r   r   
is_grid_on  s
    z5TestPlotBase._check_grid_settings.<locals>.is_grid_onrc      r!   F)gridkindT)r   r   )ZpieZhexbinZscatter)r   r   Zsubplotr-   rcZplotr   )r   objkindskwsr   r   Zspndxr   r   r   r   _check_grid_settings  s2    


z!TestPlotBase._check_grid_settingsrM   c                   s    fdd|d D S )zT
        Auxiliary function for correctly unpacking cycler after MPL >= 1.5
        c                   s   g | ]}|  qS r   r   r?   fieldr   r   r(     s     z/TestPlotBase._unpack_cycler.<locals>.<listcomp>zaxes.prop_cycler   )r   ZrcParamsr   r   r   r   _unpack_cycler  s    zTestPlotBase._unpack_cyclerc                 C  s"   ddl m} | r|jd S |jS )Nr   mpl_ge_3_5_0x)"pandas.plotting._matplotlib.compatr   _shared_axesZ_shared_x_axesr   r$   r   r   r   r   
get_x_axis  s    
zTestPlotBase.get_x_axisc                 C  s"   ddl m} | r|jd S |jS )Nr   r   y)r   r   r   Z_shared_y_axesr   r   r   r   
get_y_axis  s    
zTestPlotBase.get_y_axis)NT)NT)T)T)NNN)NNNN)rZ   rZ   )NNN)r   r   )NT)rM   )__name__
__module____qualname____doc__r   r   r   r   r   r%   r+   r1   r8   r>   rE   rP   r    rY   r[   rb   r_   r   rl   ry   r   r   r   r   r   r   r   r   r
      sH   




      
B       
0

$

   
<)
r
   alwaysFc           
      K  s   ddl m} |rt}nt}d}t  t| zz\|	d|
 }|  || |f|D ]}t| q\tjdd}|| W 5 Q R X W n& tk
r }	 z|	W 5 d}	~	X Y nX W 5 t| X |W  5 Q R  S Q R X dS )aT  
    Create plot and ensure that plot return object is valid.

    Parameters
    ----------
    f : func
        Plotting function.
    filterwarnings : str
        Warnings filter.
        See https://docs.python.org/3/library/warnings.html#warning-filter
    default_axes : bool, optional
        If False (default):
            - If `ax` not in `kwargs`, then create subplot(211) and plot there
            - Create new subplot(212) and plot there as well
            - Mind special corner case for bootstrap_plot (see `_gen_two_subplots`)
        If True:
            - Simply run plotting function with kwargs provided
            - All required axes instances will be created automatically
            - It is recommended to use it when the plotting function
            creates multiple axes itself. It helps avoid warnings like
            'UserWarning: To output multiple subplots,
            the figure containing the passed axes is being cleared'
    **kwargs
        Keyword arguments passed to the plotting function.

    Returns
    -------
    Plot object returned by the last plotting.
    r   Nr`   T)Zreturn_filelike)r   r   _gen_default_plot_gen_two_subplotswarningscatch_warningssimplefilterr   r   getZgcfZclfZ"assert_is_valid_plot_return_objectZensure_cleanZsavefig	Exception)
ffilterwarningsZdefault_axeskwargsr   Z	gen_plotsretfigpatherrr   r   r   _check_plot_works  s$    

r   c                 k  s   | f |V  dS )z'
    Create plot in a default way.
    Nr   r   r   r   r   r   r   r   E  s    r   c                 k  sV   d|kr| d | f |V  | tjjkr8d|ksFtn| d|d< | f |V  dS )z9
    Create plot on two subplots forcefully created.
    r$         N)Zadd_subplotpdZplottingZbootstrap_plotr   r   r   r   r   r   L  s    
r   )r   F)r   
__future__r   typingr   r   r   ZnumpyrJ   Zpandas.util._decoratorsr   Zpandas.util._test_decoratorsutilZ_test_decoratorstdZpandas.core.dtypes.apir   Zpandasr   r   Zpandas._testingZ_testingr   rn   r	   Zskip_if_no_mplr
   r   r   r   r   r   r   r   <module>   s(      q
: