a
    `                     @   s  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 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! dd
lm"Z"m#Z#m$Z$ ddlm%Z% ddl&m'Z'm(Z( ddl)m*Z+ zd dl,Z,W n e-y   dZ,Y n0 zd dl.Z.W n e-y.   dZ.Y n0 G dd de/Z0G dd de0Z1G dd de0Z2e1 e2 dZ3dd Z4G dd de/Z5dd Z6dd Z7dd Z8e e6_9dS )    )absolute_importdivisionprint_function)Number)log10N)string_types)	DataArrayDataset)OrderedDict   )
Dispatcherngjitcalc_res	calc_bboxorient_arraycompute_coordsdshape_from_xarray_dataset)get_indicesdshape_from_pandasdshape_from_dask)Expr)resample_2dresample_2d_distributed)
reductionsc                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )Axisau  Interface for implementing axis transformations.

    Instances hold implementations of transformations to and from axis space.
    The default implementation is equivalent to:

    >>> def forward_transform(data_x):
    ...     scale * mapper(data_x) + t
    >>> def inverse_transform(axis_x):
    ...     inverse_mapper((axis_x - t)/s)

    Where ``mapper`` and ``inverse_mapper`` are elementwise functions mapping
    to and from axis-space respectively, and ``scale`` and ``transform`` are
    parameters describing a linear scale and translate transformation, computed
    by the ``compute_scale_and_translate`` method.
    c                 C   s.   t | j|\}}|||  }| | }||fS )a  Compute the scale and translate parameters for a linear transformation
        ``output = s * input + t``, mapping from data space to axis space.

        Parameters
        ----------
        range : tuple
            A tuple representing the range ``[min, max]`` along the axis, in
            data space. Both min and max are inclusive.
        n : int
            The number of bins along the axis.

        Returns
        -------
        s, t : floats
        )mapmapper)selfrangenstartendst r$   .lib/python3.9/site-packages/datashader/core.pycompute_scale_and_translate1   s    
z Axis.compute_scale_and_translatec                 C   s(   t |d }|\}}| || | S )a)  Compute a 1D array representing the axis index.

        Parameters
        ----------
        st : tuple
            A tuple of ``(scale, translate)`` parameters.
        n : int
            The number of bins along the dimension.

        Returns
        -------
        index : ndarray
        g      ?)npZarangeinverse_mapper)r   str   Zpxr"   r#   r$   r$   r%   compute_indexF   s    zAxis.compute_indexc                 C   s   t dS )z'A mapping from data space to axis spaceNNotImplementedErrorvalr$   r$   r%   r   X   s    zAxis.mapperc                 C   s   t dS )z'A mapping from axis space to data spaceNr+   r-   r$   r$   r%   r(   \   s    zAxis.inverse_mapperc                 C   s   dS )zNGiven a range (low,high), raise an error if the range is invalid for this axisNr$   )r   r   r$   r$   r%   validate`   s    zAxis.validateN)	__name__
__module____qualname____doc__r&   r*   r   r(   r/   r$   r$   r$   r%   r       s   r   c                   @   s0   e Zd ZdZeedd Zeedd ZdS )
LinearAxiszA linear Axisc                 C   s   | S Nr$   r-   r$   r$   r%   r   g   s    zLinearAxis.mapperc                 C   s   | S r5   r$   r-   r$   r$   r%   r(   l   s    zLinearAxis.inverse_mapperN)r0   r1   r2   r3   staticmethodr   r   r(   r$   r$   r$   r%   r4   e   s   r4   c                   @   s8   e Zd ZdZeedd Zeedd Zdd ZdS )	LogAxiszA base-10 logarithmic Axisc                 C   s   t t| S r5   )r   floatr-   r$   r$   r%   r   t   s    zLogAxis.mapperc                 C   s   d}||  S )N
   r$   )r.   yr$   r$   r%   r(   y   s    zLogAxis.inverse_mapperc                 C   s0   t | j|\}}t|r$t|s,tdd S )Nz%Range values must be >0 for a LogAxis)r   r   r'   Zisfinite
ValueError)r   r   ZlowZhighr$   r$   r%   r/      s    zLogAxis.validateN)	r0   r1   r2   r3   r6   r   r   r(   r/   r$   r$   r$   r%   r7   r   s   r7   )linearlogc                 C   sV   |d u r|d u s0|d u s0|d urR|d us0|d urRt dj| t|t|t|dd S )Nz
{glyph} coordinates may be specified by providing both the x and y arguments, or by
providing the geometry argument. Received:
    x: {x}
    y: {y}
    geometry: {geometry}
glyphxr:   geometry)r;   formatreprr>   r$   r$   r%   validate_xy_or_geometry   s    rD   c                   @   s|   e Zd ZdZdddZdddZdddZdddZdddZdddZ	d ddZ
dde dddddfddZdd ZdS )!Canvasa  An abstract canvas representing the space in which to bin.

    Parameters
    ----------
    plot_width, plot_height : int, optional
        Width and height of the output aggregate in pixels.
    x_range, y_range : tuple, optional
        A tuple representing the bounds inclusive space ``[min, max]`` along
        the axis.
    x_axis_type, y_axis_type : str, optional
        The type of the axis. Valid options are ``'linear'`` [default], and
        ``'log'``.
    X  Nr<   c                 C   sP   || _ || _|d u rd nt|| _|d u r.d nt|| _t| | _t| | _d S r5   )
plot_widthplot_heighttuplex_rangey_range_axis_lookupx_axisy_axis)r   rG   rH   rJ   rK   Zx_axis_typeZy_axis_typer$   r$   r%   __init__   s    
zCanvas.__init__c                 C   s   ddl m}m} ddlm} td||| |du r8| }|du rL|||}	nddlm}
 ddlm	} t
||r| jdur~| jnd	}| jdur| jnd	}|jt| t| f }nt
||
std
jt|d||}	t|| |	|S )a  Compute a reduction by pixel, mapping data to pixels as points.

        Parameters
        ----------
        source : pandas.DataFrame, dask.DataFrame, or xarray.DataArray/Dataset
            The input datasource.
        x, y : str
            Column names for the x and y coordinates of each point. If provided,
            the geometry argument may not also be provided.
        agg : Reduction, optional
            Reduction to compute. Default is ``count()``.
        geometry: str
            Column name of a PointsArray of the coordinates of each point. If provided,
            the x and y arguments may not also be provided.
        r   )PointMultiPointGeometry)countrP   Nr   GeoDataFrameDaskGeoDataFrameNNsource must be an instance of spatialpandas.GeoDataFrame or 
spatialpandas.dask.DaskGeoDataFrame.
  Received value of type {typ}typ)glyphsrP   rQ   r   rR   rD   spatialpandasrT   spatialpandas.daskrV   
isinstancerJ   rK   cx_partitionsslicer;   rB   typebypixel)r   sourcer@   r:   aggrA   rP   rQ   Z	count_rdnr?   rT   rV   rJ   rK   r$   r$   r%   points   s*    

zCanvas.pointsr   Fc                 C   s  ddl m}m}	m}
m}m}m}m} td||| |du rBt	
 }|durddlm} ddlm} t||r| jdur|| jnd}| jdur| jnd}|jt| t| f }nt||std	jt|d
||}n|| }}t||\}}|dkrtt|ttfr$t|ttfr$|||}nNt|ttfrXt|ttfrX|t|t|}ntdjt|t|dn|dkrVt|ttfrt|ttfr|	t|t|}nt|tjrt|ttfr|
|t|}ntt|ttfrt|tjr|t||}nFt|ttfr:t|ttfr:|||}ntdjt|t|dntdj|d|rt|t	jt	j fr|!  nd|}t"#| t$|| ||S )a  Compute a reduction by pixel, mapping data to pixels as one or
        more lines.

        For aggregates that take in extra fields, the interpolated bins will
        receive the fields from the previous point. In pseudocode:

        >>> for i in range(len(rows) - 1):    # doctest: +SKIP
        ...     row0 = rows[i]
        ...     row1 = rows[i + 1]
        ...     for xi, yi in interpolate(row0.x, row0.y, row1.x, row1.y):
        ...         add_to_aggregate(xi, yi, row0)

        Parameters
        ----------
        source : pandas.DataFrame, dask.DataFrame, or xarray.DataArray/Dataset
            The input datasource.
        x, y : str or number or list or tuple or np.ndarray
            Specification of the x and y coordinates of each vertex
            * str or number: Column labels in source
            * list or tuple: List or tuple of column labels in source
            * np.ndarray: When axis=1, a literal array of the
              coordinates to be used for every row
        agg : Reduction, optional
            Reduction to compute. Default is ``any()``.
        axis : 0 or 1, default 0
            Axis in source to draw lines along
            * 0: Draw lines using data from the specified columns across
                 all rows in source
            * 1: Draw one line per row in source using data from the
                 specified columns
        geometry : str
            Column name of a LinesArray of the coordinates of each line. If provided,
            the x and y arguments may not also be provided.
        antialias : bool
            If True, draw anti-aliased lines, distributing the aggregate value
            across neighboring pixels to more closely approximate the line
            shape. If False, each position on the line affects only a single
            pixel, resulting in line shapes that are blocky but easier to
            reason about. Needs at least Numba 0.51.2 to work and can only
            operate on the 'sum' or 'max' aggregators.

        Examples
        --------
        Define a canvas and a pandas DataFrame with 6 rows
        >>> import pandas as pd  # doctest: +SKIP
        ... import numpy as np
        ... import datashader as ds
        ... from datashader import Canvas
        ... import datashader.transfer_functions as tf
        ... cvs = Canvas()
        ... df = pd.DataFrame({
        ...    'A1': [1, 1.5, 2, 2.5, 3, 4],
        ...    'A2': [1.5, 2, 3, 3.2, 4, 5],
        ...    'B1': [10, 12, 11, 14, 13, 15],
        ...    'B2': [11, 9, 10, 7, 8, 12],
        ... }, dtype='float64')

        Aggregate one line across all rows, with coordinates df.A1 by df.B1
        >>> agg = cvs.line(df, x='A1', y='B1', axis=0)  # doctest: +SKIP
        ... tf.spread(tf.shade(agg))

        Aggregate two lines across all rows. The first with coordinates
        df.A1 by df.B1 and the second with coordinates df.A2 by df.B2
        >>> agg = cvs.line(df, x=['A1', 'A2'], y=['B1', 'B2'], axis=0)  # doctest: +SKIP
        ... tf.spread(tf.shade(agg))

        Aggregate two lines across all rows where the lines share the same
        x coordinates. The first line will have coordinates df.A1 by df.B1
        and the second will have coordinates df.A1 by df.B2
        >>> agg = cvs.line(df, x='A1', y=['B1', 'B2'], axis=0)  # doctest: +SKIP
        ... tf.spread(tf.shade(agg))

        Aggregate 6 length-2 lines, one per row, where the ith line has
        coordinates [df.A1[i], df.A2[i]] by [df.B1[i], df.B2[i]]
        >>> agg = cvs.line(df, x=['A1', 'A2'], y=['B1', 'B2'], axis=1)  # doctest: +SKIP
        ... tf.spread(tf.shade(agg))

        Aggregate 6 length-4 lines, one per row, where the x coordinates
        of every line are [0, 1, 2, 3] and the y coordinates of the ith line
        are [df.A1[i], df.A2[i], df.B1[i], df.B2[i]].
        >>> agg = cvs.line(df,  # doctest: +SKIP
        ...                x=np.arange(4),
        ...                y=['A1', 'A2', 'B1', 'B2'],
        ...                axis=1)
        ... tf.spread(tf.shade(agg))

        Aggregate RaggedArrays of variable length lines, one per row
        (requires pandas >= 0.24.0)
        >>> df_ragged = pd.DataFrame({  # doctest: +SKIP
        ...    'A1': pd.array([
        ...        [1, 1.5], [2, 2.5, 3], [1.5, 2, 3, 4], [3.2, 4, 5]],
        ...        dtype='Ragged[float32]'),
        ...    'B1': pd.array([
        ...        [10, 12], [11, 14, 13], [10, 7, 9, 10], [7, 8, 12]],
        ...        dtype='Ragged[float32]'),
        ...    'group': pd.Categorical([0, 1, 2, 1])
        ... })
        ...
        ... agg = cvs.line(df_ragged, x='A1', y='B1', axis=1)
        ... tf.spread(tf.shade(agg))

        Aggregate RaggedArrays of variable length lines by group column,
        one per row (requires pandas >= 0.24.0)
        >>> agg = cvs.line(df_ragged, x='A1', y='B1',  # doctest: +SKIP
        ...                agg=ds.count_cat('group'), axis=1)
        ... tf.spread(tf.shade(agg))
        r   )	LineAxis0
LinesAxis1LinesAxis1XConstantLinesAxis1YConstantLineAxis0MultiLinesAxis1RaggedLineAxis1GeometryZLineNr   rS   rU   rW   rX   rY   z
Invalid combination of x and y arguments to Canvas.line when axis=0.
    Received:
        x: {x}
        y: {y}
See docstring for more information on valid usager@   r:   z
Invalid combination of x and y arguments to Canvas.line when axis=1.
    Received:
        x: {x}
        y: {y}
See docstring for more information on valid usageE
The axis argument to Canvas.line must be 0 or 1
    Received: {axis}axisz0Aggresgation: '{}' is not supported by antialias)%r[   rf   rg   rh   ri   rj   rk   rl   rD   rdanyr\   rT   r]   rV   r^   rJ   rK   r_   r`   r;   rB   ra    _broadcast_column_specificationsr   r   listrI   rC   r'   ndarraysummaxZenable_antialiaswarningswarnrb   )r   rc   r@   r:   rd   rp   rA   Z	antialiasrf   rg   rh   ri   rj   rk   rl   rT   rV   rJ   rK   r?   orig_xorig_ymessager$   r$   r%   line   sz    m$





 

	

zCanvas.linec                 C   s  ddl m}m}m}	m}
m}m}m}m}m	}m
}m}m} ddlm} |du rR| }|||  }}}t|||\}}}|dkr|du rt|ttfrt|ttfr|||}nJt|ttfrt|ttfr|	t|t|}ntdjt|t|dnt|ttfr8t|ttfr8t|ttfr8||||}njt|ttfrt|ttfrt|ttfr|
t|t|t|}n tdjt|t|t|d	n*|dkr|du rt|ttfrt|ttfr|t|t|}nt|tjrt|ttfr||t|}ntt|ttfrJt|tjrJ|t||}nFt|ttfrvt|ttfrv|||}ntd
jt|t|dqt|ttfrt|ttfrt|ttfr|t|t|t|}nt|tjr"t|ttfr"t|ttfr"||t|t|}nt|ttfr`t|tjr`t|tjr`|t|||}n^t|ttfrt|ttfrt|ttfr||||}n tdjt|t|t|d	ntdj|dt|| ||S )a  Compute a reduction by pixel, mapping data to pixels as a filled
        area region

        Parameters
        ----------
        source : pandas.DataFrame, dask.DataFrame, or xarray.DataArray/Dataset
            The input datasource.
        x, y : str or number or list or tuple or np.ndarray
            Specification of the x and y coordinates of each vertex of the
            line defining the starting edge of the area region.
            * str or number: Column labels in source
            * list or tuple: List or tuple of column labels in source
            * np.ndarray: When axis=1, a literal array of the
              coordinates to be used for every row
        agg : Reduction, optional
            Reduction to compute. Default is ``count()``.
        axis : 0 or 1, default 0
            Axis in source to draw lines along
            * 0: Draw area regions using data from the specified columns
                 across all rows in source
            * 1: Draw one area region per row in source using data from the
                 specified columns
        y_stack: str or number or list or tuple or np.ndarray or None
            Specification of the y coordinates of each vertex of the line
            defining the ending edge of the area region, where the x
            coordinate is given by the x argument described above.

            If y_stack is None, then the area region is filled to the y=0 line

            If y_stack is not None, then the form of y_stack must match the
            form of y.

        Examples
        --------
        Define a canvas and a pandas DataFrame with 6 rows
        >>> import pandas as pd  # doctest: +SKIP
        ... import numpy as np
        ... import datashader as ds
        ... from datashader import Canvas
        ... import datashader.transfer_functions as tf
        ... cvs = Canvas()
        ... df = pd.DataFrame({
        ...    'A1': [1, 1.5, 2, 2.5, 3, 4],
        ...    'A2': [1.6, 2.1, 2.9, 3.2, 4.2, 5],
        ...    'B1': [10, 12, 11, 14, 13, 15],
        ...    'B2': [11, 9, 10, 7, 8, 12],
        ... }, dtype='float64')

        Aggregate one area region across all rows, that starts with
        coordinates df.A1 by df.B1 and is filled to the y=0 line
        >>> agg = cvs.area(df, x='A1', y='B1',  # doctest: +SKIP
        ...                agg=ds.count(), axis=0)
        ... tf.shade(agg)

        Aggregate one area region across all rows, that starts with
        coordinates df.A1 by df.B1 and is filled to the line with coordinates
        df.A1 by df.B2
        >>> agg = cvs.area(df, x='A1', y='B1', y_stack='B2', # doctest: +SKIP
        ...                agg=ds.count(), axis=0)
        ... tf.shade(agg)

        Aggregate two area regions across all rows. The first starting
        with coordinates df.A1 by df.B1 and the second with coordinates
        df.A2 by df.B2. Both regions are filled to the y=0 line
        >>> agg = cvs.area(df, x=['A1', 'A2'], y=['B1', 'B2'], agg=ds.count(), axis=0)  # doctest: +SKIP
        ... tf.shade(agg)

        Aggregate two area regions across all rows where the regions share the
        same x coordinates. The first region will start with coordinates
        df.A1 by df.B1 and the second will start with coordinates
        df.A1 by df.B2. Both regions are filled to the y=0 line
        >>> agg = cvs.area(df, x='A1', y=['B1', 'B2'], agg=ds.count(), axis=0)  # doctest: +SKIP
        ... tf.shade(agg)

        Aggregate 6 length-2 area regions, one per row, where the ith region
        starts with coordinates [df.A1[i], df.A2[i]] by [df.B1[i], df.B2[i]]
        and is filled to the y=0 line
        >>> agg = cvs.area(df, x=['A1', 'A2'], y=['B1', 'B2'], agg=ds.count(), axis=1)  # doctest: +SKIP
        ... tf.shade(agg)

        Aggregate 6 length-4 area regions, one per row, where the
        starting x coordinates of every region are [0, 1, 2, 3] and
        the starting y coordinates of the ith region are
        [df.A1[i], df.A2[i], df.B1[i], df.B2[i]].  All regions are filled to
        the y=0 line
        >>> agg = cvs.area(df,  # doctest: +SKIP
        ...                x=np.arange(4),
        ...                y=['A1', 'A2', 'B1', 'B2'],
        ...                agg=ds.count(),
        ...                axis=1)
        ... tf.shade(agg)

        Aggregate RaggedArrays of variable length area regions, one per row.
        The starting coordinates of the ith region are df_ragged.A1 by
        df_ragged.B1 and the regions are filled to the y=0 line.
        (requires pandas >= 0.24.0)
        >>> df_ragged = pd.DataFrame({  # doctest: +SKIP
        ...    'A1': pd.array([
        ...        [1, 1.5], [2, 2.5, 3], [1.5, 2, 3, 4], [3.2, 4, 5]],
        ...        dtype='Ragged[float32]'),
        ...    'B1': pd.array([
        ...        [10, 12], [11, 14, 13], [10, 7, 9, 10], [7, 8, 12]],
        ...        dtype='Ragged[float32]'),
        ...    'B2': pd.array([
        ...        [6, 10], [9, 10, 18], [9, 5, 6, 8], [4, 5, 11]],
        ...        dtype='Ragged[float32]'),
        ...    'group': pd.Categorical([0, 1, 2, 1])
        ... })
        ...
        ... agg = cvs.area(df_ragged, x='A1', y='B1', agg=ds.count(), axis=1)
        ... tf.shade(agg)

        Instead of filling regions to the y=0 line, fill to the line with
        coordinates df_ragged.A1 by df_ragged.B2
        >>> agg = cvs.area(df_ragged, x='A1', y='B1', y_stack='B2', # doctest: +SKIP
        ...                agg=ds.count(), axis=1)
        ... tf.shade(agg)

        (requires pandas >= 0.24.0)
        r   )AreaToZeroAxis0AreaToLineAxis0AreaToZeroAxis0MultiAreaToLineAxis0MultiAreaToZeroAxis1AreaToLineAxis1AreaToZeroAxis1XConstantAreaToLineAxis1XConstantAreaToZeroAxis1YConstantAreaToLineAxis1YConstantAreaToZeroAxis1RaggedAreaToLineAxis1Raggedrr   Nr   z
Invalid combination of x and y arguments to Canvas.area when axis=0.
    Received:
        x: {x}
        y: {y}
See docstring for more information on valid usagerm   z
Invalid combination of x, y, and y_stack arguments to Canvas.area when axis=0.
    Received:
        x: {x}
        y: {y}
        y_stack: {y_stack}
See docstring for more information on valid usage)r@   r:   y_stackz
Invalid combination of x and y arguments to Canvas.area when axis=1.
    Received:
        x: {x}
        y: {y}
See docstring for more information on valid usagez
Invalid combination of x, y, and y_stack arguments to Canvas.area when axis=1.
    Received:
        x: {x}
        y: {y}
        y_stack: {y_stack}
See docstring for more information on valid usagern   ro   )r[   r~   r   r   r   r   r   r   r   r   r   r   r   r   rr   rs   r^   r   r   rt   rI   r;   rB   rC   r'   ru   rb   )r   rc   r@   r:   rd   rp   r   r~   r   r   r   r   r   r   r   r   r   r   r   any_rdnrz   r{   Zorig_y_stackr?   r$   r$   r%   area  s    y8

	





zCanvas.areac                 C   s   ddl m} ddlm} ddlm} ddlm} t||rz| j	durJ| j	nd}| j
dur^| j
nd}	|jt| t|	 f }nt||std	jt|d
|du r| }||}
t|| |
|S )a  Compute a reduction by pixel, mapping data to pixels as one or
        more filled polygons.

        Parameters
        ----------
        source : xarray.DataArray or Dataset
            The input datasource.
        geometry : str
            Column name of a PolygonsArray of the coordinates of each line.
        agg : Reduction, optional
            Reduction to compute. Default is ``any()``.

        Returns
        -------
        data : xarray.DataArray

        Examples
        --------
        >>> import datashader as ds  # doctest: +SKIP
        ... import datashader.transfer_functions as tf
        ... from spatialpandas.geometry import PolygonArray
        ... from spatialpandas import GeoDataFrame
        ... import pandas as pd
        ...
        ... polygons = PolygonArray([
        ...     # First Element
        ...     [[0, 0, 1, 0, 2, 2, -1, 4, 0, 0],  # Filled quadrilateral (CCW order)
        ...      [0.5, 1,  1, 2,  1.5, 1.5,  0.5, 1],     # Triangular hole (CW order)
        ...      [0, 2, 0, 2.5, 0.5, 2.5, 0.5, 2, 0, 2],  # Rectangular hole (CW order)
        ...      [2.5, 3, 3.5, 3, 3.5, 4, 2.5, 3],  # Filled triangle
        ...     ],
        ...
        ...     # Second Element
        ...     [[3, 0, 3, 2, 4, 2, 4, 0, 3, 0],  # Filled rectangle (CCW order)
        ...      # Rectangular hole (CW order)
        ...      [3.25, 0.25, 3.75, 0.25, 3.75, 1.75, 3.25, 1.75, 3.25, 0.25],
        ...     ]
        ... ])
        ...
        ... df = GeoDataFrame({'polygons': polygons, 'v': range(len(polygons))})
        ...
        ... cvs = ds.Canvas()
        ... agg = cvs.polygons(df, geometry='polygons', agg=ds.sum('v'))
        ... tf.shade(agg)
        r   )PolygonGeomr   r   rS   rU   NrW   rX   rY   )r[   r   r   rr   r\   rT   r]   rV   r^   rJ   rK   r_   r`   r;   rB   ra   rb   )r   rc   rA   rd   r   r   rT   rV   rJ   rK   r?   r$   r$   r%   polygons  s$    .

zCanvas.polygonsc              
   C   s  ddl m}m}m} ddlm} t|tr^|du s<|jdu rLt	|j
d }	n|j}	||	g }n"t|trx|j}	| }ntd|du r||	}|du r|du r||	 j\}}n|r|std|| ||  }
}|
jdks|jdkr
|j|
jkr
td|j|
jf |	dur>|jdur>|j|	kr>td	|j|f |jdkrh| jtd
 u }| jtd
 u }t|
t|
d |
d t|
}t|t|d |d t|}|rL|rL|rL|rL||||	}|||||	| j| j| j| j\}}|r|rt|	}t|| ||S |s0|s0t|| ||S ||||	}t|| ||S n||||	}t|| ||S n<|jdkr||||	}t|| ||S tdj t	|jddS )a  Samples a recti- or curvi-linear quadmesh by canvas size and bounds.
        Parameters
        ----------
        source : xarray.DataArray or Dataset
            The input datasource.
        x, y : str
            Column names for the x and y coordinates of each point.
        agg : Reduction, optional
            Reduction to compute. Default is ``mean()``. Note that agg is ignored when
            upsampling.
        Returns
        -------
        data : xarray.DataArray
        r   )QuadMeshRasterQuadMeshRectilinearQuadMeshCurvilinearmeanNr   zInvalid input typezDEither specify both x and y coordinatesor allow them to be inferred.zEnsure that x- and y-coordinate arrays share the same dimensions. x-coordinates are indexed by %s dims while y-coordinates are indexed by %s dims.7DataArray name %r does not match supplied reduction %s.r<      zcx- and y-coordinate arrays must have 1 or 2 dimensions.
    Received arrays with dimensions: {dims})dims)!r[   r   r   r   r   r   r^   r	   columnrt   	data_varsr   nameZ
to_datasetr;   r   ndimrM   rL   rN   r'   ZallcloseZlinspacelenZis_upsamplerJ   rK   rG   rH   rq   Z	_upsamplerb   rB   )r   rc   r@   r:   rd   r   r   r   Zmean_rndr   ZyarrZxarrZxaxis_linearZyaxis_linearZeven_yspacingZeven_xspacingr?   Zupsample_widthZupsample_heightr$   r$   r%   quadmesh  sx    


$


zCanvas.quadmeshTc              
   C   s   ddl m} ddlm} ddlm}	 |}
|dur^|dkr>d}n |dkrLd	}ntd
ddg|
du rp|	||}
t|j	dk}|r|j	d }n
|j	d }|du r||}n|j
du r||_
|
j	}|d |d |dd   }}}t|
| ||||||d|S )a
  Compute a reduction by pixel, mapping data to pixels as a triangle.

        >>> import datashader as ds
        >>> verts = pd.DataFrame({'x': [0, 5, 10],
        ...                         'y': [0, 10, 0],
        ...                         'weight': [1, 5, 3]},
        ...                        columns=['x', 'y', 'weight'])
        >>> tris = pd.DataFrame({'v0': [2], 'v1': [0], 'v2': [1]},
        ...                       columns=['v0', 'v1', 'v2'])
        >>> cvs = ds.Canvas(x_range=(verts.x.min(), verts.x.max()),
        ...                 y_range=(verts.y.min(), verts.y.max()))
        >>> untested = cvs.trimesh(verts, tris)

        Parameters
        ----------
        vertices : pandas.DataFrame, dask.DataFrame
            The input datasource for triangle vertex coordinates. These can be
            interpreted as the x/y coordinates of the vertices, with optional
            weights for value interpolation. Columns should be ordered
            corresponding to 'x', 'y', followed by zero or more (optional)
            columns containing vertex values. The rows need not be ordered.
            The column data types must be floating point or integer.
        simplices : pandas.DataFrame, dask.DataFrame
            The input datasource for triangle (simplex) definitions. These can
            be interpreted as rows of ``vertices``, aka positions in the
            ``vertices`` index. Columns should be ordered corresponding to
            'vertex0', 'vertex1', and 'vertex2'. Order of the vertices can be
            clockwise or counter-clockwise; it does not matter as long as the
            data is consistent for all simplices in the dataframe. The
            rows need not be ordered.  The data type for the first
            three columns in the dataframe must be integer.
        agg : Reduction, optional
            Reduction to compute. Default is ``mean()``.
        mesh : pandas.DataFrame, optional
            An ordered triangle mesh in tabular form, used for optimization
            purposes. This dataframe is expected to have come from
            ``datashader.utils.mesh()``. If this argument is not None, the first
            two arguments are ignored.
        interpolate : str, optional default=linear
            Method to use for interpolation between specified values. ``nearest``
            means to use a single value for the whole triangle, and ``linear``
            means to do bilinear interpolation of the pixels within each
            triangle (a weighted average of the vertex values). For
            backwards compatibility, also accepts ``interp=True`` for ``linear``
            and ``interp=False`` for ``nearest``.
        r   )	Trianglesr   )meshNr<   TnearestF.Invalid interpolate method: options include {}r      r   )Zweight_typeinterp)r[   r   r   r   utilsr   r;   rB   r   columnsr   rb   )r   ZverticesZ	simplicesr   rd   r   interpolater   Zmean_rdnZcreate_meshrc   Zverts_have_weightsZ
weight_colZcolsr@   r:   Zweightsr$   r$   r%   trimesh.  s.    /



 zCanvas.trimeshc
           G       C   sN  |du r|}|du r|}ddg}
ddt jdddt jdddt jdddt jdddt jdd	d	t jd	d
d
t jd
ddt jdi}||
vrt	d
|
t|ttfst	dt|j d}t|t jrt||j }}t|tr|dur|j|krd|j|f }t	d|j|f t|tr`t|j}|du r<t	d| n||jvrXtd||f || }|| vrt	d
t| || }|jdvrt	d|j t|}|jdd \}}|| j|| j }}t|||\}}}}|dur|jf i |jd |i}t||}|j}|durH||k}tj j!|||d}|}ntj"}| j#du rd||f| _#| j$du rz||f| _$t| j#d |}t| j$d |}t| j#d |}t| j$d |} t|| | j#d | j#d   d}!t| | | j$d | j$d   d}"t%|!dst%|"dr"t	dtt&t'| j(|! d}#tt&t'| j)|" d}$t*||||d \}%}&t*|| ||d \}'}(t+|#|$|||d})|jdkr||'|(d |%|&d f }*|dv r|*,d}*t|*t-j.rt/|*f||	d|)}+nt0|*fi |)}+d},n|dd|'|(d |%|&d f }*|dv r>|*,d}*g }-|*D ]F}.t|.t-j.rpt/|.f||	d|)}.nt0|.fi |)}.|-1|. qFt2|-}+t3|-},|#| j(ks|$| j)kr| j)|$ }/| j(|# }0|| j#d  }1| j#d | }2|1|2 dkr|1|1|2  nd}3tt&t4|0|3 d}t|0| d}| j)|f| j)|f }4}5|,dkrb|4|,f |5|,f  }4}5t5|4||*j}6t5|5||*j}7|| j$d  }8| j$d |  }9|8|9 dkr|8|8|9  nd}:tt&t4|/|: d}t|/| d}||#f||#f };}<|,dkr|;|,f |<|,f  };}<t5|;||*j}=t5|<||*j}>t|+t-j.rHt-j6ntj6}?|=j7d dkrf|=|+fn|+f}-|>j7d dkr|-|>f7 }-t3|-dkr|?|-ddn|-d }+|6j7d dkr|6|+fn|+f}-|7j7d dkr|-|7f7 }-t3|-dkr|?|-ddn|-d }+|d dkr|+ddd  }+|d dk rB|+ddddd f }+|durT|+8 }+||+jkrj|+,|}+t9| j(| j)| j#| j$|\}@}A||@||Ai}B||g}Ct+|d d!}Dd"D ]&}E|E|j:v r|j:|E |Dd#<  qԐqd#|Dvrz|j:d$ d |Dd#< W n   Y n0 |+jd%kr>|+;g d&}+|jd }F|j<|F |B|F< |Fg|C }Ct|+|B|C|Dd'S )(aO
  Sample a raster dataset by canvas size and bounds.

        Handles 2D or 3D xarray DataArrays, assuming that the last two
        array dimensions are the y- and x-axis that are to be
        resampled. If a 3D array is supplied a layer may be specified
        to resample to select the layer along the first dimension to
        resample.

        Missing values (those having the value indicated by the
        "nodata" attribute of the raster) are replaced with `NaN` if
        floats, and 0 if int.

        Also supports resampling out-of-core DataArrays backed by dask
        Arrays. By default it will try to maintain the same chunksize
        in the output array but a custom chunksize may be provided.
        If there are memory constraints they may be defined using the
        max_mem parameter, which determines how large the chunks in
        memory may be.

        Parameters
        ----------
        source : xarray.DataArray or xr.Dataset
            2D or 3D labelled array (if Dataset, the agg reduction must
            define the data variable).
        layer : float
            For a 3D array, value along the z dimension : optional default=None
        ds_method : str (optional)
            Grid cell aggregation method for a possible downsampling.
        us_method : str (optional)
            Grid cell interpolation method for a possible upsampling.
        nan_value : int or float, optional
            Optional nan_value which will be masked out when applying
            the resampling.
        agg : Reduction, optional default=mean()
            Resampling mode when downsampling raster. The supported
            options include: first, last, mean, mode, var, std, min,
            The agg can be specified as either a string name or as a
            reduction function, but note that the function object will
            be used only to extract the agg type (mean, max, etc.) and
            the optional column name; the hardcoded raster code
            supports only a fixed set of reductions and ignores the
            actual code of the provided agg.
        interpolate : str, optional  default=linear
            Resampling mode when upsampling raster.
            options include: nearest, linear.
        chunksize : tuple(int, int) (optional)
            Size of the output chunks. By default this the chunk size is
            inherited from the *src* array.
        max_mem : int (optional)
            The maximum number of bytes that should be loaded into memory
            during the regridding operation.

        Returns
        -------
        data : xarray.Dataset
        Nr   r<   firstlastmoder   varstdminrw   r   zBExpected xarray DataArray or Dataset as the data source, found %s.z%s(%r)r   zsWhen supplying a Dataset the agg reduction must specify the variable to aggregate. Available data_vars include: %r.zdSupplied reduction column %r not found in Dataset, expected one of the following data variables: %r.z.Invalid aggregation method: options include {})r   r   zDRaster aggregation expects a 2D or 3D DataArray, found %s dimensionsr   )mask
fill_valuer   zCanvas x_range or y_range values do not match closely enough with the data source to be able to accurately rasterize. Please provide ranges that are more accurate.)wh	ds_methodZ	us_methodr   r   )r   r   f)	chunksizemax_memro   r   )res)Z
_FillValueZmissing_valuer   nodataZNODATAr   Z
nodatavalsr   )r   r   r   )coordsr   attrs)=rq   r   r   r   r   r   r   r   rw   r;   rB   r^   r   r	   ra   r0   Z	Reductionr   r   rt   r   KeyErrorkeysr   r   r   valuesr   Zselr   dtyper'   ZmaZmasked_arrayZNaNrJ   rK   ZiscloseintroundrG   rH   r   dictZastypedaZArrayr   r   appendZdstackr   ZceilZfullZconcatenateshapeZfilledr   r   Z	transposer   )Gr   rc   ZlayerZupsample_methodZdownsample_methodZ	nan_valuerd   r   r   r   Zupsample_methodsZdownsample_methodsr   Zagg_reprr   r   r   ZydimZxdimZxvalsZyvalsleftZbottomrighttoparrayr   r   r   ZxminZyminZxmaxZymaxZwidth_ratioZheight_ratior   r   ZcminZcmaxZrminZrmaxkwargsZsource_windowdataZlayersZarraysZarrZ
num_heightZ	num_widthZlpadZrpadZlpctZlshapeZrshapeZleft_padZ	right_padZtpadZbpadZtpctZtshapeZbshapeZtop_padZ
bottom_padconcatZxsZysr   r   r   aZ	layer_dimr$   r$   r%   raster  sH   C







	




""

"







"
"$





zCanvas.rasterc                 C   s    | j | j | j| j dS )z7Check that parameter settings are valid for this objectN)rM   r/   rJ   rN   rK   )r   r$   r$   r%   r/     s    zCanvas.validate)rF   rF   NNr<   r<   )NNNN)NNNr   NF)Nr   N)N)NNN)NNTN)r0   r1   r2   r3   rO   re   r}   r   r   r   r   rq   r   r   r/   r$   r$   r$   r%   rE      s6      


,  
 @
 n
B
h
T
  rE   c                    s|  t | tr(| jdkr(| js d| _|  } t | trt| jdkrt| j	
 t| j
  }t||| |  fdd|D } |  } t | tjstrt | tjrt| j|| t t| jk r|   } t| }n4t | tjrt| }nt | trt| }ntd|j}|| || |  tj 0 tjdd t| ||||W  d   S 1 sn0    Y  dS )	a  Compute an aggregate grouped by pixel sized bins.

    Aggregate input data ``source`` into a grid with shape and axis matching
    ``canvas``, mapping data to bins by ``glyph``, and aggregating by reduction
    ``agg``.

    Parameters
    ----------
    source : pandas.DataFrame, dask.DataFrame
        Input datasource
    canvas : Canvas
    glyph : Glyph
    agg : Reduction
    r   valuec                    s   g | ]}| vr|qS r$   r$   .0colcols_to_keepr$   r%   
<listcomp>      zbypixel.<locals>.<listcomp>z)source must be a pandas or dask DataFrameignorez All-NaN (slice|axis) encounteredN) r^   r   r   r   Zreset_coordsr	   r   r   rt   r   r   r   _cols_to_keepZdropZto_dask_dataframepdZ	DataFramecudfr   r   ddr   r   r;   Zmeasurer/   r'   rx   catch_warningsfilterwarningsrb   pipeline)rc   Zcanvasr?   rd   r   ZdshapeZschemar$   r   r%   rb     s<    





rb   c                 C   s   t dd | D }| D ]}d||< qt|drT|jD ]}|jd ur8d||j< q8n<t|dr||jD ]}|d urdd||< qdn|jd urd||j< dd | D S )Nc                 S   s   i | ]
}|d qS )Fr$   r   r$   r$   r%   
<dictcomp>  r   z!_cols_to_keep.<locals>.<dictcomp>Tr   r   c                 S   s   g | ]\}}|r|qS r$   r$   )r   r   Zkeepitr$   r$   r%   r     r   z!_cols_to_keep.<locals>.<listcomp>)r
   Zrequired_columnshasattrr   r   r   items)r   r?   rd   r   r   Zsubaggr   r$   r$   r%   r     s    







r   c                     s@   dd | D }t |dkr| S |  t fdd| D S d S )Nc                 S   s"   h | ]}t |ttfrt|qS r$   )r^   rt   rI   r   )r   r   r$   r$   r%   	<setcomp>  r   z3_broadcast_column_specifications.<locals>.<setcomp>r   c                 3   s*   | ]"}t |ttfr|f  n|V  qd S r5   )r^   r   r   )r   argr   r$   r%   	<genexpr>  s   z3_broadcast_column_specifications.<locals>.<genexpr>)r   poprI   )argsZlengthsr$   r   r%   rs     s    rs   ):Z
__future__r   r   r   Znumbersr   Zmathr   rx   Znumpyr'   Zpandasr   Zdask.dataframeZ	dataframer   Z
dask.arrayr   r   Zsixr   Zxarrayr   r	   collectionsr
   r   r   r   r   r   r   r   r   r   r   r   r   Z
resamplingr   r    r   rq   r   	ExceptionZ	dask_cudfobjectr   r4   r7   rL   rD   rE   rb   r   rs   r   r$   r$   r$   r%   <module>   sP   $

E       |7