
    g|=                         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 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_        y)    )build_dataframe)make_docstring)choropleth_mapboxscatter_mapboxNc                     |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       a/var/www/dash_apps/app1/venv/lib/python3.12/site-packages/plotly/figure_factory/_hexbin_mapbox.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   9   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z   t        j                  |dddf         z   }||||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	   rX   r#   r"   r   r   rA   strpdSeries)r   r   	lat_range	lon_ranger\   r]   r^   r_   r   r   rZ   r[   r   r   r   r   hexagons_latshexagons_lonshexagons_idss                      r   _compute_wgs84_hexbinr      s    ` $C-DAqHHcggi34	HHcggi34	/	9EGW*9	1gwr8Y+'Cg'
 $<C#E M= nnS!G99WQT]+c1BIIgadm4LLL-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   (  s    
 H
{iiM*+]M3? 	
S#3*%''..0fQi 96(C	
	
 (8<<r      Fc                    t        t               d      }|t        j                  }|d   |d      j	                  ddg      j
                  }|d   |d      j	                  ddg      j
                  }t        |d   |d      j
                  |d   |d      j
                  ||d|||      \  }}}}t        |||      }|^||t        d	d	
      } n1||t        d	|
      } n||t        ||
      } nt        ||
      } t        |d   |d   |d   |d   |       }|)t        |j                         |j                               }|d   "|d   j                  |d         j                  }!nd|d   j                  i}!g }"|!j                         D ]  \  }#}$|d   j                  |$   }%t        |%|d      j
                  |%|d      j
                  |||d   r|%|d      j
                  nd|||      \  }&}&}}'|"j                  t!        j"                  t        j$                  ||'f   ddg              t!        j&                  |"d|!j)                               j+                  d      j-                  d      }(t!        j.                  |(d         |(d<   |&|(d   j1                         |(d   j3                         g}t5        d,i d|(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(|})|rgt7        |d   |d   j9                  |d   )      n|d   |d   |d   |d   *      }*d+|*j:                  d   _        d|*j:                  d   _        ||*j:                  d   _         |)jC                  |*j:                  d          |d   tE        tG        |*jH                              D ]  }+d+|*jH                  |+   j:                  d   _        d|*jH                  |+   j:                  d   _        ||*jH                  |+   j:                  d   _         |)jH                  |+   j:                  d   |*jH                  |+   j:                  d   g|)jH                  |+   _         |)S )-zO
    Returns a figure aggregating scattered points into connected hexagons
    N)argsconstructor
data_framer   r#   r"   r   )r   r   r   r   r\   r]   r^   r_   i  r   r   r    )r   r   animation_framer\   	locations)columns)axiskeys)frameindex)r   r   geojson
hover_dataTF)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)r   r   r   r   skip )%r   localsr	   meanaggvaluesr   r   r   r8   groupbygroupsr   itemslocrP   r   	DataFramec_concatr   rename_axisreset_index
to_numericr#   r"   r   r   sort_valuesdata	hoverinfohovertemplatemarker	add_tracerN   rO   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   countr   r/   r   agg_data_frame_listr   r   dfrh   aggregated_valueagg_data_framefigoriginal_figr}   s,                                               r   create_hexbin_mapboxr   =  sO   : d;D77\"4;/33UENCJJI\"4;/33UENCJJI8MtE{+22tE{+22	95M=, #=-NG|>emC0F^ 1E2FEMv6Fu5F"aL)A,	!ilF
 ~)..*	0@A*l#++D1B,CDKKT,'--. 
u,##E*/D4;&&4;&&.27m"T']#**	0
,1l, 	""LLl$445W?U	

$ 			%AFKKMB	-	.	W	  !mmN7,CDN7%g.224nW6M6Q6Q6ST
 !  	
 "F %)):$;$GT !8 .   6   #<     "!" #$ %& '( )C. % )*6 \"..$7H2I.J,'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Scattermapbox marker options.)r   r^   r_   r   r   )override_dict)NNNNNNNN)N)plotly.express._corer   plotly.express._docr   plotly.express._chart_typesr   r   numpyr	   pandasr   r   r   r8   r   r   r   r   r   __doc__r   r   r   <module>r      s    0 . I  +>e/R 	
DHN=, 
 "	

1Wt  .LM

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