
    6Dh*A                         S SK Jr  S SKJr  S SKJrJr  S SKJs  J	r
  S SKrS rS rS rS r         SS	 jrSS
 jrSSSSSSSS0 0 SSSSSSSSSSSSSS4S jr\" \\" SS// SQ/ SQSS/SS/S9S9\l        g)    )build_dataframe)make_docstring)choropleth_mapboxscatter_mapboxNc                     U[         R                  -  S-  n[         R                  " [         R                  " U [         R                  -  S-  5      5      nX#4$ )zM
Projects lat and lon to WGS84, used to get regular hexagons on a mapbox map
   )nppiarctanhsin)latlonxys       V/var/www/html/env/lib/python3.13/site-packages/plotly/figure_factory/_hexbin_mapbox.py_project_latlon_to_wgs84r      sA     	beecA


266#++,-A4K    c                     U S-  [         R                  -  nS[         R                  " [         R                  " U5      5      -  [         R                  S-  -
  S-  [         R                  -  nX24$ )zM
Projects WGS84 to lat and lon, used to get regular hexagons on a mapbox map
r      )r	   r
   arctanexp)r   r   r   r   s       r   _project_wgs84_to_latlonr      sR     c'BEE/Cryy##beeai/3
6
>C8Or   c                     SnSU-  SU-  S.nSnS nS n	U" U5      U" U5      -
  [         R                  -  n
X-
  nUS:  a  US-   OUS-  nU	" US	   US	   U
5      nU	" US
   US
   U5      n[        XU5      $ )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                    [         R                  " U [         R                  -  S-  5      n[         R                  " SU-   SU-
  -  5      S-  n[	        [        U[         R                  5      [         R                  * 5      S-  $ )Nr      r   )r	   r   r
   logmaxmin)r   r   radX2s      r   latRad#_getBoundsZoomLevel.<locals>.latRad&   s`    ffS255[3&'CAG,-13ubee$ruuf-11r   c                 l    S[         R                  " X-  U-  5      -  [         R                  " S5      -  $ )Ngffffff?r   )r	   r!   )mapPxworldPxfractions      r   zoom!_getBoundsZoomLevel.<locals>.zoom+   s*    bffU_x788266!9DDr   r   ih  r   r   )r	   r
   r#   )lon_minlon_maxlat_minlat_maxmapDimscale	WORLD_DIMZOOM_MAXr%   r+   latFractionlngDifflngFractionlatZoomlngZooms                  r   _getBoundsZoomLevelr:      s     	
 
 ;u=IH2
E '?VG_4=KG&-kGcMw#EK6(#Yx%8+FG6'?Ig$6DGw**r   c           
         UR                  5       nUR                  5       n	UR                  5       n
UR                  5       nSX-
  -  nX-  nX-  n	X-
  nX-
  nUS:X  a  US:  a  X-  nO US:X  a  US:X  a  [        SS5      u  nnOX-  nU[        R                  " S5      -  n[        R
                  " UU-  5      R                  [        5      nXUU-  -   U-
  S-  -  n
X-
  U-  n X-
  U-  n[        R                  " U 5      R                  [        5      n[        R                  " U5      R                  [        5      n[        R                  " U 5      R                  [        5      n[        R                  " U5      R                  [        5      nUS-   nUS-   nUnUnUU-  UU-  -   nU U-
  S-  SUU-
  S-  -  -   nU U-
  S-
  S-  SUU-
  S-
  S-  -  -   nUU:  nUGc3  [        R                  " UU45      n[        R                  " UU45      n SU:*  UU:  -  SU:*  -  UU:  -  U-  n!SU:*  UU:  -  SU:*  -  UU:  -  U) -  n"[        R                  R                  UUU!   UU!   4S5        [        R                  R                  U UU"   UU"   4S5        Ub,  [        R                  UUU:  '   [        R                  U U U:  '   [        R                  " UR                  5       U R                  5       /5      n#[        R                   " U#5      ) n$GO{Uc  Sn[        R"                  " UU4[$        S	9n['        U5       H  n%['        U5       H
  n&/ UU%U&4'   M     M     [        R"                  " UU4[$        S	9n ['        U5       H  n%['        U5       H
  n&/ U U%U&4'   M     M     ['        [)        U 5      5       H  n%UU%   (       aM  SUU%   s=::  a  U:  a;  O  M!  SUU%   s=::  a  U:  a%  O  M5  UUU%   UU%   4   R+                  UU%   5        MV  MX  MZ  SUU%   s=::  a  U:  d  Ml  O  Mp  SUU%   s=::  a  U:  d  M  O  M  U UU%   UU%   4   R+                  UU%   5        M     ['        U5       HO  n%['        U5       H=  n&UU%U&4   n'[)        U'5      U:  a  U" U'5      UU%U&4'   M(  [        R                  UU%U&4'   M?     MQ     ['        U5       HO  n%['        U5       H=  n&U U%U&4   n'[)        U'5      U:  a  U" U'5      U U%U&4'   M(  [        R                  U U%U&4'   M?     MQ     [        R,                  " UR                  [.        5      R                  5       U R                  [.        5      R                  5       45      n#[        R                   " U#5      ) n$U#U$   n([        R                  " US4[.        5      n)[        R0                  " [        R2                  " U5      U5      U)SUU-  2S4'   [        R4                  " [        R2                  " U5      U5      U)SUU-  2S4'   [        R0                  " [        R2                  " U5      S-   U5      U)UU-  S2S4'   [        R4                  " [        R2                  " U5      U5      S-   U)UU-  S2S4'   U)SS2S4==   U-  ss'   U)SS2S4==   U-  ss'   U)SS2S4==   U-  ss'   U)SS2S4==   U
-  ss'   U)U$   n)/ S
Qn*S[        R6                  " [        R8                  S-  5      -  S[        R:                  " [        R8                  S-  5      -  S[        R:                  " [        R8                  S-  5      -  S[        R6                  " [        R8                  S-  5      -  S[        R:                  " [        R8                  S-  5      -  S[        R:                  " [        R8                  S-  5      -  /n+[)        U)5      n,[        R<                  " U*/U,-  5      U-  [        R>                  " U)SS2S4   5      -   n-[        R<                  " U+/U,-  5      U-  [        R                  " S5      -  [        R>                  " U)SS2S4   5      -   n.U-U.U)U(4$ )a  
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      @      ?N)dtype)r   r=   r=   r         r?   r?      ) r#   r"   r   r	   sqrtceilastypeintroundfloorzerosaddatnanconcatenateravelisnanemptyobjectrangelenappendhstackfloatrepeatarangetilecosr
   tanarrayvstack)/r   r   x_rangey_rangecolornxagg_func	min_countxminxmaxyminymaxpaddingDxDydx_dynyix1iy1ix2iy2nx1ny1nx2ny2nd1d2bdistlattice1lattice2c1c2accum	good_idxsijvalsagreggated_valuecentershxhymhxshyss/                                                  r   _compute_hexbinr   9   sq   L ;;=D;;=D;;=D;;=D $GODOD	B	B	Qw26W	qR1W(A.AW	bggajB	b		 	 	%B 	BG^d"a''D	
RA	
RA
((1+

S
!C
((1+

S
!C
((1+

S
!C
((1+

S
!C
q&C
q&C
C
Cc	C#IA
c'a#SQ.	.B
c'C-A	q3w}&: :	:BGE}88S#J'88S#J'3h39%c2cCi@5H3h39%c2cCi@E6I
		(SWc"g.2
		(SWc"g.2 -/VVHX	)*-/VVHX	)* 0(..2BCDXXe_$	I 88S#Jf5sA3Z!#A    88S#Jf5sA3Z!#A    s1vAQxA$$c!f):s):SVSV^,33E!H= *;$ A$$$c!f):s):):SVSV^,33E!H=  sA3Z1~t9	)%-d^HQTN%'VVHQTN    sA3Z1~t9	)%-d^HQTN%'VVHQTN    		__U#))+X__U-C-I-I-KL
 XXe_$	Y'hh1vu%G ii		#<GKcCiKN ggbiinc:GKcCiKN ii		#(<cBGC#IKN ggbiinc:S@GC#IKNAqDMRMAqDMRMAqDMTMAqDMTMi G 
&Brvvbeeai  rvvbeeai  bffRUUQYbffRUUQYbffRUUQYrvvbeeai  
B 	GA ((B4!8
r
!BIIgadm$<
<C
((B4!8
r
!BGGAJ
.71a4=1I
ICW...r   c	           
         [        X5      u  pUc4  [        R                  " U R                  5       U R	                  5       /5      nUc4  [        R                  " UR                  5       UR	                  5       /5      n[        X#5      u  p[        XXXEXg5      u  pnn[        X5      u  nnUR                  [        5      n[        R                  " USS2S4   USS2S4   S.US9R                  [        R                  " [        R                  " S5      [        R                  " S5      /SS	9S
9R                  S5      nUUUU4$ )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)
nw.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    )x1x2native_namespacer   r   ,)	separator)hexagons_idsr   )r   r	   rZ   r#   r"   r   r   rC   strnw	from_dictselect
concat_strcol
get_column)r   r   	lat_range	lon_ranger^   r_   r`   ra   r   r   r   r\   r]   r   r   r   r   hexagons_latshexagons_lonsr   s                       r   _compute_wgs84_hexbinr      s   b $C-DAHHcggi34	HHcggi34	/	EG*9	g8+'Cg'
 $<C#E M= nnS!G
1a4=16-	
 
R]]BFF4L"&&,+GSVW	X	N	#  -7GGGr   c                 V   / nUc  [         R                  " [        U 5      5      n[        XU5       Hl  u  pEn[         R                  " XT/5      R
                  R                  5       nUR                  US   5        UR                  [        SU[        SU/S9S95        Mn     [        SUS9$ )zW
Creates a geojson of hexagonal features based on the outputs of
_compute_wgs84_hexbin
r   FeaturePolygon)typecoordinates)r   idgeometryFeatureCollection)r   features)	r	   rV   rQ   ziprZ   TtolistrR   dict)r   r   idsr   r   r   idxpointss           r   _hexagons_to_geojsonr   0  s    
 H
{iiM*+]3?#3*%''..0fQi 96(C	
 @ (8<<r      Fc                 r   [        [        5       SS9n[        R                  " US   5      nUc  [        R
                  nUS   R                  [        R                  " US   5      R                  R                  S5      [        R                  " US   5      R                  R                  S5      5      R                  5       R                  5       nUS   R                  [        R                  " US   5      R                  R                  S5      [        R                  " US   5      R                  R                  S5      5      R                  5       R                  5       n[        US   R                  US   5      R                  5       US   R                  US   5      R                  5       UUSUUUUS9	u  nnnn[        UUU5      n UcX  Uc  Uc  [!        S	S	S
9n!O,Uc  Ub  [!        S	US
9n!OUb  Uc  [!        UUS
9n!O
[!        UUS
9n![#        US   US   US   US   U!5      nUc&  [!        UR                  5       UR                  5       S9nUS   b.  [!        US   R%                  US   SS9R'                  5       5      n"OSUS   0n"/ n#U"R)                  5        H  u  n$n%[        U%R                  US   5      R                  5       U%R                  US   5      R                  5       UUUS   (       a"  U%R                  US   5      R                  5       OSUUUUS9	u    n&nn'U#R+                  [        R,                  " U$S   /[/        U5      -  UU'S.US95        M     [        R0                  " U#SS9R3                  [        R4                  " S5      R7                  [        R8                  5      S9n(Uc&  U(S   R                  5       U(S   R                  5       /n[;        S/0 SU(R=                  5       _SU _SS_SS_SSSSS._SUS   b  SOS_SU_SU_S U	_S!U
_S"U_S#U_S$U_S%U_S&U_S'U_S(U_S)U_S*U_S+U_6n)U(       Gau  [?        US   b  US   RA                  US   SSS,9OUS   R=                  5       US   US   US   S-9n*S.U*RB                  S   l"        SU*RB                  S   l#        UU*RB                  S   l$        U)RK                  U*RB                  S   5        US   b  [M        [/        U*RN                  5      5       H  n+S.U*RN                  U+   RB                  S   l"        SU*RN                  U+   RB                  S   l#        UU*RN                  U+   RB                  S   l$        U)RN                  U+   RB                  S   U*RN                  U+   RB                  S   /U)RN                  U+   l!        M     U)$ )0zG
Returns a figure aggregating scattered points into connected hexagons
N)argsconstructor
data_framer   _min_maxr   )	r   r   r   r   r^   r_   r`   ra   r   i  r   r   r    )r   r   animation_frameT)drop_null_keys)r   r^   )frame	locationsr^   r   vertical)how)r^   geojsonr   
hover_dataF)r^   r   r   r   color_discrete_sequencecolor_discrete_maplabelscolor_continuous_scalerange_colorcolor_continuous_midpointopacityr+   centermapbox_styletitletemplater   r   )by
descending
nulls_last)r   r   r   r   skip )(r   localsr   get_native_namespacer	   meanr   r#   namesuffixr"   to_numpysqueezer   r   r   r   r:   group_by__iter__itemsrR   r   rQ   concatwith_columnsr   castInt64r   	to_nativer   sortdata	hoverinfohovertemplatemarker	add_tracerP   frames),r   r   r   r^   
nx_hexagonr`   r   r   r   r   r   r   r   r   r+   r   r   r   r   r   r   ra   show_original_dataoriginal_data_markerr   r   r   r   r   r   r   countr   r1   groupsagg_data_frame_listkeydfrj   aggregated_valueagg_data_framefigoriginal_figr   s,                                               r   create_hexbin_mapboxr   E  s   : d;D..tL/AB77 	\	FF4;$$++F3FF4;$$++F3

 
	  	\	FF4;$$++F3FF4;$$++F3

 
	  9N))$u+6??A))$u+6??A)
95M=, #=-NG|>emC0F^ 1E2FEMv6Fu5F"aL)A,	!ilF
 ~)..*	0@A*Xd,-dXCXZ
 \*+<<>R/Dd5k*335d5k*335=A']"--W.779PT-
0
,1l, 	""LL!!fXL(99!--
 "2		
 ". YY2
CPPffWo""288, Q N %g.224nW6M6Q6Q6ST
 !++-  	
 "F %)):$;$GT !8 .   6   #<     "!" #$ %& '( )C. %
 )*6 \"''-.5T (  ,'ikUU !23
 *0!&-1!*&:!#l''*+!".3|2234;A##A&++A.8?C##A&++A.<8L##A&++A.5 JJqM&&q) ''*//2&

1" 5 Jr   rD   z/Number of hexagons (horizontally) to be created)functionz8Numpy array aggregator, it must take as input a 1D arrayzand output a scalar value.)rD   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`   ra   r   r   )override_dict)	NNNNNNNNN)N)plotly.express._corer   plotly.express._docr   plotly.express._chart_typesr   r   narwhals.stable.v1stablev1r   numpyr	   r   r   r:   r   r   r   r   r   __doc__r   r   r   <module>r      s    0 . I   +>e/R 	
LH^=, 
 "	

1qh  .LM


 Q
 %&EF#   r   