
    hMh                      d dl mZ d dl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Zd dlZd dlZd dlmZ d d	lmZmZ d d
lmZmZmZmZmZmZ  G d d          Z  G d de           Z! G d de           Z" G d de           Z# G d d          Z$ G d de          Z%ddZ&ddZ'd Z(d Z)d dZ*dS )!    )annotationsNcopy)
UserString)IterableSequenceMapping)Number)datetime)PlotData)QUAL_PALETTEScolor_palette)_check_argument_version_predates
desaturatelocator_to_legend_entriesget_color_cycle	remove_nac                  B    e Zd ZU dZdZded<   dZdZd Zd Z	d Z
d ZdS )	SemanticMappingz6Base class for mapping data values to plot attributes.Nz
str | Nonemap_typec                    || _         d S N)plotter)selfr   s     M/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/seaborn/_base.py__init__zSemanticMapping.__init__+   s         c                @   d}t          |          t          |          k    rjd                    d| dt          |           ddt          |           ddg          }d	 t          |t          j        |                    D             }nst          |          t          |          k    rSd                    d
| dt          |           ddt          |           dg          }|dt          |                   }|rt          j        |t          d           |S )z/Input check when values are provided as a list.  z
The z list has fewer values ()zthan needed (z) and will cycle, which mayz produce an uninterpretable plot.c                    g | ]\  }}|S  r$   ).0_xs      r   
<listcomp>z6SemanticMapping._check_list_length.<locals>.<listcomp>>   s    IIIDAqaIIIr   The z list has more values (z), which may not be intended.N   
stacklevel)lenjoinzip	itertoolscyclewarningswarnUserWarning)r   levelsvaluesvariablemessages        r   _check_list_lengthz"SemanticMapping._check_list_length4   s0    v;;V$$hhIII3v;;IIIHFHHH2   G
 JIC	0G0G$H$HIIIFF[[3v;;&&hhFxFFFFFFJFJJJ   G LS[[L)F 	>M';1====r   c                    | j         |         S )z)Apply the mapping to a single data value.lookup_table)r   keys     r   _lookup_singlezSemanticMapping._lookup_singleL   s     %%r   c                     t          |t          t          j        t          j        f          r fd|D             S   j        |gR i S )z-Get the attribute(s) values for the data key.c                2    g | ]} j         |gR i S r$   )r>   )r%   kargskwargsr   s     r   r(   z,SemanticMapping.__call__.<locals>.<listcomp>S   s7    III'D';D;;;F;;IIIr   )
isinstancelistnpndarraypdSeriesr>   )r   r=   rB   rC   s   ` ``r   __call__zSemanticMapping.__call__P   se    cD"*bi899 	=IIIIIISIIII&4&s<T<<<V<<<r   )__name__
__module____qualname____doc__r   __annotations__r5   r<   r   r9   r>   rJ   r$   r   r   r   r      sy         @@
  H F L    0& & &= = = = =r   r   c                  J     e Zd ZdZdZdZdZ	 d	 fd	Zd Zd Z	d Z
d Z xZS )

HueMappingz9Mapping that sets artist colors according to data values.N   c                   t                                          |           |j                            dt	          j        t                              }t          |t          j	                  r,d}t          j        |d           |                                }|                                                                r|d}t          j        |d           dS dS |                     |||j        |j        d                   }|dk    r1t	          j        |          }|                     |||          \  }	}
}}nP|d	k    rdx}}|                     |||          \  }	}
n+dx}}|                     t+          |          ||          \  }	}
|| _        || _        |
| _        || _        |	| _        || _        || _        dS )
zMap the levels of the `hue` variable to distinct colors.

        Parameters
        ----------
        # TODO add generic parameters

        huedtypez|Numpy array is not a supported type for `palette`. Please convert your palette to a list. This will become an error in v0.14   r+   Nz?Ignoring `palette` because no `hue` variable has been assigned.numericcategorical)superr   	plot_datagetrH   rI   floatrD   rF   rG   r2   r3   tolistisnaallinfer_map_typeinput_format	var_types
to_numericnumeric_mappingcategorical_mappingrE   
saturationr   r<   paletter5   normcmap)r   r   rh   orderri   rg   datamsgr   r5   r<   rj   	__class__s               r   r   zHueMapping.__init__c   s    	!!! $$UBIE,B,B,BCCgrz** 	'5 
 M#!,,,,nn&&G99;;?? 1	"Wca000000 #"
 **w3W5Fu5M H 9$$}T**373G3G'44 40dDD ]**""t'+'?'?'5( ($ #"t'+'?'? JJ( ($ )DO$DM ,D"DL DKDIDIIIr   c                   	 | j         |         }n# t          $ r | j        Y dS 	 |                     |          }t          j                            |          rt          j        }|                     |          }n0# t          $ r#}t          j	        |          rd}n|Y d}~nd}~ww xY wY nw xY w| j
        dk     rt          || j
                  }|S )z@Get the color for a single value, using colormap to interpolate.N)r   r   r   r   rR   )r<   KeyErrorri   rF   ma	is_maskednanrj   	TypeErrorisnanrg   r   )r   r=   valuenormederrs        r   r>   zHueMapping._lookup_single   s    	*%c*EE 	* 	* 	*y  $||
*3 5??6** $VF		&))    8C== (EEI EEEE	*, ?Qudo66Es8    B.A;AB.;
B(B#B.#B((B.-B.c                |    |t           v rd}n/|d}n*t          |t          t          f          rd}n|dk    rd}n|}|S )z'Determine how to implement the mapping.rY   NrX   wide)r   rD   dictrE   )r   rh   ri   rb   var_typer   s         r   ra   zHueMapping.infer_map_type   sZ    m##$HH HH$.. 	 $HHV##$HHHr   c                V   t          ||          }t          |          }t          |t                    rUt	          |          t	          |          z
  }t          |          r$d}t          |                    |                    |}n|A|t          t                                k    rt          d|          }	nNt          d|          }	n=t          |t                    r|                     ||d          }	nt          ||          }	t          t          ||	                    }||fS )z5Determine colors when the hue mapping is categorical.z*The palette dictionary is missing keys: {}Nhuslrh   )categorical_orderr-   rD   r{   setany
ValueErrorformatr   r   rE   r9   r/   )
r   rl   rh   rk   r5   n_colorsmissingrx   r<   colorss
             r   rf   zHueMapping.categorical_mapping   s    #4//v;; gt$$ 	5&kkCLL0G7|| 6B G!4!4555"LL s?#4#45555*4::FF*68<<FFGT** :00)LL&w99FF 3 344L|##r   c           
        t          t                    rlt          t                              }fdt                    D             }t          j                            |          }                                }net          t          j	        t          |                                                              }dnt          t          j        j                  r}nt          d          }|t          j                                        }nYt          |t                    rt	          j        j        | }n0t          |t          j        j                  sd}t!          |          |                                s/ |t          j        |                                                     t          t)          | | ||                                        }||||fS )z7Determine colors when the hue variable is quantitative.c                     g | ]
}|         S r$   r$   )r%   rA   rh   s     r   r(   z.HueMapping.numeric_mapping.<locals>.<listcomp>  s    :::Qgaj:::r   Nzch:T)as_cmapz6``hue_norm`` must be None, tuple, or Normalize object.)rD   r{   rE   sortedmplr   ListedColormapr   rF   sortr   uniqueColormapr   	Normalizetupler   scaledasarraydropnar/   )	r   rl   rh   ri   r5   r   rj   r<   rx   s	     `      r   re   zHueMapping.numeric_mapping   s   gt$$ %	A &//**F::::&//:::F:,,V44D"<<>>LL
 "')DKKMM":":;;<<F  'eeGG'3:#677 <$Wd;;; |z++--D%(( &z+T2cj&:;; &N oo%;;== 0RZ..///FDDf,>,> ? ?@@L|T4//r   NNNrR   )rK   rL   rM   rN   rh   ri   rj   r   r>   ra   rf   re   __classcell__rn   s   @r   rQ   rQ   X   s        CCG D D HIH H H H H HT  @   $  $  $D)0 )0 )0 )0 )0 )0 )0r   rQ   c                  B     e Zd ZdZdZ	 d fd	Zd Zd Zd Zd Z	 xZ
S )	SizeMappingz8Mapping that sets artist sizes according to data values.Nc                v   t                                          |           |j                            dt	          j        t                              }|                                                                r| 	                    |||j
        d                   }|dk    r|                     |||          \  }}}}	nL|dk    r|                     |||          \  }}d}	n)|                     t          |          ||          \  }}d}	|| _        || _        || _        || _        |	| _        || _        dS dS )zMap the levels of the `size` variable to distinct values.

        Parameters
        ----------
        # TODO add generic parameters

        sizerU   rX   rY   N)rZ   r   r[   r\   rH   rI   r]   notnar   ra   rc   re   rf   rE   r   r5   ri   sizes
size_ranger<   )r   r   r   rk   ri   rl   r   r5   r<   r   rn   s             r   r   zSizeMapping.__init__/  s[    	!!! $$VRYU-C-C-CDD::<< (	-**eW.v6 H 9$$9=9M9M%: :6dJJ ]**'+'?'?%( ($ "

 (,'?'? JJu( ($
 "
$DM DKDIDJ(DO ,DQ(	- (	-r   c                R    |d}n!t          |t          t          f          rd}n|}|S )NrX   rY   )rD   r{   rE   )r   ri   r   r|   r   s        r   ra   zSizeMapping.infer_map_typeg  s6     HHd|,, 	 $HHHr   c                   	 | j         |         }nz# t          $ rm |                     |          }t          j                            |          rt          j        }| j        d         |t          j        | j                  z  z   }Y nw xY w|S )Nr   )	r<   rp   ri   rF   rq   rr   rs   r   ptp)r   r=   rv   rw   s       r   r>   zSizeMapping._lookup_singler  s    	J%c*EE 	J 	J 	JYYs^^Fuv&&  OA&"&2I2I)IIEEE		J
 s    A4BBc                   t          ||          }t          |t                    rWt          |          t          |          z
  }t	          |          rd| }t          |          |                                }nt          |t                    r5|                     ||d          }t          t          ||                    }nt          |t                    r%t          |          dk    rd}t          |          n"|d| }t          |          | j        j        }t          j        g |t          |          R  d d d         }t          t          ||                    }||fS )Nz(Missing sizes for the following levels: r      'A `sizes` tuple must have only 2 values"Value for `sizes` not understood: )r   rD   r{   r   r   r   r   rE   r9   r/   r   r-   r   _default_size_rangerF   linspace)r   rl   r   rk   r5   r   rx   r<   s           r   rf   zSizeMapping.categorical_mapping}  sl   "4//eT"" 2	4 &kkCJJ.G7|| &JJJ oo% ::<<LLt$$ )	4 ++FE7CCEFE 2 233LL %'' 9 u::??CC$S//) # "B5BB oo% 8 K44F444TTrT:EFE 2 233L|##r   c                :   t          |t                    rat          t          j        t          |                              }|                                }t          |          t          |          f}nt          t          j        t          |	                                                              }t          |t                    r't          |          dk    rd}t          |          |}n"|d| }t          |          | j        j        }|t          j                                        }nkt          |t                    rt          j        j        | }nBt          |t          j        j                  sd| }t          |          t%          |          }d|_        |                                s ||            ||          }t          |t                    r|}	n-|\  }
}|
|||
z
  z  z   }t          t+          ||                    }	||	||fS )Nr   r   r   z0Value for size `norm` parameter not understood: T)rD   r{   rE   rF   r   r6   minmaxr   r   r   r-   r   r   r   r   r   r   r   clipr   r/   )r   rl   r   ri   r5   size_valuesr   rx   sizes_scaledr<   lohis               r   re   zSizeMapping.numeric_mapping  s   eT"" $	> "'$u++..//F,,..K[))3{+;+;;JJ
 "')DKKMM":":;;<<F%'' > u::??CC$S//)"

"B5BB oo% "\=
 <:''))DDe$$ 	:'.DDD#*"677 	KTKKCS//! ::D 	 {{}} 	DLLL tF|| eT"" 	4 LLFBb11EFE 2 233L|T:55r   NNN)rK   rL   rM   rN   ri   r   ra   r>   rf   re   r   r   s   @r   r   r   *  s        BBD 596- 6- 6- 6- 6- 6-p	 	 		 	 	8$ 8$ 8$tM6 M6 M6 M6 M6 M6 M6r   r   c                  6     e Zd ZdZdZd fd	ZddZd Z xZS )	StyleMappingz8Mapping that sets artist style according to data values.rY   Nc           	        t                                          |           |j                            dt	          j        t                              }|                                                                rt          |          dk    rt          |          }t          ||          }|                     ||t          t          |                    d          }|                     ||t          t          |                    d          }i }g }|                                D ]\  }	}
t#          |
t$          j        j                  st$          j                            |
          }
|
                                                    |
                                          ||	<   |                    |
                                           t          |          r t5          |          sd}t7          |          i }|D ]>}i ||<   |r"||         ||         d<   ||         ||         d<   |r||         ||         d<   ?|| _        || _        d	S d	S )
zMap the levels of the `style` variable to distinct values.

        Parameters
        ----------
        # TODO add generic parameters

        stylerU   r   markersdashesz+Filled and line art markers cannot be mixedmarkerpathN)rZ   r   r[   r\   rH   rI   r]   r   r   variable_typerE   r   _map_attributesunique_markersr-   unique_dashesitemsrD   r   r   MarkerStyleget_pathtransformedget_transformappend	is_filledr`   r   r5   r<   )r   r   r   r   rk   rl   r5   pathsfilled_markersrA   mrx   r<   r=   rn   s                 r   r   zStyleMapping.__init__  s>    	!!! $$Wbie.D.D.DEE::<< ,	- T""j00Dzz 'tU33F**F!<!<i G ))c&kk : :H F
 EN 5 51!!S[%<== 3//22A::<<33AOO4E4EFFa%%akkmm4444 >"" &3~+>+> &C oo%L > >$&S! ;29#,L%h/05c
L%f- >28+L%h/ DK ,DY,	- ,	-r   c                L    || j         |         }n| j         |         |         }|S )z(Get attribute(s) for a given data point.r;   )r   r=   attrrv   s       r   r>   zStyleMapping._lookup_singleG  s-    <%c*EE%c*40Er   c                   |du rt          t          ||                    }nt          |t                     r;t          |          t          |          z
  }|rd| d| }t	          |          |}net          |t
                    r5|                     |||          }t          t          ||                    }n|rd| d| }t	          |          i }|S )z5Handle the specification for a given style attribute.TzThese `z` levels are missing values: zThis `z` argument was not understood: )r{   r/   rD   r   r   r   r9   )r   argr5   defaultsr   r<   r   rx   s           r   r   zStyleMapping._map_attributesO  s    $;;FH 5 566LLT"" 	&kkCHH,G &LLL7LL oo%LLX&& 	))&#t<<CFC 0 011LL 	E4EEEECS//!Lr   r   r   )	rK   rL   rM   rN   r   r   r>   r   r   r   s   @r   r   r     sn        BB H8- 8- 8- 8- 8- 8-t         r   r   c                  
   e Zd ZdZdddddZdddZdZdi fd	Zed
             Z	ed             Z
di fdZd"dZd#dZd$dZd$dZ	 d"dddddddZed             Zd Z	 	 d%dZd Zd&dZ	 d$dZd Zd Zd Zd  Zd%d!ZdS )'VectorPlotterz2Base class for objects underlying *plot functions.@index@values@columns)r'   yrT   r   r'   r   )rR   r   Nc                    i | _         ddd| _        |                     ||           dD ]!}||v r t          | d|                        "d S )NFr   rT   r   r   map_)_var_levels_var_orderedassign_variablesgetattr)r   rl   	variablesvars       r   r   zVectorPlotter.__init__r  sw    
 #(e44dI...
 , 	. 	.Ci+lSll++---	. 	.r   c                N    t          ddht          | j                  z            S )z.Return True at least one of x or y is defined.r'   r   )boolr   r   )r   s    r   has_xy_datazVectorPlotter.has_xy_data  s%     S#JT^!4!44555r   c                p    | j         D ](}t          | d| dd          x}|j        | j        |<   )| j        S )a4  Property interface to ordered list of variables levels.

        Each time it's accessed, it updates the var_levels dictionary with the
        list of levels in the current semantic mappers. But it also allows the
        dictionary to persist, so it can be used to set levels by a key. This is
        used to track the list of col/row levels using an attached FacetGrid
        object, but it's kind of messy and ideally fixed by improving the
        faceting logic so it interfaces better with the modern approach to
        tracking plot variables.

        r&   _mapN)r   r   r5   r   )r   r   map_objs      r   
var_levelszVectorPlotter.var_levels  sM     > 	7 	7C"4S===J(/ %r   c                &   |                     dd          }|                     dd          }||d| _         | j        |fi |\  }n%d| _        t          ||          }|j        |j        }| _        || _        fd|D             | _        | S )z;Define plot variables, optionally using lookup from `data`.r'   Nr   rz   longc                L    i | ] }|t          |         |d v rdnd          !S )xyrX   rY   )boolean_typer   )r%   vframes     r   
<dictcomp>z2VectorPlotter.assign_variables.<locals>.<dictcomp>  sR     
 
 

 	 }a*+t))YY  
 
 
r   )	r\   rb   _assign_variables_wideformr   r   namesr[   r   rc   )r   rl   r   r'   r   r   r[   r   s          @r   r   zVectorPlotter.assign_variables  s    MM#t$$MM#t$$9 &D:4:4MM9MMLE55
 !'D y11IOEOE
 
 
 

 
 
 
 r   c                   d |                                 D             }t          |          rNt          |          dk    rdnd}d| d}|d                    d |D                       z  }t	          |          |d	u pt          |           }t          |t                    r|                                }n-t          j	        t          j
        |t          
                    }t          d |D                        }|rt          j                    }	i }
n|rt          j        |                                          }|j        |j        j        d}i }	i }
dD ]I}|| j        v r>| j        |         }t'          ||dd	                   |	|<   || j        |                  |
|<   Jt          j        |	          }	nt          |t(                    rAi }t+          |          D ]-\  }}t'          |d|          }t          j        |          ||<   .|}t          |t,                    rd |                                 D             }t          j        |d          }d |                                 D             }||         }ddd}d| j                                        v }|rnd|d<   	 |j        j        }|j        j        }|j                            d          |_        d}n# t8          $ r d}Y nw xY w|j                                        |d<    |j        di |}	|r!|rt          j        |	d         ||          |	d<   | j                                         D ]\  }}|	|         |	|<   i }
| j                                         D ]1\  }}t'          ||dd	                   }t'          |dd	          |
|<   2|	tA          |
                   }	|	|
fS )a5  Define plot variables given wide-form data.

        Parameters
        ----------
        data : flat vector or collection of vectors
            Data can be a vector or mapping that is coerceable to a Series
            or a sequence- or mapping-based collection of such vectors, or a
            rectangular numpy array, or a Pandas DataFrame.
        kwargs : variable -> data mappings
            Behavior with keyword arguments is currently undefined.

        Returns
        -------
        plot_data : :class:`pandas.DataFrame`
            Long-form data object mapping seaborn variables (x, y, hue, ...)
            to data vectors.
        variables : dict
            Keys are defined seaborn variables; values are names inferred from
            the inputs (or None when no name can be determined).

        c                    g | ]	\  }}||
S r   r$   r%   rA   r   s      r   r(   z<VectorPlotter._assign_variables_wideform.<locals>.<listcomp>  s    BBB$!QAMAMMMr   rR   sr    zThe following variablez) cannot be assigned with wide-form data: z, c              3  "   K   | ]
}d | d V  dS )`Nr$   r%   r   s     r   	<genexpr>z;VectorPlotter._assign_variables_wideform.<locals>.<genexpr>  s*      88!XXXX888888r   NrU   c              3  z   K   | ]6}t          |t                    ot          |t          t          f           V  7d S r   )rD   r   strbytesr   s     r   r   z;VectorPlotter._assign_variables_wideform.<locals>.<genexpr>  sV       
 
 q(##GJq3,,G,G(G
 
 
 
 
 
r   )r   r   r   namec                >    i | ]\  }}|t          j        |          S r$   )rH   rI   )r%   r=   vals      r   r   z<VectorPlotter._assign_variables_wideform.<locals>.<dictcomp>  s&    IIISRYs^^IIIr   Tr   c                >    g | ]\  }}t          |          d k    |S rX   r   r   s      r   r(   z<VectorPlotter._assign_variables_wideform.<locals>.<listcomp>  s5       a=3C3Cy3P3P3P3P3Pr   r   r   )var_name
value_namer   id_varsFr$   )!r   r   r-   r.   r   rD   r{   r6   rF   
atleast_1dr   objectrH   	DataFramerI   r   r   indexflat_structurer   r   	enumerater	   wide_structurecolumns
categoriesorderedadd_categoriesAttributeError	to_seriesmeltCategoricalrE   )r   rl   rC   assignedr   rx   emptyr6   flatr[   r   	flat_datar   r   r   	data_dictir=   	wide_datanumeric_colsmelt_kws	use_indexorig_categoriesorig_orderedcategory_columnsobjs                             r   r   z(VectorPlotter._assign_variables_wideform  sr   . CB&,,..BBBx== 	"8}}q((bAW1WWWC49988x888888CS//! -CII dD!! 	C[[]]FF]2:d&#A#A#ABBF 
 

 
 
 
 
 

  _	3 III Y	3
 	$,,..I$>#/. E
 II! E E$---.s3D%,YQRR%A%AIcN%*4+>s+C%DIcNY//II $)) !	'oo 4 4FAs!#vq11C &(Ys^^IcNN  $(( JIIDJJLLIII T555I 'oo//  L ",/I %/iHHH D$7$>$>$@$@@I 
B&.#,&/&7&BO#,#4#<L(1(9(H(H(R(RI% (,$$ & - - -',$$$- '0o&?&?&A&A	(#&	2222I E- E(*y7L7F7C)E )E	*%
 "06688 1 1	T!*4	# I!06688 < <	Tiabb22!(fd!;!;	# "$y//2I)##s   )7K# #K21K2rR   c                :    t          | ||||          }|| _        d S r   )rQ   _hue_map)r   rh   rk   ri   rg   mappings         r   map_huezVectorPlotter.map_hueE  s"    T7E4DDr   c                8    t          | |||          }|| _        d S r   )r   	_size_map)r   r   rk   ri   r!  s        r   map_sizezVectorPlotter.map_sizeI  s     dE5$77 r   c                8    t          | |||          }|| _        d S r   )r   
_style_map)r   r   r   rk   r!  s        r   	map_stylezVectorPlotter.map_styleM  s     tWfe<<!r   FT)reversefrom_comp_databy_facetallow_emptyr   c             #     K   |g }n=t          |t                    r|g}n$t          |t                    rt          |          }|r>ddh}|                    |t           j                  t          |          z
  z              fd|D             }|r j        }n j        }|r|	                                } j
                                        }	|rddht          |          z  D ]}
 j        |
         j        d         } j        |
         dk    r\ j        |
         r|                    |	|
                   |	|
<   Wt#          j        ||
                                                   |	|
<   |                                j        } ||                    |	|
                             |	|
<   |r&|                    |d	d	d	
          }g }|D ]0}|	                    |          }|                    |g n|           1t3          j        | }|rt7          t          |                    }|D ]}t9          |          dk    rt;          t<          d          r|d         n|}	 |                    |          }n# t@          $ r |j!        g          }Y nw xY w|j"        r|srtG          tI          ||                    }||                                fV  dS i |                                fV  dS )a  Generator for getting subsets of data defined by semantic variables.

        Also injects "col" and "row" into grouping semantics.

        Parameters
        ----------
        grouping_vars : string or list of strings
            Semantic variables that define the subsets of data.
        reverse : bool
            If True, reverse the order of iteration.
        from_comp_data : bool
            If True, use self.comp_data rather than self.plot_data
        by_facet : bool
            If True, add faceting variables to the set of grouping variables.
        allow_empty : bool
            If True, yield an empty dataframe when no observations exist for
            combinations of grouping variables.
        dropna : bool
            If True, remove rows with missing data.

        Yields
        ------
        sub_vars : dict
            Keys are semantic names, values are the level of that semantic.
        sub_data : :class:`pandas.DataFrame`
            Subset of ``plot_data`` for this combination of semantic values.

        Ncolrowc                &    g | ]}|j         v |S r$   )r   )r%   r   r   s     r   r(   z+VectorPlotter.iter_data.<locals>.<listcomp>  s%    OOO9N9N9N9N9Nr   r'   r   r   rY   F)r   as_indexobservedrR   z2.2.0)%rD   r   r   rE   extendr   r   	comp_datar[   r   r   r   
convertersilocrc   r   convert_unitsrF   r   r   r   	transformgroupbyr\   r   r0   productreversedr-   r   rH   	get_grouprp   locr  r{   r/   )r   grouping_varsr)  r*  r+  r,  r   
facet_varsrl   r5   axis	converterr8  grouped_datagrouping_keysr   r=   	iter_keyspd_keydata_subsetsub_varss   `                    r   	iter_datazVectorPlotter.iter_dataQ  sn     F  MMs++ 	0*OMMu-- 	0 //M  	J  S003}3E3EEE  
 POOOOOO 	">DD>D 	!;;==D%%'' 	Tc
S%7%77 T T OD16q9	>$'=88(. 	D
 (1'>'>vd|'L'Lt (*wtDz/@/@/B/B'C'Ct ) 7 7 9 9 CI#,9Y-D-DVD\-R-R#S#SF4LL &	"<<EEE (  L M$ A Ajjoo$$3;RRC@@@@!)=9I 6$T)__55	  3 3 "#hh!mm0A"g0N0NmCFFTW /"."8"8"@"@KK / / /
 #'(2,KKK/ $ [ M3 7 788 0 0 2 222222'3 3. diikk/!!!!!s   &I<<JJc           	     >   t          | d          s| j        S t          | d          s| j                            d                              ddgdd	          }d
D ]}|| j        vrg }| j        |                             | j        |         d          }|D ](\  }}|                    |                    t          j
        t          j
         g          t          j                  }|                                }|| j        v r&||                    | j        |                            }t          j        |                    |                                        t$                    }|                                j        }|                    t          j         ||          |j        |j                             *|rt          j        |          }	nt          j        t$          |          }	|                    d||	           || _        | j        S )zFDataframe with numeric x and y, after unit conversion and log scaling.ax
_comp_dataF)deepr'   r   rR   ignore)r@  errorsyxr   r   )rV   r   r   )hasattrr[   r   dropr   r9  r5  maskisinrF   infrs   r   r   rH   rd   r7  astyper]   r   r8  r   rI   r  r   concatinsertrK  )
r   r4  r   partsgroupedrA  origcompr8  comp_cols
             r   r4  zVectorPlotter.comp_data  s    tT"" 	"
 >!t\** 	( 5!!sCjq::   3 3dn,,.-55doc6JQV5WW'. 
Y 
YOIt99TYY/@%A%A26JJD;;==Ddo--  $DIIdoc.B$C$CD=)@)@)F)FGGNNuUUD ) 7 7 9 9 CILL99T??DJTY!W!W!WXXXX @!y//HH!yu3???H  C2222'DOr   c                   |                     dd          }|                     dd          }||| j        j        ||f         S || j        j        |         S || j        j        |         S | j        | j        j        S | j        S )z>Return an Axes object based on existence of row/col variables.r/  Nr.  )r\   facets	axes_dictrJ  )r   rG  r/  r.  s       r   	_get_axeszVectorPlotter._get_axes  s    ll5$''ll5$''?s;(#s44_;(--_;(--W_;>!7Nr   c                   ddl m} t          ||          rTd| _        || _        |j                                        }|j        |j        | j        d<   |j	        |j	        | j        d<   n|| _        d| _        |g}t          d                              | j                  }|g d}nt          |t                    r|g}|D ].}| j        |         }||vrd| d	| d
| d}	t          |	          /ddd}
i | _        |D ]}ddd|         }t#          j        | j        j        |t*                    }t-          | j        d| d          }|du s||
|         k    r$t-          |d         | d          |j        dd<   n|du rP|                                 D ]:\  }}|                     |          }t-          || d          |j        |j        <   ;nwt-          | j        | d          }t5          |          D ]O\  }}|dk    r|dfnd|f}t-          | j        j        |         | d          }||j        | j        |         |k    <   P|| j        |<   | j        |                             | j        |         d          }|D ]X\  }}| j        |         dk    r-| j        |         r| j        |         }nd}t;          ||          }|                    |           Y|dx}}n[	 |\  }}nT# t          $ rG | j                            d          dk    r|nd}| j                            d          dk    r|nd}Y nw xY wtA          d||f          D ]@\  }}|r9|D ]6}t-          |d| d          }|du r |dd           ( |d|d           7A| j                            dd          dk    r|D ]}|j!        "                    d           dS dS )a  Associate the plotter with an Axes manager and initialize its units.

        Parameters
        ----------
        obj : :class:`matplotlib.axes.Axes` or :class:'FacetGrid`
            Structural object that we will eventually plot onto.
        allowed_types : str or list of str
            If provided, raise when either the x or y variable does not have
            one of the declared seaborn types.
        log_scale : bool, number, or pair of bools or numbers
            If not False, set the axes to use log scaling, with the given
            base or defaulting to 10. If a tuple, interpreted as separate
            arguments for the x and y axes.

        rR   )	FacetGridNr.  r/  r   rX   r   rY   r)   z variable is z, but one of z is requiredr   r   r'   )r  r   rV   _shareTr   r@  F_namesrP  rY   rX   set_scalelogrT  )nonpositive)baserk  )#axisgridrd  rD   rJ  r`  axesflatten	col_namesr   	row_namesr   intersectionr   r   rc   rt   r5  rH   rI   r[   r  r  r   r=  rH  rb  r  r9  r   r   update_unitsr\   r/   yaxisset_inverted)r   r  allowed_types	log_scalerd  ax_listaxis_variablesr   r|   rx   	facet_dim	other_varrA  share_state	axes_vars	axes_datarJ  r   r  levelidxr@  r[  	seed_datark   scalexscaleyri  	set_scales                                r   _attachzVectorPlotter._attach  s   * 	('''''c9%% 	DGDKh&&((G}(),&}(),&DGDKeG T//??  BBBMMs++ 	,*OM! 	% 	%C~c*H},,33 3 3X 3 3$3 3 3   nn$ -  e,,	! ,	2 ,	2C!,,S1I	(<3fUUUI!$+~~~tDDK
 d""kYy5I&I&I#*71:#|||#D#D	aaa   %''040@0@ S S,	9!^^I669@\\\9R9R	io66S $DKK1G1G1GHHE$-e$4$4 S S5(3u(<(<q!ff1a&&t{'7'<lllKKNR	dn[&AU&JKK $-DOC  nS)11$/#2FU1SSG(/ 2 2$	9>#&-77(- % $ 4 $ 1)U C CI&&y11112 ##FVVV!* V V V&*n&8&8&=&=&J&JPU&*n&8&8&=&=&J&JPUV
 tff%566 	I 	IKD% I! I IB ',>4,>,>,> ? ?I}}!	%V<<<<<!	%eHHHHH >c4((M99 , ,%%d++++ :9, ,s   )K/ /AM ?M c                v   | j         hfd| j        j        j        D             }d |D             }t	          |          dk    rd}t          |          |d                                         }n*t          | j          d                                          }|j        |	                                j        fS )zDReturn a function implementing the scale transform (or its inverse).Nc                6    g | ]}t          | d           S )r@  )r   )r%   rJ  r@  s     r   r(   z7VectorPlotter._get_scale_transforms.<locals>.<listcomp>  s)    TTT]]]33TTTr   c                6    h | ]}|                                 S r$   )	get_scale)r%   r@  s     r   	<setcomp>z6VectorPlotter._get_scale_transforms.<locals>.<setcomp>  s"    ===4dnn&&===r   rR   z=Cannot determine transform with mixed scales on faceted axes.r   r@  )
rJ  r`  rn  r  r-   RuntimeErrorr   r   r8  inverted)r   r@  	axis_listscalesrx   transform_objs    `    r   _get_scale_transformsz#VectorPlotter._get_scale_transforms  s    7?TTTTdk>N>STTTI==9===F6{{Q V"3'''%aL6688MM $DG]]];;IIKKM&(>(>(@(@(JJJr   r    c                   |                                 s[t          d |                                D                       }|                    | j                            d|          |           |                                s]t          d |                                D                       }|                    | j                            d|          |           dS dS )zCAdd axis labels if not present, set visibility to match ticklabels.c              3  >   K   | ]}|                                 V  d S r   get_visibler%   ts     r   r   z1VectorPlotter._add_axis_labels.<locals>.<genexpr>  *      JJAMMOOJJJJJJr   r'   )visiblec              3  >   K   | ]}|                                 V  d S r   r  r  s     r   r   z1VectorPlotter._add_axis_labels.<locals>.<genexpr>  r  r   r   N)	
get_xlabelr   get_xticklabels
set_xlabelr   r\   
get_ylabelget_yticklabels
set_ylabel)r   rJ  	default_x	default_y	x_visible	y_visibles         r   _add_axis_labelszVectorPlotter._add_axis_labels  s     }} 	QJJR5G5G5I5IJJJJJIMM$.,,S)<<iMPPP}} 	QJJR5G5G5I5IJJJJJIMM$.,,S)<<iMPPPPP	Q 	Qr   c                R     j         }t          |t                    r|dvrd}t          |          |du rd}g i |i n|                                }|i n|                                }d  fddD             D             }t          |          d	k    rd
n|                                }	t          ddddd
d
          }
fd}|dddgdd}|                                D ]3\  }} 	                    ||||	|
||
                    |                     4i }g }|
                    dd          |                    d           D ]B}|\  }}|         }i }g  j        |d |                                D             }|D ]}||v r||         ||<    |dd|iddi||}t          t          d          rt          |t          j        j                  r|                    |           nt          |t          j        j                  r|                    |           nJt          |t          j        j                  r|                    |           n|                    |           |||<   |                    |           D|	 _        | _        | _        dS )z>Add labeled artists to represent the different plot semantics.)autobrieffullz7`legend` must be 'auto', 'brief', 'full', or a boolean.Tr  Nc                    h | ]}||S r   r$   )r%   titles     r   r  z0VectorPlotter.add_legend_data.<locals>.<setcomp>  s(     
 
 
     r   c              3  N   K   | ]}j                             |d           V   d S r   )r   r\   )r%   r   r   s     r   r   z0VectorPlotter.add_legend_data.<locals>.<genexpr>  s5      KKQT^4((KKKKKKr   r   rR   r    Fwr   )r  colorr   	linewidthr   r   c                    | |f}|v r |         j         di | d S                     |           t          di ||<   d S )Nr$   )updater   r{   )r   val_namekwsr=   keys
legend_kwss       r   r  z-VectorPlotter.add_legend_data.<locals>.update  sd    H$Cj  &
3&-------C   "&++++
3r   r  r  r   c                    g | ]	}|D ]}|
S r$   r$   )r%   	var_attrsr   s      r   r(   z1VectorPlotter.add_legend_data.<locals>.<listcomp>  s%    TTT9)TT$$TTTTr   labelz.2z3.5.0r$   )legendrD   r   r   r   r-   popr{   r   _update_legend_datar\   _legend_attributesr6   r   r   linesLine2Dadd_linepatchesPatch	add_patchcollections
Collectionadd_collection
add_artistr   legend_titlelegend_datalegend_order)r   rJ  func
common_kwsattrssemantic_kws	verbosityrx   titlesr  	title_kwsr  r   r   r  r  r=   r&   r  r  	level_kws	use_attrsr   artistr  r  s   `                       @@r   add_legend_datazVectorPlotter.add_legend_data  s_    K	i%% 	);T*T*TKCS//!$I
%-RR:??3D3D
)1rr|7H7H7J7J

 
KKKK2JKKK
 
 

 &kkQ&&FJJLLQr"
 
 
		. 	. 	. 	. 	. 	. =#k3-?$OOE++-- 	 	JC$$Yy%AQAQRUAVAV     >>'5))1NN7### 	% 	%CHAuS/CI( UT(;(;(=(=TTTI
 " 0 03;;&)$iIdOTTTT'4)S:)S)STTF g.. &fci&677 .KK''''(9:: .LL(((((BCC .%%f---f%%%%K$$$$!&(r   c                   d}t          | d| dd          }	|	dS |	j        dk    o#|dk    p|dk    ot          |	j                  |k    }
|
rt	          |	j        t          j        j                  r!t          j	        
                    |          }n t          j	                            |	          }t          |	j                  t          |	j                  f}t          ||| j        |                                         j                  \  }}n|	j        g x}}n	|	j        x}}|s=| j                            |d          " || j        |         d
f| j        |         fi | |i n|}t)          ||          D ]\  }} |	          t	          |t*                    rfd|D             n||i                    fd|                                D                         || j        |         |fi  dS )z1Generate legend tick values and formatted labels.r*   r&   r   NrX   r  r  )numticks)nbinsr  c                    i | ]}|S r$   r$   )r%   r   r   s     r   r   z5VectorPlotter._update_legend_data.<locals>.<dictcomp>/  s    >>>4D$>>>r   c                0    i | ]\  }}|v 	||         S r$   r$   )r%   rA   r   r  s      r   r   z5VectorPlotter._update_legend_data.<locals>.<dictcomp>2  s)    WWWTQEUVJJQ%JJJr   )r   r   r-   r5   rD   ri   r   r   LogNormticker
LogLocatorMaxNLocatorr   r   r   r[   infer_objectsrV   r   r\   r/   rE   r  r   )r   r  r   r  r  r  
attr_namesother_propsbrief_ticksmapperr  locatorlimitsr5   formatted_levelsformatted_levelr   r  s                   @@r   r  z!VectorPlotter._update_legend_data  sg    }3}}}d33>F9, 
  JV#HFM(:(:[(H 	  	6&+sz'9:: D*///EE*00{0CC''V]););;F'@!4!B!B!D!D!J( ($F$$ ]"(**F%%(.5F% 	U++C66BFDN3'14>#3FTT)TTT'/bb[&)&2B&C&C 	E 	E"E? ve}}j$// .>>>>:>>>DD+&-DWWWW[5F5F5H5HWWWXXXt~c*ODDtDDD	E 	Er   c                    t           r   NotImplementedErrorr   r@  rB   rC   s       r   scale_nativezVectorPlotter.scale_native:  s
     "!r   c                    t           r   r  r  s       r   scale_numericzVectorPlotter.scale_numeric@  
    
 "!r   c                    t           r   r  r  s       r   scale_datetimezVectorPlotter.scale_datetimeG  r  r   c                   t          dddg|           || j        vrd| j        |<   d| j        |<   d| j        |<   | j        |         dk    r!| j                            |d	          | _        | j        |                                         }|dup|j        j        d
k    | j        |<   t          j
        t          ||          |          }|+|                    |          }|                    |          }n4|                    t                    }|                    t                    }|| j        |<   d| j        |<   || j        |<   | S )a  
        Enforce categorical (fixed-scale) rules for the data on given axis.

        Parameters
        ----------
        axis : "x" or "y"
            Axis of the plot to operate on.
        order : list
            Order that unique values should appear in.
        formatter : callable
            Function mapping values to a string representation.

        Returns
        -------
        self

        r@  r'   r   NrY   r    rX   	mergesort)kindcategoryrQ  )r   r   rc   r[   sort_valuesr   rV   r   r   rH   Indexr   maprW  r   r   )r   r@  rk   	formattercat_datas        r   scale_categoricalzVectorPlotter.scale_categoricalN  sW   T 	c
D111 t~%%#'DN4 #0DN4 #%DN4  >$9,,!^77;7OODN >$'..00 #(t"3"Xx~7Jj7X$*8U;;$GGG  ||I..HIIi((EEs++HLL%%E !&  -t  (tr   r   r   r   )NN)r    r    )rK   rL   rM   rN   r  r  r   r   propertyr   r   r   r   r"  r%  r(  rH  r4  rb  r  r  r  r  r  r  r  r  r  r$   r   r   r   r   h  s+       << Ij: N $)44N B . . . ." 6 6 X6     X " %)B    :L$ L$ L$ L$\       ! ! ! !" " " "
 !u"e5u" u" u" u" u"n * * X*X  $ 	G, G, G, G,VK K K,Q Q Q Q CGP) P) P) P)d/E /E /El" " "" " "" " "[ [ [ [ [ [r   r   c                  ,     e Zd ZdZdZ fdZd Z xZS )VariableTypez
    Prevent comparisons elsewhere in the library from using the wrong name.

    Errors are simple assertions because users should not be able to trigger
    them. If that changes, they should be more verbose.

    re  c                p    || j         v s
J |            t                                          |           d S r   )allowedrZ   r   )r   rl   rn   s     r   r   zVariableType.__init__  s<    t|###T###r   c                >    || j         v s
J |            | j        |k    S r   )r  rl   )r   others     r   __eq__zVariableType.__eq__  s*    $$$e$$$yE!!r   )rK   rL   rM   rN   r  r   r  r   r   s   @r   r  r    sX          3G    " " " " " " "r   r  rX   c                   t          j        |           } t          | j        t           j                  rt          d          S t          j        |                                           rt          d          S |                                 } t          j
                    5  t          j        dt          t          f           	 t          j        | ddg                                          rt          |          cddd           S n# t           $ r Y nw xY wddd           n# 1 swxY w Y   t           j        j                            |           rt          d          S t           j        j                            |           rt          d          S d	 } ||           rt          d          S d
 } ||           rt          d          S t          d          S )a+  
    Determine whether a vector contains numeric, categorical, or datetime data.

    This function differs from the pandas typing API in two ways:

    - Python sequences or object-typed PyData objects are considered numeric if
      all of their entries are numeric.
    - String or mixed-type data are considered categorical even if not
      explicitly represented as a :class:`pandas.api.types.CategoricalDtype`.

    Parameters
    ----------
    vector : :func:`pandas.Series`, :func:`numpy.ndarray`, or Python sequence
        Input data to test.
    boolean_type : 'numeric' or 'categorical'
        Type to use for vectors containing only 0s and 1s (and NAs).

    Returns
    -------
    var_type : 'numeric', 'categorical', or 'datetime'
        Name identifying the type of data in the vector.
    rY   rX   rM  )actionr  r   rR   Nr   c                @    | D ]}t          |t                    s dS dS NFT)rD   r
   r'   x_is     r   all_numericz"variable_type.<locals>.all_numeric  s4     	 	Cc6** uutr   c                X    | D ]&}t          |t          t          j        f          s dS 'dS r  )rD   r   rF   
datetime64r  s     r   all_datetimez#variable_type.<locals>.all_datetime  s;     	 	CcHbm#<== uutr   )rH   rI   rD   rV   CategoricalDtyper  r_   r`   r   r2   catch_warningssimplefilterFutureWarningDeprecationWarningrF   rU  rt   apitypesis_numeric_dtypeis_datetime64_dtype)vectorr   r  r  s       r   r   r     sG   . YvF &, 344 +M*** 
wv 'I&&& ]]__F 
	 	"	" 
 
}6H&I	
 	
 	
 	
	wv1v&&**,, 2#L11
 
 
 
 
 
 
 

2 	 	 	 D	
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
v|$$V,, 'I&&&	v|''// (J'''   {6 'I&&&   |F (J''' &&&s6   #D$7DD$
DD$DD$$D(+D(Tc                `   | dnt          |           }|dnt          |          }d}d}| wt          |                              d          r(t          j        |                    dd                     |r)|dk    r#t          |                    dd                    d	S |wt          |                              d
          r(t          j        |                    dd	                     |r)|dk    r#t          |                    dd	                    dS t          |                              d
          s|d	k    r-|r)|dk    r#t          |                    dd                    d	S t          |                              d          s|dk    r-|r)|dk    r#t          |                    dd	                    dS |"dt          |           d}t          |          |dk    r|dk    rdS |dk    r|dk    rd	S |dk    r|dk    rdS |rd||fvrd}t          |          d	S )aa  Determine how the plot should be oriented based on the data.

    For historical reasons, the convention is to call a plot "horizontally"
    or "vertically" oriented based on the axis representing its dependent
    variable. Practically, this is used when determining the axis for
    numerical aggregation.

    Parameters
    ----------
    x, y : Vector data or None
        Positional data vectors for the plot.
    orient : string or None
        Specified orientation. If not None, can be "x" or "y", or otherwise
        must start with "v" or "h".
    require_numeric : bool
        If set, raise when the implied dependent variable is not numeric.

    Returns
    -------
    orient : "x" or "y"

    Raises
    ------
    ValueError: When `orient` is an unknown string.
    TypeError: When dependent variable is not numeric, with `require_numeric`

    Nz.{} orientation requires numeric `{}` variable.z0{} orientation ignored with only `{}` specified.h
Horizontalr   rX   Verticalr'   r   z5`orient` must start with 'v' or 'h' or be None, but `z` was passed.rY   z7Neither the `x` nor `y` variable appears to be numeric.)	r   r   
startswithr2   r3   r   rt   reprr   )	r'   r   orientrequire_numericx_typey_typenonnumeric_dv_errorsingle_var_warningrx   s	            r   infer_orientr"    s   : YTTM!$4$4FYTTM!$4$4FJKyv;;!!#&& 	HM,33L#FFGGG 	Iv22/66z3GGHHHs	
v;;!!#&& 	FM,33JDDEEE 	Kv22/66|SIIJJJs	V			$	$ # 	Iv22/66z3GGHHHs	V			$	$ # 	Kv22/66|SIIJJJs		0LL0 0 0 	 oo	=	 	 V}%<%<s	9		9!4!4s	9		9!4!4s	 Yvv.>>>Gnn sr   c                   g d}d}t          |          | k     rt          j        ddg|          }t          j        ddg|          }t          j        t	          t          |          dd         ddd         t          |          dd                    }|D ]M}t          |          t          t          j        fd|D                        }|                    |           N|dz  }t          |          | k     |d|          S )	a  Build an arbitrarily long list of unique dash styles for lines.

    Parameters
    ----------
    n : int
        Number of unique dash specs to generate.

    Returns
    -------
    dashes : list of strings or tuples
        Valid arguments for the ``dashes`` parameter on
        :class:`matplotlib.lines.Line2D`. The first spec is a solid
        line (``""``), the remainder are sequences of long and short
        dashes.

    )r    )rW         ?)rR   rR   )         ?r$  r&  )   rR   rR   rR   r%  r&  rW   rR   r   Nc              3      K   | ]}|fV  	d S r   r$   )r%   seggaps     r   r   z unique_dashes.<locals>.<genexpr>  s'      *J*J#C:*J*J*J*J*J*Jr   )	r-   r0   combinations_with_replacementchainr/   rE   r   r   r   )	nr   pabsegment_listsegmentsspecr*  s	           @r   r   r   o  s#   $  F 	
A
f++// 3QIqAA3QFA>> !GGAbDM$$B$GGAbDM)
 )
  % 	  	 Hh--C*J*J*J*J*J*J*JKLLDMM$	Q% f++//( "1":r   c                    g d}d}t          |          | k     rNd|dz   z  dz  }|                    |dz   d|f|dz   d|f|ddf|ddfg           |dz  }t          |          | k     N|d|          S )aW  Build an arbitrarily long list of unique marker styles for points.

    Parameters
    ----------
    n : int
        Number of unique marker specs to generate.

    Returns
    -------
    markers : list of string or tuples
        Values for defining :class:`matplotlib.markers.MarkerStyle` objects.
        All markers will be filled.

    )	oX)rW   r   -   P)rW   r   r   )rW   rR   r   ^)rW   rR   r7  r   r'  ih  rR   r   r   N)r-   r3  )r-  r   r   r/  s       r   r   r     s     
 
 
G 	
A
g,,

1q5MAUAqMUAqM1I1I	
 	 	 	 	
Q g,,

 2A2;r   c                l   |t          | d          r| j        }nr	 | j        j        }nd# t          t          f$ rP t          j        |                                           }t          |           dk    rt          j
        |          }Y nw xY wt          t
          j        |          }t          |          S )a  Return a list of unique data values.

    Determine an ordered list of levels in ``values``.

    Parameters
    ----------
    vector : list, array, Categorical, or Series
        Vector of "categorical" values
    order : list-like, optional
        Desired order of category levels to override the order determined
        from the ``values`` object.

    Returns
    -------
    order : list
        Ordered list of category levels not including null values.

    Nr
  rX   )rR  r
  catrt   r  rH   rI   r   r   rF   r   filternotnullrE   )r  rk   s     r   r   r     s    & }6<(( 
	+%EE+
-~. + + +	&))0022 ((I55GENNE+ rz5));;s   ) AB
	B
r   )NNNTr   )+
__future__r   r2   r0   r   r  r   collections.abcr   r   r	   numbersr
   r   numpyrF   pandasrH   
matplotlibr   seaborn._core.datar   seaborn.palettesr   r   seaborn.utilsr   r   r   r   r   r   r   rQ   r   r   r   r  r   r"  r   r   r   r$   r   r   <module>rG     s   " " " " " "            " " " " " " 7 7 7 7 7 7 7 7 7 7                         ' ' ' ' ' '                      8= 8= 8= 8= 8= 8= 8= 8=vO0 O0 O0 O0 O0 O0 O0 O0dZ6 Z6 Z6 Z6 Z6/ Z6 Z6 Z6z[ [ [ [ [? [ [ [BA A A A A A A AH" " " " ": " " "(Y' Y' Y' Y'xP P P Pf0 0 0f+ + +\! ! ! ! ! !r   