B
    &[¨_}=  ã               @   sà   d dl mZ d dlmZ d dlmZmZ d dlZd dl	Z
dd„ Zdd„ Zd	d
„ Zdd„ Zd#dd„Zd$dd„Zddddddddi i ddddddddddddddfdd„Zeeeddgdddgddddgddgdd gd!d"e_dS )%é    )Úbuild_dataframe)Úmake_docstring)Úchoropleth_mapboxÚscatter_mapboxNc             C   s0   |t j d }t  t  | t j d ¡¡}||fS )zU
    Projects lat and lon to WGS84, used to get regular hexagons on a mapbox map
    é´   )ÚnpÚpiZarctanhÚsin)ÚlatÚlonÚxÚy© r   úH/tmp/pip-install-l29rncou/plotly/plotly/figure_factory/_hexbin_mapbox.pyÚ_project_latlon_to_wgs84   s    r   c             C   s>   | d t j }dt  t  |¡¡ t jd  d t j }||fS )zU
    Projects WGS84 to lat and lon, used to get regular hexagons on a mapbox map
    r   é   )r   r   ZarctanÚexp)r   r   r   r
   r   r   r   Ú_project_wgs84_to_latlon   s    (r   c             C   s”   d}d| d| dœ}d}dd„ }dd„ }	||ƒ||ƒ t j }
||  }|d	k rX|d
 n|d
 }|	|d |d |
ƒ}|	|d |d |ƒ}t|||ƒS )zÁ
    Get the mapbox zoom level given bounds and a figure dimension
    Source: https://stackoverflow.com/questions/6048975/google-maps-v3-how-to-calculate-the-zoom-level-for-a-given-bounds
    r   é   )ÚheightÚwidthé   c             S   sH   t  | t j d ¡}t  d| d|  ¡d }tt|t jƒt j ƒd S )Nr   é   r   )r   r	   r   ÚlogÚmaxÚmin)r
   r	   ZradX2r   r   r   ÚlatRad&   s    z#_getBoundsZoomLevel.<locals>.latRadc             S   s    dt  | | | ¡ t  d¡ S )Ngffffffî?r   )r   r   )ZmapPxZworldPxÚfractionr   r   r   Úzoom+   s    z!_getBoundsZoomLevel.<locals>.zoomr   ih  r   r   )r   r   r   )Zlon_minZlon_maxZlat_minZlat_maxÚmapDimZscaleZ	WORLD_DIMZZOOM_MAXr   r   ZlatFractionZlngDiffZlngFractionZlatZoomZlngZoomr   r   r   Ú_getBoundsZoomLevel   s    r    c       /   
   C   sò  |  ¡ }| ¡ }	|  ¡ }
| ¡ }d|	|  }||8 }|	|7 }	|	| }||
 }|dkrf|dkrf|| }n(|dkr†|dkr†tddƒ\}}n|| }|t d¡ }t || ¡ t¡}|
|
||  | d 8 }
| | | } ||
 | }t | ¡ t¡}t |¡ t¡}t 	| ¡ t¡}t 	|¡ t¡}|d }|d }|}|}|| ||  }| | d d|| d   }| | d d d|| d d   }||k }|dkr„t 
||f¡}t 
||f¡} d|k||k @ d|k@ ||k @ |@ }!d|k||k @ d|k@ ||k @ | @ }"tj |||! ||! fd¡ tj | ||" ||" fd¡ |dk	r^tj|||k < tj| | |k < t | ¡ |  ¡ g¡}#t |#¡ }$nl|dkr’d}tj||ftd	}x2t|ƒD ]&}%xt|ƒD ]}&g ||%|&f< q¼W q®W tj||ftd	} x2t|ƒD ]&}%xt|ƒD ]}&g | |%|&f< qW qôW xÞtt| ƒƒD ]Î}%||% ršd||%   krV|k røn n>d||%   krv|k røn n|||% ||% f  ||% ¡ n^d||%   kr¶|k r,n n>d||%   krÖ|k r,n n| ||% ||% f  ||% ¡ q,W x`t|ƒD ]T}%xLt|ƒD ]@}&||%|&f }'t|'ƒ|krF||'ƒ||%|&f< ntj||%|&f< qW qW x`t|ƒD ]T}%xLt|ƒD ]@}&| |%|&f }'t|'ƒ|kr¨||'ƒ| |%|&f< ntj| |%|&f< qxW qjW t | t¡ ¡ |  t¡ ¡ f¡}#t |#¡ }$|#|$ }(t 
|dft¡})t t |¡|¡|)d|| …df< t t |¡|¡|)d|| …df< t t |¡d |¡|)|| d…df< t t |¡|¡d |)|| d…df< |)dd…df  |9  < |)dd…df  |9  < |)dd…df  |7  < |)dd…df  |
7  < |)|$ })ddddd
d
g}*d
t tjd ¡ d
t tjd ¡ dt tjd ¡ dt tjd ¡ dt tjd ¡ d
t tjd ¡ g}+t|)ƒ},t |*g|, ¡| t |)dd…df ¡ }-t |+g|, ¡| t d¡ t |)dd…df ¡ }.|-|.|)|(fS )aQ  
    Computes the aggregation at hexagonal bin level.
    Also defines the coordinates of the hexagons for plotting.
    The binning is inspired by matplotlib's implementation.

    Parameters
    ----------
    x : np.ndarray
        Array of x values (shape N)
    y : np.ndarray
        Array of y values (shape N)
    x_range : np.ndarray
        Min and max x (shape 2)
    y_range : np.ndarray
        Min and max y (shape 2)
    color : np.ndarray
        Metric to aggregate at hexagon level (shape N)
    nx : int
        Number of hexagons horizontally
    agg_func : function
        Numpy compatible aggregator, this function must take a one-dimensional
        np.ndarray as input and output a scalar
    min_count : int
        Minimum number of points in the hexagon for the hexagon to be displayed

    Returns
    -------
    np.ndarray
        X coordinates of each hexagon (shape M x 6)
    np.ndarray
        Y coordinates of each hexagon (shape M x 6)
    np.ndarray
        Centers of the hexagons (shape M x 2)
    np.ndarray
        Aggregated value in each hexagon (shape M)

    g•Ö&è.>r   r   é   r   g      @g      à?N)Zdtypeg      à¿é   ) r   r   r   r   ÚsqrtÚceilÚastypeÚintÚroundÚfloorÚzerosÚaddZatÚnanZconcatenateZravelÚisnanÚemptyÚobjectÚrangeÚlenÚappendZhstackÚfloatÚrepeatÚarangeZtileÚcosr   ÚtanÚarrayZvstack)/r   r   Úx_rangeÚy_rangeÚcolorÚnxÚagg_funcÚ	min_countZxminZxmaxZyminZymaxÚpaddingZDxZDyZdxÚ_ZdyÚnyZix1Ziy1Zix2Ziy2Znx1Zny1Znx2Zny2ÚnZd1Zd2ÚbdistZlattice1Zlattice2Zc1Úc2ÚaccumZ	good_idxsÚiÚjÚvalsÚagreggated_valueÚcentersÚhxZhyÚmÚhxsÚhysr   r   r   Ú_compute_hexbin9   sÀ    &
$
$&


@ @$""&&*4rN   c          	   C   sÊ   t | |ƒ\}}	|dkr,t |  ¡ |  ¡ g¡}|dkrJt | ¡ | ¡ g¡}t ||ƒ\}
}t||	|
|||||ƒ\}}}}t||ƒ\}}| t¡}t	 
|dd…df ¡d t	 
|dd…df ¡ }||||fS )a  
    Computes the lat-lon aggregation at hexagonal bin level.
    Latitude and longitude need to be projected to WGS84 before aggregating
    in order to display regular hexagons on the map.

    Parameters
    ----------
    lat : np.ndarray
        Array of latitudes (shape N)
    lon : np.ndarray
        Array of longitudes (shape N)
    lat_range : np.ndarray
        Min and max latitudes (shape 2)
    lon_range : np.ndarray
        Min and max longitudes (shape 2)
    color : np.ndarray
        Metric to aggregate at hexagon level (shape N)
    nx : int
        Number of hexagons horizontally
    agg_func : function
        Numpy compatible aggregator, this function must take a one-dimensional
        np.ndarray as input and output a scalar
    min_count : int
        Minimum number of points in the hexagon for the hexagon to be displayed

    Returns
    -------
    np.ndarray
        Lat coordinates of each hexagon (shape M x 6)
    np.ndarray
        Lon coordinates of each hexagon (shape M x 6)
    pd.Series
        Unique id for each hexagon, to be used in the geojson data (shape M)
    np.ndarray
        Aggregated value in each hexagon (shape M)

    Nr   ú,r   )r   r   r7   r   r   rN   r   r%   ÚstrÚpdZSeries)r
   r   Ú	lat_rangeÚ	lon_ranger:   r;   r<   r=   r   r   r8   r9   rL   rM   rI   rH   Úhexagons_latsÚhexagons_lonsÚhexagons_idsr   r   r   Ú_compute_wgs84_hexbiná   s    0
0rW   c          
   C   s‚   g }|dkrt  t| ƒ¡}xZt| ||ƒD ]J\}}}t  ||g¡j ¡ }| |d ¡ | td|td|gdd¡ q(W td|dS )	zc
    Creates a geojson of hexagonal features based on the outputs of
    _compute_wgs84_hexbin
    Nr   ZFeatureZPolygon)ÚtypeZcoordinates)rX   ÚidZgeometryZFeatureCollection)rX   Úfeatures)	r   r4   r0   Úzipr7   ÚTÚtolistr1   Údict)rT   rU   ÚidsrZ   r
   r   ÚidxZpointsr   r   r   Ú_hexagons_to_geojson(  s    ra   é   Fc       ,      C   s¾  t tƒ dd}|dkrtj}|d |d   ddg¡j}|d |d   ddg¡j}t|d |d  j|d |d  j||d|||d\}}}}t|||ƒ}|dkr0|dkrÄ|dkrÄtd	d	d
} nL|dkrâ|dk	râtd	|d
} n.|dk	r|dkrt||d
} nt||d
} t	|d |d |d |d | ƒ}|dkrNt| ¡ | ¡ d}|d dk	rr|d  
|d ¡j}!nd|d ji}!g }"x’|! ¡ D ]†\}#}$|d j|$ }%t|%|d  j|%|d  j|||d rÚ|%|d  jnd|||d\}&}&}}'|" tjtj||'f ddgd¡ qŽW tj|"d|! ¡ djdd d¡}(t |(d ¡|(d< |dkrn|(d  ¡ |(d  ¡ g}t|(|ddddddœ|d dk	r”dnd|||	|
||||||||||d})|rºt|d dk	râ|d j|d dn|d |d |d |d d}*d|*jd _d|*jd _||*jd _ |) !|*jd ¡ |d dk	rºxvt"t#|*j$ƒƒD ]d}+d|*j$|+ jd _d|*j$|+ jd _||*j$|+ jd _ |)j$|+ jd |*j$|+ jd g|)j$|+ _qRW |)S )zP
    Returns a figure aggregating scattered points into connected hexagons 
    N)ÚargsÚconstructorÚ
data_framer
   r   r   r   )r
   r   rR   rS   r:   r;   r<   r=   iÂ  )r   r   r   r   )r
   r   Úanimation_framer:   Ú	locations)Úcolumns)ZaxisÚkeys)ÚframeÚindex)rk   rj   TF)r:   rg   rj   )re   Úgeojsonrg   r:   Z
hover_datarf   Úcolor_discrete_sequenceÚcolor_discrete_mapÚlabelsÚcolor_continuous_scaleÚrange_colorÚcolor_continuous_midpointÚopacityr   ÚcenterÚmapbox_styleÚtitleÚtemplater   r   )Zby)re   r
   r   rf   Úskip)%r   Úlocalsr   ZmeanZaggÚvaluesrW   ra   r^   r    ÚgroupbyÚgroupsrk   ÚitemsÚlocr1   rQ   Z	DataFrameZc_Úconcatri   Zrename_axisZreset_indexZ
to_numericr   r   r   r   Zsort_valuesÚdataZ	hoverinfoZhovertemplateÚmarkerZ	add_tracer/   r0   Úframes),re   r
   r   r:   Ú
nx_hexagonr<   rf   rm   rn   ro   rp   rq   rr   rs   r   rt   ru   rv   rw   r   r   r=   Úshow_original_dataÚoriginal_data_markerrc   rR   rS   rT   rU   rV   Úcountrl   r   r|   Zagg_data_frame_listrj   rk   Zdfr?   Zaggregated_valueZagg_data_frameZfigZoriginal_figrE   r   r   r   Úcreate_hexbin_mapbox=  s¶    

 

" r‡   r&   z/Number of hexagons (horizontally) to be createdÚfunctionz8Numpy array aggregator, it must take as input a 1D arrayzand output a scalar value.z=Minimum number of points in a hexagon for it to be displayed.z3If None and color is not set, display all hexagons.zDIf None and color is set, only display hexagons that contain points.ÚboolzCWhether to show the original data on top of the hexbin aggregation.r^   zScattermapbox marker options.)rƒ   r<   r=   r„   r…   )Zoverride_dict)NNNNNNNN)N)Zplotly.express._corer   Zplotly.express._docr   Zplotly.express._chart_typesr   r   Znumpyr   ZpandasrQ   r   r   r    rN   rW   ra   r‡   r^   Ú__doc__r   r   r   r   Ú<module>   sr   		 *       
?
 