
    .iMC                        d dl mZ d dlmZ d dlmZmZ d dlmc m	Z
 d dlZd dlZd Zd Zd Zd Z	 	 	 	 	 	 	 	 	 dd	Z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Z ee eddgg dg dddgddg            e_        d Zy)    )build_dataframe)make_docstring)choropleth_mapscatter_mapNc                     |t         j                  z  dz  }t        j                  t        j                  | t         j                  z  dz              }||fS )zU
    Projects lat and lon to WGS84, used to get regular hexagons on a mapbox map
       )nppiarctanhsin)latlonxys       ^/opt/house_gps_flutter/.venv/lib/python3.12/site-packages/plotly/figure_factory/_hexbin_map.py_project_latlon_to_wgs84r   	   sC     	beecA


266#++,-Aa4K    c                     | dz  t         j                  z  }dt        j                  t        j                  |            z  t         j                  dz  z
  dz  t         j                  z  }||fS )zU
    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      sT     c'BEE/Cryy##beeai/3
6
>C8Or   c                     d}d|z  d|z  d}d}d }d }	 ||       ||      z
  t         j                  z  }
|| z
  }|dk  r|dz   n|dz  } |	|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                    t        j                  | t         j                  z  dz        }t        j                  d|z   d|z
  z        dz  }t	        t        |t         j                        t         j                         dz  S )Nr      r   )r	   r   r
   logmaxmin)r   r   radX2s      r   latRadz#_getBoundsZoomLevel.<locals>.latRad'   s`    ffS255[3&'CAG,-13ubee$ruuf-11r   c                 j    dt        j                  | |z  |z        z  t        j                  d      z  S )Ngffffff?r   )r	   r!   )mapPxworldPxfractions      r   zoomz!_getBoundsZoomLevel.<locals>.zoom,   s,    bffUW_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   _getBoundsZoomLevelr8      s     	
 
 ;u=IH2
E '?VG_4=KG&-kGcMw#EK6(#Yx%8+FG6'?Ig$6DGw**r   c           
      P   |j                         }|j                         }	|j                         }
|j                         }d|	|z
  z  }||z  }|	|z  }	|	|z
  }||
z
  }|dk(  r|dkD  r||z  }n|dk(  r|dk(  rt        dd      \  }}n||z  }|t        j                  d      z  }t        j
                  ||z        j                  t              }|
|
||z  z   |z
  dz  z  }
| |z
  |z  } ||
z
  |z  }t        j                  |       j                  t              }t        j                  |      j                  t              }t        j                  |       j                  t              }t        j                  |      j                  t              }|dz   }|dz   }|}|}||z  ||z  z   }| |z
  dz  d||z
  dz  z  z   }| |z
  dz
  dz  d||z
  dz
  dz  z  z   }||k  }|.t        j                  ||f      }t        j                  ||f      } d|k  ||k  z  d|k  z  ||k  z  |z  }!d|k  ||k  z  d|k  z  ||k  z  | z  }"t        j                  j                  |||!   ||!   fd       t        j                  j                  | ||"   ||"   fd       |,t        j                  |||k  <   t        j                  | | |k  <   t        j                  |j                         | j                         g      }#t        j                   |#       }$nP|d}t        j"                  ||ft$        	      }t'        |      D ]  }%t'        |      D ]	  }&g ||%|&f<     t        j"                  ||ft$        	      } t'        |      D ]  }%t'        |      D ]	  }&g | |%|&f<     t'        t)        |             D ]  }%||%   rDd||%   cxk  r|k  sn d||%   cxk  r|k  s)n ,|||%   ||%   f   j+                  ||%          Ld||%   cxk  r|k  s[n ^d||%   cxk  r|k  smn p| ||%   ||%   f   j+                  ||%           t'        |      D ]J  }%t'        |      D ]:  }&||%|&f   }'t)        |'      |k\  r ||'      ||%|&f<   &t        j                  ||%|&f<   < L t'        |      D ]J  }%t'        |      D ]:  }&| |%|&f   }'t)        |'      |k\  r ||'      | |%|&f<   &t        j                  | |%|&f<   < L t        j,                  |j                  t.              j                         | j                  t.              j                         f      }#t        j                   |#       }$|#|$   }(t        j                  |dft.              })t        j0                  t        j2                  |      |      |)d||z  df<   t        j4                  t        j2                  |      |      |)d||z  df<   t        j0                  t        j2                  |      dz   |      |)||z  ddf<   t        j4                  t        j2                  |      |      dz   |)||z  ddf<   |)dddfxx   |z  cc<   |)dddfxx   |z  cc<   |)dddfxx   |z  cc<   |)dddfxx   |
z  cc<   |)|$   })g d
}*dt        j6                  t        j8                  dz        z  dt        j:                  t        j8                  dz        z  dt        j:                  t        j8                  dz        z  dt        j6                  t        j8                  dz        z  dt        j:                  t        j8                  dz        z  dt        j:                  t        j8                  dz        z  g}+t)        |)      },t        j<                  |*g|,z        |z  t        j>                  |)dddf         z   }-t        j<                  |+g|,z        |z  t        j                  d      z  t        j>                  |)dddf         z   }.|-|.|)|(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      @      ?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   :   s   L ;;=D;;=D;;=D;;=D t$GGODGOD	B	B	Qw26"W	qR1W(A.A"W	bggajB	b		 	 	%B 	TBG^d"a''D	
TRA	
T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	           
         t        | |      \  }	}
|3t        j                  | j                         | j	                         g      }|3t        j                  |j                         |j	                         g      }t        ||      \  }}t        |	|
||||||      \  }}}}t        ||      \  }}|j                  t              }t        j                  |dddf   |dddf   d|      j                  t        j                  t        j                  d      t        j                  d      gd	      
      j                  d      }||||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)
    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	   rX   r#   r"   r   r   rA   strnw	from_dictselect
concat_strcol
get_column)r   r   	lat_range	lon_ranger\   r]   r^   r_   r   r   r   rZ   r[   r   r   r   r   hexagons_latshexagons_lonsr   s                       r   _compute_wgs84_hexbinr      s/   b $C-DAqHHcggi34	HHcggi34	/	9EGW*9	1gwr8Y+'Cg'
 $<C#E M= nnS!G
1a4=16-	
 
R]]BFF4L"&&,+GSVW	X	N	#  -7GGGr   c                 d   g }|t        j                  t        |             }t        | ||      D ]r  \  }}}t        j                  ||g      j
                  j                         }|j                  |d          |j                  t        d|t        d|g                   t t        d|      S )zc
    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	   rT   rO   ziprX   TtolistrP   dict)r   r   idsr   r   r   idxpointss           r   _hexagons_to_geojsonr   1  s    
 H
{iiM*+]M3? 	
S#3*%''..0fQi 96(C	
	
 (8<<r      Fc                 ~   t        t               d      }t        j                  |d         }|t        j
                  }|d   j                  t        j                  |d         j                  j                  d      t        j                  |d         j                  j                  d            j                         j                         }|d   j                  t        j                  |d         j                  j                  d      t        j                  |d         j                  j                  d            j                         j                         }t        |d   j                  |d         j                         |d   j                  |d         j                         ||d||||	      \  }}}}t        |||      } |^||t!        d	d	
      }!n1||t!        d	|
      }!n||t!        ||
      }!nt!        ||
      }!t#        |d   |d   |d   |d   |!      }|)t!        |j                         |j                               }|d   1t!        |d   j%                  |d   d      j'                               }"nd|d   i}"g }#|"j)                         D ]  \  }$}%t        |%j                  |d         j                         |%j                  |d         j                         |||d   r"|%j                  |d         j                         nd||||	      \  }&}&}}'|#j+                  t        j,                  |$d   gt/        |      z  ||'d|              t        j0                  |#d      j3                  t        j4                  d      j7                  t        j8                              }(|&|(d   j                         |(d   j                         g}t;        d/i d|(j=                         d| dddddddddd|d   dndd|d|d |	d!|
d"|d#|d$|d%|d&|d'|d(|d)|d*|d+|})|rwt?        |d   |d   jA                  |d   dd,      n|d   j=                         |d   |d   |d   -      }*d.|*jB                  d   _"        d|*jB                  d   _#        ||*jB                  d   _$        |)jK                  |*jB                  d          |d   tM        t/        |*jN                              D ]  }+d.|*jN                  |+   jB                  d   _"        d|*jN                  |+   jB                  d   _#        ||*jN                  |+   jB                  d   _$        |)jN                  |+   jB                  d   |*jN                  |+   jB                  d   g|)jN                  |+   _!         |)S )0zO
    Returns a figure aggregating scattered points into connected hexagons
    N)argsconstructor
data_framer   _min_maxr   )	r   r   r   r   r\   r]   r^   r_   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	map_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   r8   group_by__iter__itemsrP   r   rO   concatwith_columnsr   castInt64r   	to_nativer   sortdata	hoverinfohovertemplatemarker	add_tracerN   frames),r   r   r   r\   
nx_hexagonr^   r   r   r   r   r   r   r   r   r*   r   r   r   r   r   r   r_   show_original_dataoriginal_data_markerr   r   r   r   r   r   r   countr   r/   groupsagg_data_frame_listkeydfrh   aggregated_valueagg_data_framefigoriginal_figr}   s,                                               r   create_hexbin_mapr   F  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 7#'')7#'')

  !++-  	
 "F %)):$;$GT !8 .   6   #<     !" #$ %& '( )C. " )*6 \"''-.$# (  ,'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" Jr   rB   z/Number of hexagons (horizontally) to be created)functionz8Numpy array aggregator, it must take as input a 1D arrayzand output a scalar value.)rB   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Scattermap marker options.)r   r^   r_   r   r   )override_dictc                      t        j                  ddt               d|v r|j                  d      |d<   t	        | i |S )Nzcreate_hexbin_mapbox() is deprecated and will be removed in the next major version. Please use create_hexbin_map() instead. Learn more at: https://plotly.com/python/mapbox-to-maplibre/r   )
stacklevelcategorymapbox_styler   )warningswarnDeprecationWarningpopr   )r   kwargss     r   create_hexbin_mapboxr     sI    MM	I # $jj8{d-f--r   )	NNNNNNNNN)N)plotly.express._corer   plotly.express._docr   plotly.express._chart_typesr   r   narwhals.stable.v1stablev1r   numpyr	   r   r   r   r8   r   r   r   r   r   __doc__r   r   r   r   <module>r     s    0 . C    +>e/R 	
LH^=, 
 "	

1vr +LM


 Q
 %&BC#  0.r   