
    1i%E                     t   d Z ddlZddlZddlZddlZddlmZ ddlZddl	Z
ddlm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 ddlmZ d	Zd
 Zd Zd Zd Zd Z e!dk(  r% ejD                  d      Z#e#jI                  dd       e#jI                  ddde d       e#jK                         Z&e&jN                  jQ                         Z'	  ee&jR                        Z)e)dz   dZ. ed      e'z  e' dz  Z/ ed      e'z  e' d e. d!z  Z0e/jb                  Z2e/jg                         s e,d"e/         ejZ                  d       e0jg                         s e,d#e0         ejZ                  d        e,d$e'ji                          d%        ejj                  e/d&'      Z6 ejj                  e0d(e. '      Z7d) Z8d*e6jr                  v rAe6d*   ju                  e8      e6d+<    e,d,e6d+   jw                         jy                                 d- Z=d.e6jr                  v rAe6d.   ju                  e=      e6d/<    e,d0e6d/   jw                         jy                                 d/d+gZ> e,d1        e,d2        e,d3       e>D ]  Z?e?e6jr                  vr e,d4e? d5        e,d6d7         e,d8e?         e,d7        e6e?   j                         j                         ZBe6e?   jw                         Z; e,d9 eCeB       d:        eDeB      D ]$  ZEe;j                  eEd      ZG e,d;eE d<eGd=d>       & eBD ]>  ZH e,d?e? d@eH         ee6e7j                         e?eH      \  ZJZKZLeJ1 e eJe?eHe'e2e.e)       @   e,dA        e,dB        e,d7       yy# e*$ r(Z+ e,de+         ejZ                  d       Y dZ+[+dZ+[+ww xY w)Ca  
Generate rasterized density heatmaps (GeoTIFF + PNG) for roads with specific attribute values.

Instead of aggregating all roads per cell, this creates SEPARATE density heatmaps for each
distinct attribute value, showing where roads with that specific characteristic are concentrated.

Outputs:
 - {location}_{attribute}_{value}_density_{size}.tif - Raster density map
 - {location}_{attribute}_{value}_density_{size}.png - Visualization
 - {location}_{attribute}_{value}_density_{size}_hotspots_{area}km2.geojson - Contours

Examples:
 - egypt_highway_motorway_density_2km.tif (density of motorway roads)
 - egypt_highway_primary_density_2km.tif (density of primary roads)
 - egypt_bridge_yes_density_2km.tif (density of bridge roads)
 - egypt_lanes_2_density_2km.tif (density of 2-lane roads)
    N)Path)	rasterize)from_origin)	colormaps)measure)PolygonGRID_CELL_SIZE_METERSc                     | xs t        j                  t              }|t        dt         d      	 t	        |      S # t        $ r}t        d| dt         d      |d}~ww xY w)z8Resolve cell size from CLI args or environment variable.Nz8Cell size must be passed as an argument or provided via .zInvalid cell size 'z'. Provide an integer or set )osgetenvCELL_SIZE_ENV_VAR
ValueErrorint)explicit_value	raw_valueexcs      5/data2/heatmap/scripts/generate_attribute_heatmaps.pyresolve_cell_sizer   '   s}    >")),=">IFGXFYYZ[
 	
9~ !),IJ[I\\]^
	s   
? 	A$AA$c                    t        d| d| d       t        j                  |      r| | |   j                            }n| | |   |k(     }|j                  rt        d| d|        yt        dt	        |      dd| d|        |j                         j                  d	d
i      }	 t        j                  |dg   |d
dg   d      }|j                  j                  |d<   |j                  d
      d   j                         }|d
   j                  |      j                  d      |d<   |j!                  d
g      j#                  |j$                        }	|	|	d   dkD     j'                         }
|
j                  rt        d| d| d       yt        dt	        |
      ddt	        |	      dd       |
d|	fS # t        $ r}t        d|        Y d}~yd}~ww xY w)zVCalculate road length density per grid cell for roads with a specific attribute value.u   📊 Computing density for =...u      ⚠️ No roads found with )NNNu      ✅ Found ,z roads with indexcell_id)columnsgeometryintersection)howu+      ⚠️ Failed to compute intersections: Nlength_mr   u       ⚠️ No grid cells contain  roadsu      📍 Cropped to z cells (out of z total))printpdisnaemptylenreset_indexrenamegpdoverlay	Exceptionr   lengthgroupbysummapfillnadrop	set_indexr   copy)roadsgridattrvaluefiltered_roads
grid_localintersectionsr   groupedgrid_resultgrid_with_roadss              r   calculate_density_for_valuer>   9   s   	'vQugS
9: 
wwu~uT{//12uT{e34.tfAeW=>	M#n-a0TF!E7
KL !!#**GY3G*HJ J<(	:./
 !. 6 6 = =M* ##I.z:>>@G (	266w?FFqIJz//9+/6@@LK "+j"9A"=>CCEO0awfEF	O 4Q7s;GWXYFZZa
bcJ33/   ;C5AB s   )!F: :	GGGc                    || j                   vrt        d| d      | j                  t        d      | j                  \  }}}}t	        t        j                  ||z
  |z              }t	        t        j                  ||z
  |z              }	|dk  s|	dk  rt        d      t        ||||      }
g }t        | j                  | |         D ]I  \  }}|%t        |t              rt        j                  |      r.|j                  |t        |      f       K |st        d|        yt        ||	|f|
t         j"                  d	      }t%        j&                  |d
d|	|dd| j                  j)                         |
t         j"                  
      5 }|j+                  |j-                  d      d       ddd       y# 1 sw Y   yxY w)z1Rasterize the attribute grid and save as GeoTIFF.zColumn 'z' not found in grid.Nz-Grid CRS is undefined; cannot export GeoTIFF.r   z5Invalid grid bounds; cannot derive raster dimensions.u&   ⚠️ No valid data to rasterize for float32)shapes	out_shape	transformfilldtypewGTiff   )driverheightwidthcountrE   crsrC   nodata)r   r   rM   total_boundsr   mathceilr   zipr   
isinstancefloatisnanappendr"   r   npnanrasterioopento_wktwriteastype)r5   attr_col	cell_sizeout_pathminxminymaxxmaxyrK   rJ   rC   rA   geomr7   rasterdsts                   r   save_attribute_geotiffrh   p   s   t||#8H:-ABCCxxHII!..D$d		4$;)345ED4K9456FzVq[PQQD$	9=IF4==$x.9e=Zu5$**U:KtU5\*+ :
 6xjAB5/VVF 
HHOOvv
 
		&--	*A.
 
 
s   "F99Gc                    t        j                  |       5 }|j                  d      j                  d      }|j                  }|)t        j                  ||k(  t
        j                  |      }n8t        j                  t        j                  |      |t
        j                        }|j                  }|j                  }ddd       t        d         }t        |d         }||z  }	|	dz  }
||
z  }t        j                  |         }t        |      dk(  ryt        j                  |      ddd   }t        t        |      t        |      dz
        }||   }t        j                  t        j                  |      ||k\  z  dd      j                  t
        j                         }t#        j$                  |d	      }|syg }|D ]  }g }|D ]4  \  }}|d
   ||d   z  z   }|d   ||d   z  z   }|j'                  ||f       6 t        |      dk\  sM	 t)        |      }|j*                  r|j,                  s|j'                  |        |syg }t1        |d      D ])  \  }}|j2                  dz  }|j'                  |||d       + t5        j6                  |d      }|j                  r/|j                  j9                         dk7  r|j;                  d      }|S # 1 sw Y   xY w# t.        $ r Y 0w xY w)zPExtract smooth contours from a GeoTIFF at a threshold that captures target area.rH   r@   Nr      i@B g      ?)level         )start)
cluster_idarea_km2r   r   )r   rM   i  )epsg)rY   rZ   readr]   rN   rW   whererX   isfiniterC   rM   absr&   sortminr   uint8r   find_contoursrV   r   is_validis_emptyr+   	enumeratearear)   GeoDataFrameto_epsgto_crs)tif_pathtarget_area_km2srcdatarN   rC   rM   pixel_widthpixel_heightpixel_area_m2pixel_area_km2target_pixels
valid_datasorted_valuesthreshold_idx	thresholdbinary_maskcontourspolygonscontourcoordsrowcolxypolyclustersidxre   rr   gdfs                                  r   extract_contours_from_geotiffr      s   	x	 Cxx{!!),88DFNBFFD9D88BKK-tRVV<DMM	gg 
! il#Ky|$L,.M"Y.N#n4Mbkk$'(J
:!GGJ'"-MM*C,>,BCMm,I ((2;;t,	0ABAqIPPQSQYQYZK$$[<H HHC!sYq\11A!sYq\11AMM1a&!  
 v;!v==OOD)   Hxq1	T99y( 
 	 2 

8jc
BC ww377??$,jjdj#JI 
!	 \  s   B(K4K(K%(	K54K5c                    t        |      j                  dd      j                  dd      j                  dd      }| d| d| d| }t        j                  d      \  }	}
|	j                  j                  d       |
j                  d       | j                         j                  }|j                          d	| d
| d| d}| d   j                         j                  s)t        j                  | d   j                         ddg      nd\  }}t        j                  d      j                         }|j!                  d       | j#                  d|d|
d||ddddddi	       |j#                  |
dd       | j$                  }dt'        |d   |d   z
  |d    |d!   z
        z  }|
j)                  |d   |z
  |d   |z          |
j+                  |d!   |z
  |d    |z          |
j-                  |d"d#$       |
j/                  d%       t        j0                          || d&z  }t        j2                  |d'd(|	j5                         )       t        j6                  |	       t9        d*|j:                          || d+z  }	 t=        | d||       t9        d,|j:                          t?        tA        jB                  d-d.            }tE        ||      }|Z|j                  sM|| d0tG        |       d1z  }|jI                  |d23       t9        d4|j:                   d5tK        |       d6       y/y/y/# tL        $ r}t9        d7|        Y d/}~y/d/}~ww xY w)8zQPlot and save heatmap for roads with specific attribute value, cropped to extent./_ :	_density_)   
   )figsizewhiteu    — r   z Road Density ()r    rn   _   )r   rH   hot)colorr   TzRoad Length (m)g333333?g{Gz?)labelshrinkpadr   )	columncmap	linewidthaxlegendvminvmaxlegend_kwdsmissing_kwdsblackg      ?)r   r   r   g?rm   ro   rH      r   )fontsizer   offz.pngi,  tight)dpibbox_inches	facecoloru      💾 Saved PNG: z.tifu      🗺️ Saved GeoTIFF: HOTSPOT_TARGET_AREA_KM2500N
_hotspots_zkm2.geojsonGeoJSON)rI   u      📍 Saved GeoJSON: z (z	 regions)u*      ⚠️ Could not save GeoTIFF/GeoJSON: )'strreplacepltsubplotspatchset_facecolordissolveboundary
capitalizedropnar%   rW   nanpercentiler   get_cmapr3   set_badplotrO   maxset_xlimset_ylim	set_titleaxistight_layoutsavefigget_facecolorcloser"   namerh   rT   r   r   r   r   to_filer&   r+   )r5   r6   r7   locationsave_dir
size_labelr_   	value_str	base_namefigr   extent_outlinetitler   r   cmap_objboundsmarginout_pngout_tiftarget_areacontours_gdfout_geojsones                           r   plot_and_save_density_heatmapr      s]   
 E
""3,44S#>FFsCPI*AdV1YKyEIll8,GCIIG$W ]]_--N""$%U4&%
|STUE NRR\M]MdMdMfMlMl!!$z"2"9"9";aWErxJD$!!%(--/H7#II/3tLw'  
 2W< FCq	F1I-vay6!9/DEEFKKq	F"F1I$67KKq	F"F1I$67LLL,GGEN I;d++GKKSgARARATUIIcN	~
./ I;d++G@tZGD*7<<.9: BII&?GH4WkJ#L,>,>"	{*S=M<Nk%ZZK  Y ?+K,<,<+=RL@Q?RR[\] -?#  @:1#>??@s   ?B+L- -	M6M		M__main__zFGenerate grid-based attribute heatmaps (GeoTIFF + PNG) for a location.)descriptionr   z/Location name (e.g., alabama, egypt, thailand).)helpr_   ?z.Grid cell size in meters. Defaults to env var z
 if unset.)nargsr   u   ❌ rH   i  kmoutputz_roads_projected.gpkg_grid_z.gpkgu   ❌ Roads file not found: u   ❌ Grid file not found: u$   📦 Loading road and grid data for r   roads_projected)layergrid_c                     t        j                  |       ryt        |       j                         j	                         }g d}g d}|D ]  }||v s y |D ]  }||v s y y)z?Categorize surface into paved/unpaved based on string matching.N)asphaltconcretecementpavedpaving_stonessettcobblestonebrickmetalwoodchipsealtartan	boardwalktileplasticrubberacrylic	composite)unpaveddirtgravelsandgroundearthsoil	compactedrockstonegrassmudclayscreepebbleshalewoodchipmulchshellscinderdecomposed_granitecrushed_stonefine_graveltrailr   r  unknownr#   r$   r   lowerstrip)surface_valsurface_lowerpaved_keywordsunpaved_keywordskeywords        r   categorize_surfacer.  _  so    77;K(..0668

 &G-' &
 (G-'  (
     surfacesurface_categoryu   📊 Surface categories: c                     t        j                  |       ryt        |       j                         j	                         }h d}ddh}h d}h d}||v ry||v ry||v ry	||v ry
y)z,Categorize highway into major network types.N>   roadtrunkprimaryservicemotorwaytertiary	secondary
trunk_linkresidentialprimary_linkunclassifiedmotorway_linktertiary_linksecondary_linkcyclewaybicycle_road>   stepsfootwaycorridorcrossingsidewalk	bridleway
pedestrian>   pathtrackr$  drivebikewalkhiker%  r&  )highway_valhighway_lowerdrive_types
bike_types
walk_types
hike_typess         r   categorize_highwayrV    s    77;K(..0668
 






 K'j(j(j(r/  highwayhighway_categoryu   📊 Highway categories: u6   🎯 Generating density heatmaps for major categories:z:   - highway_category: network type (drive/bike/walk/hike)z3   - surface_category: surface type (paved/unpaved)u   
⚠️ Skipping z - not found in data
z<============================================================u   🔍 Processing attribute: u      📋 Categories found (z):z      - z: r   r!   u   
   🎯 Processing: r   z=
============================================================uC   ✅ All attribute-specific density heatmaps generated successfully!)M__doc__argparserP   r   syspathlibr   	geopandasr)   pandasr#   matplotlib.pyplotpyplotr   numpyrW   rY   rasterio.featuresr   rasterio.transformr   
matplotlibr   skimager   shapely.geometryr   r   r   r>   rh   r   r   __name__ArgumentParserparseradd_argument
parse_argsargsr   r'  r_   r   errr"   exitr   gdf_path	grid_pathparentr   existsr   	read_filer4   r5   r.  r   applyvalue_countsto_dictrV  attributes_to_analyzer6   r   uniqueunique_valuesr&   sortedvalgetrL   r7   r3   grid_croppedr   	grid_full r/  r   <module>r     sP  $   	 
       ' *    $+ $14n-/fFXC@R z$X$$\F 
)Z[
%%6$7zC   D}}""$H%dnn5	 tO$B'JH~(hZ7L+MMHX)xjzl%,PPIH??*8*56))56	01D1D1F0Gs
KLCMM(*;<E3==E**>?D!H EMM!$))$4$:$:;M$N !)%0B*C*P*P*R*Z*Z*\)]^_(V EMM!$))$4$:$:;M$N !)%0B*C*P*P*R*Z*Z*\)]^_
 	
 
BD	FH	?A &u}}$&tf,@AB6(m+D623 d**,335T{//1*3}+=*>bAB-(C $$S!,EHSEE!9F34 )
 #E*4&%9: ,Gudiik[_af+g(L#y# *dE8Xz9 #' &D 
-	
OP	&Ma    SEls   N
 
N7N22N7