
    hhsL                       d dl mZ d dlZd dlmZmZ d dlmZ erdd dlZd dl	m
Z d dlZd dl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 d dlmZmZ d dlm Z  d dl!mZm"Z" d d	l#m$Z$ d d
l%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/  e0dg          Z1ddZ2ddZ3ddZ4ddZ5ddZ6ddZ7ddZ8ddZ9ddZ:ddZ;ddZ<ddZ=ddZ>ddZ?ddZ@ddZAdd ZBdd"ZCdd$ZDdd&ZEdd)ZFdd+ZGdd-ZHdd/ZIdd1ZJdd3ZKdd5ZLdd8ZMdd:ZNdd<ZOdd>ZPdd@ZQddBZRddDZSddFZTddHZUddJZVddLZWddNZXddPZYddRZZddTZ[ddVZ\ddXZ]dd\Z^dd^Z_dd`Z`ddbZaddeZbddfZcddgZdddhZeddjZfddlZgddpZhddtZiddwZjdd{Zkdd~ZlddZmg dZndS )    )annotationsN)TYPE_CHECKINGAny)issue_warning	DataFrame)	TypeGuardTypeIs)SQLFrameDataFrame)r   	LazyFrameSeries)
IntoDataFrameTIntoLazyFrameTIntoSeriesTPandasLikeDType_1DArray_1DArrayInt_2DArray_NDArray_NumpyScalar_ShapeT	fireducksreturnr   c                 B    t           j                            dd          S )z;Get Polars module (if already imported - else return None).polarsNsysmodulesget     L/var/www/histauto/venv/lib/python3.11/site-packages/narwhals/dependencies.py
get_polarsr$   /       ;??8T***r"   c                 B    t           j                            dd          S )z;Get pandas module (if already imported - else return None).pandasNr   r!   r"   r#   
get_pandasr(   4   r%   r"   c                 B    t           j                            dd          S )zAGet modin.pandas module (if already imported - else return None).zmodin.pandasNr   r!   r"   r#   	get_modinr*   9   s    ;??>4000r"   c                 B    t           j                            dd          S )z9Get cudf module (if already imported - else return None).cudfNr   r!   r"   r#   get_cudfr-   >       ;??64(((r"   c                 B    t           j                            dd          S )z9Get cupy module (if already imported - else return None).cupyNr   r!   r"   r#   get_cupyr1   C   r.   r"   c                 B    t           j                            dd          S )z<Get pyarrow module (if already imported - else return None).pyarrowNr   r!   r"   r#   get_pyarrowr4   H       ;??9d+++r"   c                 B    t           j                            dd          S )z:Get numpy module (if already imported - else return None).numpyNr   r!   r"   r#   	get_numpyr8   M   s    ;??7D)))r"   c                 B    t           j                            dd          S )z2Get dask (if already imported - else return None).daskNr   r!   r"   r#   get_daskr;   R   r.   r"   c                 B    t           j                            dd          S )zCGet dask.dataframe module (if already imported - else return None).zdask.dataframeNr   r!   r"   r#   get_dask_dataframer=   W   s    ;??+T222r"   c                 B    t           j                            dd          S )z;Get duckdb module (if already imported - else return None).duckdbNr   r!   r"   r#   
get_duckdbr@   \   r%   r"   c                 B    t           j                            dd          S )z9Get ibis module (if already imported - else return None).ibisNr   r!   r"   r#   get_ibisrC   a   r.   r"   c                     t                      x} t          | d          r| j        S t          j                            dd          S )z>Get dask_expr module (if already imported - else return None).N	dask_expr)r=   hasattrrE   r   r   r    )dds    r#   get_dask_exprrH   f   s@     """/GB4L4L/|;??;---r"   c                 B    t           j                            dd          S )z<Get pyspark module (if already imported - else return None).pysparkNr   r!   r"   r#   get_pysparkrK   m   r5   r"   c                 B    t           j                            dd          S )z@Get pyspark.sql module (if already imported - else return None).zpyspark.sqlNr   r!   r"   r#   get_pyspark_sqlrM   r   s    ;??=$///r"   c                 B    t           j                            dd          S )zHGet pyspark.sql.connect module (if already imported - else return None).zpyspark.sql.connectNr   r!   r"   r#   get_pyspark_connectrO   w   s    ;??0$777r"   c                 B    t           j                            dd          S )z=Get sqlframe module (if already imported - else return None).sqlframeNr   r!   r"   r#   get_sqlframerR   |   s    ;??:t,,,r"   dfNonec                    t          |           st          |           r*dt          |            d}t          |t                     d S d S )NYou passed a `z` to `is_pandas_dataframe`.

Hint: Instead of e.g. `is_pandas_dataframe(df)`, did you mean `is_pandas_dataframe(df.to_native())`?)is_narwhals_dataframeis_narwhals_lazyframetyper   UserWarning)rS   msgs     r#   _warn_if_narwhals_df_or_lfr\      si    R   ($9"$=$= (BT"XX B B B 	
 	c;'''''( (r"   serc                x    t          |           r*dt          |            d}t          |t                     d S d S )NrV   zz` to `is_pandas_series`.

Hint: Instead of e.g. `is_pandas_series(ser)`, did you mean `is_pandas_series(ser.to_native())`?)is_narwhals_seriesrY   r   rZ   )r]   r[   s     r#   _warn_if_narwhals_seriesr`      sY    # (@T#YY @ @ @ 	
 	c;'''''( (r"   TypeIs[pd.DataFrame]c                     t                      t                      x}durt           |j                  p t	           fdt
          D                       S )zCheck whether `df` is a pandas DataFrame without importing pandas.

    Warning:
        This method cannot be called on a Narwhals DataFrame/LazyFrame.
    Nc              3     K   | ]B}t           j                            |d           xd uot          j        j                  V  Cd S N)r   r   r    
isinstancer'   r   ).0module_namerS   mods     r#   	<genexpr>z&is_pandas_dataframe.<locals>.<genexpr>   sr       V V  T22	24? 	1r3:/00V V V V V Vr"   )r\   r(   re   r   anyIMPORT_HOOKS)rS   pdrh   s   ` @r#   is_pandas_dataframerm      s     r"""<<R,MB1M1M RU V V V V V (V V V S S r"   TypeIs[pd.Series[Any]]c                     t                      t                      x}durt           |j                  p t	           fdt
          D                       S )zCheck whether `ser` is a pandas Series without importing pandas.

    Warning:
        This method cannot be called on Narwhals Series.
    Nc              3     K   | ]B}t           j                            |d           xd uot          j        j                  V  Cd S rd   )r   r   r    re   r'   r   )rf   rg   rh   r]   s     r#   ri   z#is_pandas_series.<locals>.<genexpr>   sr       T T  T22	24? 	/sCJ-..T T T T T Tr"   )r`   r(   re   r   rj   rk   )r]   rl   rh   s   ` @r#   is_pandas_seriesrq      s     S!!!<<R,KC1K1K PS T T T T T (T T T Q Q r"   indexTypeIs[pd.Index[Any]]c                     t                      x}durt           |j                  p t           fdt          D                       S )zACheck whether `index` is a pandas Index without importing pandas.Nc              3     K   | ]B}t           j                            |d           xd uot          j        j                  V  Cd S rd   )r   r   r    re   r'   Index)rf   rg   rr   rh   s     r#   ri   z"is_pandas_index.<locals>.<genexpr>   sr       U U  T22	24? 	0ucj.//U U U U U Ur"   )r(   re   rv   rj   rk   )rr   rl   rh   s   ` @r#   is_pandas_indexrw      st    <<R,LE281L1L QT U U U U U (U U U R R r"   TypeIs[mpd.DataFrame]c                n    t          |            t                      x}duot          | |j                  S )zCheck whether `df` is a modin DataFrame without importing modin.

    Warning:
        This method cannot be called on a Narwhals DataFrame/LazyFrame.
    N)r\   r*   re   r   )rS   mpds     r#   is_modin_dataframer{      s7     r""";;Ct+M
2s}0M0MMr"   TypeIs[mpd.Series]c                n    t          |            t                      x}duot          | |j                  S )zCheck whether `ser` is a modin Series without importing modin.

    Warning:
        This method cannot be called on Narwhals Series.
    N)r`   r*   re   r   )r]   rz   s     r#   is_modin_seriesr~      s7     S!!!;;Ct+K
3
0K0KKr"   TypeIs[mpd.Index[Any]]c                P    t                      x}duot          | |j                  S )z?Check whether `index` is a modin Index without importing modin.N)r*   re   rv   )rr   rz   s     r#   is_modin_indexr      s'    ;;Ct+L
5#)0L0LLr"   TypeIs[cudf.DataFrame]c                n    t          |            t                      x}duot          | |j                  S )zCheck whether `df` is a cudf DataFrame without importing cudf.

    Warning:
        This method cannot be called on a Narwhals DataFrame/LazyFrame.
    N)r\   r-   re   r   )rS   r,   s     r#   is_cudf_dataframer      s7     r"""JJDt+N
2t~0N0NNr"   TypeIs[cudf.Series[Any]]c                n    t          |            t                      x}duot          | |j                  S )zCheck whether `ser` is a cudf Series without importing cudf.

    Warning:
        This method cannot be called on Narwhals Series.
    N)r`   r-   re   r   )r]   r,   s     r#   is_cudf_seriesr      s7     S!!!JJDt+L
30L0LLr"   TypeIs[cudf.Index]c                P    t                      x}duot          | |j                  S )z=Check whether `index` is a cudf Index without importing cudf.N)r-   re   rv   )rr   r,   s     r#   is_cudf_indexr      s0    JJDt+ 
tz1 1 r"   objboolc                f    t                      x}d uot          | |j                  o
| j        dk    S )N   )r1   re   ndarraysize)r   r0   s     r#   is_cupy_scalarr      s:    	D( 	sDL))	HMr"   TypeIs[dd.DataFrame]c                n    t          |            t                      x}duot          | |j                  S )zCheck whether `df` is a Dask DataFrame without importing Dask.

    Warning:
        This method cannot be called on a Narwhals DataFrame/LazyFrame.
    N)r\   r=   re   r   )rS   rG   s     r#   is_dask_dataframer      s9     r"""$&&&Bt3T
2r|8T8TTr"   TypeIs[duckdb.DuckDBPyRelation]c                n    t          |            t                      x}duot          | |j                  S )zCheck whether `df` is a DuckDB Relation without importing DuckDB.

    Warning:
        This method cannot be called on Narwhals DataFrame/LazyFrame.
    N)r\   r@   re   DuckDBPyRelation)rS   r?   s     r#   is_duckdb_relationr      sA     r""" ll"F4/ J
F#5 5 r"   TypeIs[ibis.Table]c                    t          |            t                      x}duot          | |j        j        j                  S )zCheck whether `df` is a Ibis Table without importing Ibis.

    Warning:
        This method cannot be called on Narwhals DataFrame/LazyFrame.
    N)r\   rC   re   exprtypesTable)rS   rB   s     r#   is_ibis_tabler     s<     r"""JJDt+U
2ty?T0U0UUr"   TypeIs[pl.DataFrame]c                n    t          |            t                      x}duot          | |j                  S )zCheck whether `df` is a Polars DataFrame without importing Polars.

    Warning:
        This method cannot be called on a Narwhals DataFrame/LazyFrame.
    N)r\   r$   re   r   rS   pls     r#   is_polars_dataframer     7     r""",,Bt+L
2r|0L0LLr"   TypeIs[pl.LazyFrame]c                n    t          |            t                      x}duot          | |j                  S )zCheck whether `df` is a Polars LazyFrame without importing Polars.

    Warning:
        This method cannot be called on Narwhals DataFrame/LazyFrame.
    N)r\   r$   re   r   r   s     r#   is_polars_lazyframer      r   r"   TypeIs[pl.Series]c                n    t          |            t                      x}duot          | |j                  S )zCheck whether `ser` is a Polars Series without importing Polars.

    Warning:
        This method cannot be called on Narwhals Series.
    N)r`   r$   re   r   )r]   r   s     r#   is_polars_seriesr   *  s7     S!!!,,Bt+J
3	0J0JJr"   TypeIs[pl.Schema]c                    t          t                      x}          o$t          |d          ot          | |j                  S )NSchema)r   r$   rF   re   r   r   r   s     r#   is_polars_schemar   4  s;    :<<R  YWR%:%:Yz#ry?Y?Yr"   TypeIs[pl.DataType]c                f    t          t                      x}          ot          | |j                  S rd   )r   r$   re   DataTyper   s     r#   is_polars_data_typer   ;  s*    jll"##D
3(D(DDr"   TypeIs[pa.ChunkedArray[Any]]c                n    t          |            t                      x}duot          | |j                  S )zCheck whether `ser` is a PyArrow ChunkedArray without importing PyArrow.

    Warning:
        This method cannot be called on Narwhals Series.
    N)r`   r4   re   ChunkedArray)r]   pas     r#   is_pyarrow_chunked_arrayr   ?  s7     S!!!--B,QC1Q1QQr"   TypeIs[pa.Table]c                n    t          |            t                      x}duot          | |j                  S )zCheck whether `df` is a PyArrow Table without importing PyArrow.

    Warning:
        This method cannot be called on Narwhals DataFrame/LazyFrame.
    N)r\   r4   re   r   )rS   r   s     r#   is_pyarrow_tabler   I  s7     r"""--B,IB1I1IIr"   TypeIs[pa.Scalar[Any]]c                P    t                      x}d uot          | |j                  S rd   )r4   re   Scalarr   r   s     r#   is_pyarrow_scalarr   S  s'    --B,KC1K1KKr"   TypeIs[pa.Schema]c                f    t          t                      x}          ot          | |j                  S rd   )r   r4   re   r   r   s     r#   is_pyarrow_schemar   W  s*    kmm#$$CC)C)CCr"   TypeIs[pa.DataType]c                f    t          t                      x}          ot          | |j                  S rd   )r   r4   re   r   r   s     r#   is_pyarrow_data_typer   [  s*    kmm#$$EC)E)EEr"   TypeIs[pyspark_sql.DataFrame]c                    t          |            t          t                      x}duot          | |j                            S )zCheck whether `df` is a PySpark DataFrame without importing PySpark.

    Warning:
        This method cannot be called on a Narwhals DataFrame/LazyFrame.
    N)r\   r   rM   re   r   )rS   pyspark_sqls     r#   is_pyspark_dataframer   _  sL     r"""'))	)$6 	2r;011  r"   TypeIs[PySparkConnectDataFrame]c                    t          |            t                      )	 ddlm} n# t          $ r Y dS w xY wt          | |          S dS )zCheck whether `df` is a PySpark Connect DataFrame without importing PySpark.

    Warning:
        This method cannot be called on a Narwhals DataFrame/LazyFrame.
    Nr   r   F)r\   rO   pyspark.sql.connect.dataframer   ImportErrorre   rS   r   s     r#   is_pyspark_connect_dataframer   l  so     r"""(	??????? 	 	 	55	"i(((5s   & 
44TypeIs[SQLFrameDataFrame]c                l    t          |            t                      ddlm} t	          | |          S dS )zCheck whether `df` is a SQLFrame DataFrame without importing SQLFrame.

    Warning:
        This method cannot be called on a Narwhals DataFrame/LazyFrame.
    Nr   )BaseDataFrameF)r\   rR   sqlframe.base.dataframer   re   )rS   r   s     r#   is_sqlframe_dataframer   |  sC     r"""~~!999999"m,,,5r"   arrAny | _NDArray[_ShapeT]TypeIs[_NDArray[_ShapeT]]c                P    t                      x}duot          | |j                  S )z=Check whether `arr` is a NumPy Array without importing NumPy.N)r8   re   r   r   nps     r#   is_numpy_arrayr     s'    ++Bd*Jz#rz/J/JJr"   TypeIs[_1DArray]c                6    t          |           o
| j        dk    S )z@Check whether `arr` is a 1D NumPy Array without importing NumPy.r   r   ndimr   s    r#   is_numpy_array_1dr         #038q=0r"   TypeIs[_1DArrayInt]c                    t                      x}o.t          |           o|                    | j        |j                  S rd   )r8   r   
issubdtypedtypeintegerr   s     r#   is_numpy_array_1d_intr     s=    {{	 	1c""	1MM#)RZ00r"   TypeIs[_2DArray]c                6    t          |           o
| j        dk    S )z@Check whether `arr` is a 2D NumPy Array without importing NumPy.   r   r   s    r#   is_numpy_array_2dr     r   r"   scalarTypeGuard[_NumpyScalar]c                P    t                      x}duot          | |j                  S )zACheck whether `scalar` is a NumPy Scalar without importing NumPy.N)r8   re   generic)r   r   s     r#   is_numpy_scalarr     s)    
 ++Bd*Mz&"*/M/MMr"   c                z    t          |            t          |           pt          |           pt          |           S )zCheck whether `df` is a pandas-like DataFrame without doing any imports.

    By "pandas-like", we mean: pandas, Modin, cuDF.

    Warning:
        This method cannot be called on a Narwhals DataFrame/LazyFrame.
    )r\   rm   r{   r   )rS   s    r#   is_pandas_like_dataframer     s=     r"""r""U&8&<&<U@QRT@U@UUr"   c                z    t          |            t          |           pt          |           pt          |           S )zCheck whether `ser` is a pandas-like Series without doing any imports.

    By "pandas-like", we mean: pandas, Modin, cuDF.

    Warning:
        This method cannot be called on Narwhals Series.
    )r`   rq   r~   r   r]   s    r#   is_pandas_like_seriesr     s:     S!!!C  OOC$8$8ON3<O<OOr"   c                \    t          |           pt          |           pt          |           S )zCheck whether `index` is a pandas-like Index without doing any imports.

    By "pandas-like", we mean: pandas, Modin, cuDF.
    )rw   r   r   )rr   s    r#   is_pandas_like_indexr     s.     	O."7"7O=;O;Or"   TypeIs[PandasLikeDType]c                    t          t                      x}          o1t          | |j        j        j        t                      j        f          S rd   )r   r(   re   api
extensionsExtensionDtyper8   r   r   rl   s     r#   is_pandas_like_dtyper     sE    jll"## 
bf.	0AB) ) r"   (TypeIs[pd.api.extensions.ExtensionDtype]c                    t          t                      x}          o.t          | |j        j        j                  ot          | d          S )Nto_arrow)r   r(   re   r   r   r   rF   r   s     r#   is_cudf_dtyper    sI     	:<<R   	%sRV.=??	%C$$r"   native_seriesAny | IntoSeriesTTypeIs[IntoSeriesT]c                    ddl m} t          | |          p<t          | d          p,t	          |           pt          |           pt          |           S )aM  Check whether `native_series` can be converted to a Narwhals Series.

    Arguments:
        native_series: The object to check.

    Examples:
        >>> import pandas as pd
        >>> import polars as pl
        >>> import numpy as np
        >>> import narwhals as nw

        >>> s_pd = pd.Series([1, 2, 3])
        >>> s_pl = pl.Series([1, 2, 3])
        >>> np_arr = np.array([1, 2, 3])

        >>> nw.dependencies.is_into_series(s_pd)
        True
        >>> nw.dependencies.is_into_series(s_pl)
        True
        >>> nw.dependencies.is_into_series(np_arr)
        False
    r   r   __narwhals_series__)narwhals.seriesr   re   rF   r   r   r   )r  r   s     r#   is_into_seriesr    sq    . '&&&&& 	=&)) 	0="788	0M**	0 $M22	0 !//r"   native_dataframeAny | IntoDataFrameTTypeIs[IntoDataFrameT]c                    ddl m} t          | |          p<t          | d          p,t	          |           pt          |           pt          |           S )a  Check whether `native_dataframe` can be converted to a Narwhals DataFrame.

    Arguments:
        native_dataframe: The object to check.

    Examples:
        >>> import pandas as pd
        >>> import polars as pl
        >>> import numpy as np
        >>> from narwhals.dependencies import is_into_dataframe

        >>> df_pd = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
        >>> df_pl = pl.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
        >>> np_arr = np.array([[1, 4], [2, 5], [3, 6]])

        >>> is_into_dataframe(df_pd)
        True
        >>> is_into_dataframe(df_pl)
        True
        >>> is_into_dataframe(np_arr)
        False
    r   r   __narwhals_dataframe__)narwhals.dataframer   re   rF   r   r   r   )r  r   s     r#   is_into_dataframer    sv    . -,,,,, 	#Y// 	6#%=>>	6/00	6 ,--	6 $$455r"   DataFrame[IntoDataFrameT] | Any!TypeIs[DataFrame[IntoDataFrameT]]c                .    ddl m} t          | |          S )zCheck whether `df` is a Narwhals DataFrame.

    This is useful if you expect a user to pass in a Narwhals
    DataFrame directly, and you want to catch both `narwhals.DataFrame`
    and `narwhals.stable.v1.DataFrame`.
    r   r   )r  r   re   r   s     r#   rW   rW     &     -,,,,,b)$$$r"   lfAny | LazyFrame[IntoLazyFrameT]!TypeIs[LazyFrame[IntoLazyFrameT]]c                .    ddl m} t          | |          S )zCheck whether `lf` is a Narwhals LazyFrame.

    This is useful if you expect a user to pass in a Narwhals
    LazyFrame directly, and you want to catch both `narwhals.LazyFrame`
    and `narwhals.stable.v1.LazyFrame`.
    r   )r   )r  r   re   )r  r   s     r#   rX   rX   -  r  r"   Any | Series[IntoSeriesT]TypeIs[Series[IntoSeriesT]]c                .    ddl m} t          | |          S )zCheck whether `ser` is a Narwhals Series.

    This is useful if you expect a user to pass in a Narwhals
    Series directly, and you want to catch both `narwhals.Series`
    and `narwhals.stable.v1.Series`.
    r   r   )r
  r   re   )r]   r   s     r#   r_   r_   ;  s&     '&&&&&c6"""r"   c                R    t          |           o| j                                        S rd   )r_   r   
is_integerr   s    r#   is_narwhals_series_intr   G  s#    c""=sy';';'='==r"   )r-   rC   r*   r8   r(   r$   r4   r   r   r   r   r  r  r{   r~   rW   rX   r_   r   rm   rw   r   r   rq   r   r   r   r   r   )r   r   )rS   r   r   rT   )r]   r   r   rT   )rS   r   r   ra   )r]   r   r   rn   )rr   r   r   rs   )rS   r   r   rx   )r]   r   r   r|   )rr   r   r   r   )rS   r   r   r   )r]   r   r   r   )rr   r   r   r   )r   r   r   r   )rS   r   r   r   )rS   r   r   r   )rS   r   r   r   )rS   r   r   r   )rS   r   r   r   )r]   r   r   r   )r   r   r   r   )r   r   r   r   )r]   r   r   r   )rS   r   r   r   )r   r   r   r   )r   r   r   r   )r   r   r   r   )rS   r   r   r   )rS   r   r   r   )rS   r   r   r   )r   r   r   r   )r   r   r   r   )r   r   r   r   )r   r   r   r   )r   r   r   r   )rS   r   r   r   )r]   r   r   r   )rr   r   r   r   )r   r   r   r   )r   r   r   r  )r  r  r   r  )r  r  r   r  )rS   r  r   r  )r  r  r   r  )r]   r  r   r  )o
__future__r   r   typingr   r   narwhals._exceptionsr   r,   dask.dataframe	dataframerG   r?   rB   modin.pandasr'   rz   rl   r   r   r3   r   pyspark.sqlsqlr   r   r   PySparkConnectDataFrametyping_extensionsr	   r
   narwhals._spark_like.dataframer   r  r   r
  r   narwhals.typingr   r   r   r   r   r   r   r   r   r   	frozensetrk   r$   r(   r*   r-   r1   r4   r8   r;   r=   r@   rC   rH   rK   rM   rO   rR   r\   r`   rm   rq   rw   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  rW   rX   r_   r   __all__r!   r"   r#   <module>r/     s   # " " " " " 



 % % % % % % % % . . . . . . KKKMMMKKK%%%%%%RRRRRR33333333@@@@@@77777777&&&&&&                       " y+''+ + + +
+ + + +
1 1 1 1
) ) ) )
) ) ) )
, , , ,
* * * *
) ) ) )
3 3 3 3
+ + + +
) ) ) )
. . . ., , , ,
0 0 0 0
8 8 8 8
- - - -
( ( ( (( ( ( (         N N N NL L L LM M M M
O O O OM M M M      U U U U	 	 	 	V V V VM M M MM M M MK K K K   E E E ER R R RJ J J JL L L LD D D DF F F F
 
 
 
       K K K K
1 1 1 1
   1 1 1 1
N N N N	V 	V 	V 	V	P 	P 	P 	P            D   D% % % %% % % %	# 	# 	# 	#> > > >  r"   