mustafa2ak's picture
Create map_visualization.py
aaeadd9 verified
"""
map_visualization.py - Interactive Map Visualization with Folium
"""
import folium
from folium import plugins
import pandas as pd
from typing import List, Dict, Optional
from datetime import datetime
class DogMapVisualizer:
def __init__(self, default_location: List[float] = [38.9637, 35.2433]):
self.default_location = default_location
self.default_zoom = 13
print(f"✅ Map Visualizer initialized")
print(f" Default location: {default_location}")
def create_map(self, dogs_data: List[Dict]) -> Optional[str]:
if not dogs_data:
return self._create_empty_map()
center_lat = sum(dog['latitude'] for dog in dogs_data) / len(dogs_data)
center_lon = sum(dog['longitude'] for dog in dogs_data) / len(dogs_data)
map_obj = folium.Map(
location=[center_lat, center_lon],
zoom_start=self.default_zoom,
tiles='OpenStreetMap'
)
self.add_markers(map_obj, dogs_data)
self._add_plugins(map_obj)
map_html = map_obj._repr_html_()
return map_html
def _create_empty_map(self) -> str:
map_obj = folium.Map(
location=self.default_location,
zoom_start=self.default_zoom,
tiles='OpenStreetMap'
)
folium.Marker(
location=self.default_location,
popup="No dogs with location data yet",
icon=folium.Icon(color='gray', icon='info-sign')
).add_to(map_obj)
return map_obj._repr_html_()
def add_markers(self, map_obj: folium.Map, dogs: List[Dict]):
for dog in dogs:
lat = dog['latitude']
lon = dog['longitude']
color = self.get_marker_color(dog.get('health_score'))
popup_content = self.create_popup(dog)
folium.Marker(
location=[lat, lon],
popup=folium.Popup(popup_content, max_width=300),
tooltip=dog['name'],
icon=folium.Icon(
color=color,
icon='info-sign',
prefix='glyphicon'
)
).add_to(map_obj)
def create_popup(self, dog_info: Dict) -> str:
dog_id = dog_info['dog_id']
name = dog_info['name']
last_seen = dog_info.get('last_seen', 'Unknown')
sightings = dog_info.get('total_sightings', 0)
health_score = dog_info.get('health_score')
health_status = dog_info.get('health_status')
html = f"""
<div style='font-family: Arial, sans-serif; min-width: 200px;'>
<h4 style='margin: 0 0 10px 0; color: #228be6;'>{name}</h4>
<table style='width: 100%; border-collapse: collapse;'>
<tr>
<td style='padding: 3px 0;'><b>ID:</b></td>
<td style='padding: 3px 0;'>#{dog_id}</td>
</tr>
<tr>
<td style='padding: 3px 0;'><b>Last Seen:</b></td>
<td style='padding: 3px 0;'>{last_seen}</td>
</tr>
<tr>
<td style='padding: 3px 0;'><b>Sightings:</b></td>
<td style='padding: 3px 0;'>{sightings}</td>
</tr>
"""
if health_score is not None:
html += f"""
<tr>
<td style='padding: 3px 0;'><b>Health Score:</b></td>
<td style='padding: 3px 0;'>{health_score:.1f}/10</td>
</tr>
"""
if health_status:
status_color = {
'Healthy': '#51cf66',
'Monitor': '#ffd43b',
'Concern': '#ff6b6b'
}.get(health_status, '#868e96')
html += f"""
<tr>
<td style='padding: 3px 0;'><b>Status:</b></td>
<td style='padding: 3px 0; color: {status_color}; font-weight: bold;'>
{health_status}
</td>
</tr>
"""
html += """
</table>
</div>
"""
return html
def get_marker_color(self, health_score: Optional[float] = None) -> str:
return 'blue'
def _add_plugins(self, map_obj: folium.Map):
plugins.Fullscreen(
position='topright',
title='Expand map',
title_cancel='Exit fullscreen',
force_separate_button=True
).add_to(map_obj)
plugins.MeasureControl(
position='topleft',
primary_length_unit='meters',
secondary_length_unit='kilometers',
primary_area_unit='sqmeters',
secondary_area_unit='hectares'
).add_to(map_obj)
def create_heatmap(self, dogs_data: List[Dict]) -> Optional[str]:
if not dogs_data:
return self._create_empty_map()
center_lat = sum(dog['latitude'] for dog in dogs_data) / len(dogs_data)
center_lon = sum(dog['longitude'] for dog in dogs_data) / len(dogs_data)
map_obj = folium.Map(
location=[center_lat, center_lon],
zoom_start=self.default_zoom,
tiles='OpenStreetMap'
)
heat_data = [[dog['latitude'], dog['longitude']] for dog in dogs_data]
plugins.HeatMap(heat_data).add_to(map_obj)
self._add_plugins(map_obj)
return map_obj._repr_html_()
def create_cluster_map(self, dogs_data: List[Dict]) -> Optional[str]:
if not dogs_data:
return self._create_empty_map()
center_lat = sum(dog['latitude'] for dog in dogs_data) / len(dogs_data)
center_lon = sum(dog['longitude'] for dog in dogs_data) / len(dogs_data)
map_obj = folium.Map(
location=[center_lat, center_lon],
zoom_start=self.default_zoom,
tiles='OpenStreetMap'
)
marker_cluster = plugins.MarkerCluster().add_to(map_obj)
for dog in dogs_data:
lat = dog['latitude']
lon = dog['longitude']
popup_content = self.create_popup(dog)
folium.Marker(
location=[lat, lon],
popup=folium.Popup(popup_content, max_width=300),
tooltip=dog['name']
).add_to(marker_cluster)
self._add_plugins(map_obj)
return map_obj._repr_html_()