Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -8,20 +8,73 @@ from jinja2 import Template
|
|
| 8 |
|
| 9 |
# 1. Districts and Coordinates (Harimo Kigali)
|
| 10 |
places = {
|
| 11 |
-
"Kigali": (-1.9441, 30.0619),
|
| 12 |
-
"Nyarugenge": (-1.9577, 30.0619),
|
| 13 |
-
"
|
| 14 |
-
"
|
| 15 |
-
"
|
| 16 |
-
"
|
| 17 |
-
"
|
| 18 |
-
"
|
| 19 |
-
"
|
| 20 |
-
"
|
| 21 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
}
|
| 23 |
|
| 24 |
-
# 2.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
def haversine(coord1, coord2):
|
| 26 |
R = 6371 # Earth radius in km
|
| 27 |
lat1, lon1 = coord1
|
|
@@ -32,7 +85,7 @@ def haversine(coord1, coord2):
|
|
| 32 |
c = 2 * atan2(sqrt(a), sqrt(1 - a))
|
| 33 |
return R * c
|
| 34 |
|
| 35 |
-
#
|
| 36 |
edges = [
|
| 37 |
("Nyarugenge", "Gasabo"), ("Gasabo", "Kicukiro"), ("Kicukiro", "Bugesera"), ("Bugesera", "Rwamagana"),
|
| 38 |
("Rwamagana", "Kayonza"), ("Kayonza", "Kirehe"), ("Kirehe", "Ngoma"), ("Ngoma", "Gatsibo"),
|
|
@@ -43,17 +96,16 @@ edges = [
|
|
| 43 |
("Ruhango", "Nyanza"), ("Nyanza", "Huye"), ("Huye", "Gisagara"), ("Gisagara", "Nyaruguru"),
|
| 44 |
("Nyaruguru", "Nyamagabe"), ("Nyamagabe", "Karongi"), ("Ngororero", "Ruhango"),
|
| 45 |
("Gicumbi", "Gasabo"), ("Bugesera", "Ngoma"),
|
| 46 |
-
|
| 47 |
# Kigali connections
|
| 48 |
("Kigali", "Nyarugenge"), ("Kigali", "Gasabo"), ("Kigali", "Kicukiro")
|
| 49 |
]
|
| 50 |
|
| 51 |
-
#
|
| 52 |
G = nx.Graph()
|
| 53 |
for u, v in edges:
|
| 54 |
G.add_edge(u, v, weight=haversine(places[u], places[v]))
|
| 55 |
|
| 56 |
-
#
|
| 57 |
class AnimateMarker(MacroElement):
|
| 58 |
_template = Template("""
|
| 59 |
{% macro script(this, kwargs) %}
|
|
@@ -76,13 +128,13 @@ class AnimateMarker(MacroElement):
|
|
| 76 |
self._name = "AnimateMarker"
|
| 77 |
self.locations = locations
|
| 78 |
|
| 79 |
-
#
|
| 80 |
def generate_map(start, end):
|
| 81 |
if start == end:
|
| 82 |
-
return "Hitamo aho utangiriye n’aho ugiye bitandukanye.", ""
|
| 83 |
|
| 84 |
if not nx.has_path(G, start, end):
|
| 85 |
-
return f"Nta nzira ibaho hagati ya {start} na {end}.", ""
|
| 86 |
|
| 87 |
try:
|
| 88 |
path = nx.astar_path(G, start, end, heuristic=lambda u, v: haversine(places[u], places[v]), weight='weight')
|
|
@@ -95,11 +147,29 @@ def generate_map(start, end):
|
|
| 95 |
PolyLine(coords, color="blue", weight=5).add_to(m)
|
| 96 |
m.add_child(AnimateMarker(coords))
|
| 97 |
|
| 98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
except Exception as e:
|
| 100 |
-
return f"Ntibishoboka kubona inzira: {str(e)}", ""
|
| 101 |
|
| 102 |
-
#
|
| 103 |
iface = gr.Interface(
|
| 104 |
fn=generate_map,
|
| 105 |
inputs=[
|
|
@@ -108,10 +178,13 @@ iface = gr.Interface(
|
|
| 108 |
],
|
| 109 |
outputs=[
|
| 110 |
gr.Textbox(label="Ubutumwa"),
|
| 111 |
-
gr.HTML(label="Ikarita")
|
|
|
|
| 112 |
],
|
| 113 |
title="🗺️ VIATEUR AI - Rwanda Smart Route Planner",
|
| 114 |
theme="default"
|
| 115 |
)
|
| 116 |
|
| 117 |
-
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
# 1. Districts and Coordinates (Harimo Kigali)
|
| 10 |
places = {
|
| 11 |
+
"Kigali": (-1.9441, 30.0619),
|
| 12 |
+
"Nyarugenge": (-1.9577, 30.0619),
|
| 13 |
+
"Gasabo": (-1.9400, 30.0861),
|
| 14 |
+
"Kicukiro": (-1.9781, 30.0597),
|
| 15 |
+
"Burera": (-1.4800, 29.7300),
|
| 16 |
+
"Gakenke": (-1.5700, 29.7561),
|
| 17 |
+
"Rulindo": (-1.8333, 30.0833),
|
| 18 |
+
"Musanze": (-1.5014, 29.6344),
|
| 19 |
+
"Gicumbi": (-1.5794, 30.0542),
|
| 20 |
+
"Nyagatare": (-1.3100, 30.3000),
|
| 21 |
+
"Gatsibo": (-1.6800, 30.3900),
|
| 22 |
+
"Kayonza": (-2.0000, 30.5667),
|
| 23 |
+
"Kirehe": (-2.3553, 30.7767),
|
| 24 |
+
"Ngoma": (-2.1600, 30.4700),
|
| 25 |
+
"Rwamagana": (-1.9491, 30.4349),
|
| 26 |
+
"Bugesera": (-2.2083, 30.2576),
|
| 27 |
+
"Kamonyi": (-2.0833, 29.9000),
|
| 28 |
+
"Muhanga": (-2.1200, 29.7561),
|
| 29 |
+
"Ruhango": (-2.2136, 29.7628),
|
| 30 |
+
"Nyamagabe": (-2.4978, 29.4897),
|
| 31 |
+
"Nyaruguru": (-2.5806, 29.4306),
|
| 32 |
+
"Huye": (-2.5921, 29.7408),
|
| 33 |
+
"Gisagara": (-2.6283, 29.6820),
|
| 34 |
+
"Nyanza": (-2.3566, 29.7507),
|
| 35 |
+
"Rutsiro": (-2.0986, 29.3269),
|
| 36 |
+
"Karongi": (-2.0667, 29.4677),
|
| 37 |
+
"Rubavu": (-1.7481, 29.2730),
|
| 38 |
+
"Rusizi": (-2.5406, 29.3737),
|
| 39 |
+
"Nyamasheke": (-2.4700, 29.3222),
|
| 40 |
+
"Ngororero": (-1.8733, 29.5811)
|
| 41 |
}
|
| 42 |
|
| 43 |
+
# 2. Place images URLs (free Wikimedia images or placeholders)
|
| 44 |
+
place_images = {
|
| 45 |
+
"Kigali": "https://upload.wikimedia.org/wikipedia/commons/8/89/Kigali_city_view.jpg",
|
| 46 |
+
"Nyarugenge": "https://upload.wikimedia.org/wikipedia/commons/f/f8/Nyarugenge_district.jpg",
|
| 47 |
+
"Gasabo": "https://upload.wikimedia.org/wikipedia/commons/a/a5/Gasabo_district.jpg",
|
| 48 |
+
"Kicukiro": "https://upload.wikimedia.org/wikipedia/commons/1/10/Kicukiro_District_-_Rwanda.jpg",
|
| 49 |
+
"Burera": "https://upload.wikimedia.org/wikipedia/commons/3/33/Burera_Lake_Muhazi.jpg",
|
| 50 |
+
"Gakenke": "https://upload.wikimedia.org/wikipedia/commons/c/c4/Gakenke_landscape.jpg",
|
| 51 |
+
"Rulindo": "https://upload.wikimedia.org/wikipedia/commons/0/01/Rulindo_landscape.jpg",
|
| 52 |
+
"Musanze": "https://upload.wikimedia.org/wikipedia/commons/6/6c/Musanze_scenery.jpg",
|
| 53 |
+
"Gicumbi": "https://upload.wikimedia.org/wikipedia/commons/7/7e/Gicumbi_landscape.jpg",
|
| 54 |
+
"Nyagatare": "https://upload.wikimedia.org/wikipedia/commons/9/98/Nyagatare_landscape.jpg",
|
| 55 |
+
"Gatsibo": "https://upload.wikimedia.org/wikipedia/commons/f/f0/Gatsibo_landscape.jpg",
|
| 56 |
+
"Kayonza": "https://upload.wikimedia.org/wikipedia/commons/b/b6/Kayonza_landscape.jpg",
|
| 57 |
+
"Kirehe": "https://upload.wikimedia.org/wikipedia/commons/3/3f/Kirehe_landscape.jpg",
|
| 58 |
+
"Ngoma": "https://upload.wikimedia.org/wikipedia/commons/4/49/Ngoma_landscape.jpg",
|
| 59 |
+
"Rwamagana": "https://upload.wikimedia.org/wikipedia/commons/0/00/Rwamagana_landscape.jpg",
|
| 60 |
+
"Bugesera": "https://upload.wikimedia.org/wikipedia/commons/1/12/Bugesera_landscape.jpg",
|
| 61 |
+
"Kamonyi": "https://upload.wikimedia.org/wikipedia/commons/d/d4/Kamonyi_landscape.jpg",
|
| 62 |
+
"Muhanga": "https://upload.wikimedia.org/wikipedia/commons/2/2a/Muhanga_landscape.jpg",
|
| 63 |
+
"Ruhango": "https://upload.wikimedia.org/wikipedia/commons/9/96/Ruhango_landscape.jpg",
|
| 64 |
+
"Nyamagabe": "https://upload.wikimedia.org/wikipedia/commons/8/80/Nyamagabe_landscape.jpg",
|
| 65 |
+
"Nyaruguru": "https://upload.wikimedia.org/wikipedia/commons/6/63/Nyaruguru_landscape.jpg",
|
| 66 |
+
"Huye": "https://upload.wikimedia.org/wikipedia/commons/7/7a/Huye_landscape.jpg",
|
| 67 |
+
"Gisagara": "https://upload.wikimedia.org/wikipedia/commons/8/8c/Gisagara_landscape.jpg",
|
| 68 |
+
"Nyanza": "https://upload.wikimedia.org/wikipedia/commons/3/3a/Nyanza_landscape.jpg",
|
| 69 |
+
"Rutsiro": "https://upload.wikimedia.org/wikipedia/commons/5/5f/Rutsiro_landscape.jpg",
|
| 70 |
+
"Karongi": "https://upload.wikimedia.org/wikipedia/commons/f/f5/Karongi_landscape.jpg",
|
| 71 |
+
"Rubavu": "https://upload.wikimedia.org/wikipedia/commons/6/68/Rubavu_landscape.jpg",
|
| 72 |
+
"Rusizi": "https://upload.wikimedia.org/wikipedia/commons/3/30/Rusizi_landscape.jpg",
|
| 73 |
+
"Nyamasheke": "https://upload.wikimedia.org/wikipedia/commons/1/17/Nyamasheke_landscape.jpg",
|
| 74 |
+
"Ngororero": "https://upload.wikimedia.org/wikipedia/commons/7/7d/Ngororero_landscape.jpg"
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
# 3. Distance calculator (Haversine Formula)
|
| 78 |
def haversine(coord1, coord2):
|
| 79 |
R = 6371 # Earth radius in km
|
| 80 |
lat1, lon1 = coord1
|
|
|
|
| 85 |
c = 2 * atan2(sqrt(a), sqrt(1 - a))
|
| 86 |
return R * c
|
| 87 |
|
| 88 |
+
# 4. Edges (connect Kigali and other districts)
|
| 89 |
edges = [
|
| 90 |
("Nyarugenge", "Gasabo"), ("Gasabo", "Kicukiro"), ("Kicukiro", "Bugesera"), ("Bugesera", "Rwamagana"),
|
| 91 |
("Rwamagana", "Kayonza"), ("Kayonza", "Kirehe"), ("Kirehe", "Ngoma"), ("Ngoma", "Gatsibo"),
|
|
|
|
| 96 |
("Ruhango", "Nyanza"), ("Nyanza", "Huye"), ("Huye", "Gisagara"), ("Gisagara", "Nyaruguru"),
|
| 97 |
("Nyaruguru", "Nyamagabe"), ("Nyamagabe", "Karongi"), ("Ngororero", "Ruhango"),
|
| 98 |
("Gicumbi", "Gasabo"), ("Bugesera", "Ngoma"),
|
|
|
|
| 99 |
# Kigali connections
|
| 100 |
("Kigali", "Nyarugenge"), ("Kigali", "Gasabo"), ("Kigali", "Kicukiro")
|
| 101 |
]
|
| 102 |
|
| 103 |
+
# 5. Create Graph
|
| 104 |
G = nx.Graph()
|
| 105 |
for u, v in edges:
|
| 106 |
G.add_edge(u, v, weight=haversine(places[u], places[v]))
|
| 107 |
|
| 108 |
+
# 6. Animation class for marker movement on folium map
|
| 109 |
class AnimateMarker(MacroElement):
|
| 110 |
_template = Template("""
|
| 111 |
{% macro script(this, kwargs) %}
|
|
|
|
| 128 |
self._name = "AnimateMarker"
|
| 129 |
self.locations = locations
|
| 130 |
|
| 131 |
+
# 7. Routing function with images output
|
| 132 |
def generate_map(start, end):
|
| 133 |
if start == end:
|
| 134 |
+
return "Hitamo aho utangiriye n’aho ugiye bitandukanye.", "", ""
|
| 135 |
|
| 136 |
if not nx.has_path(G, start, end):
|
| 137 |
+
return f"Nta nzira ibaho hagati ya {start} na {end}.", "", ""
|
| 138 |
|
| 139 |
try:
|
| 140 |
path = nx.astar_path(G, start, end, heuristic=lambda u, v: haversine(places[u], places[v]), weight='weight')
|
|
|
|
| 147 |
PolyLine(coords, color="blue", weight=5).add_to(m)
|
| 148 |
m.add_child(AnimateMarker(coords))
|
| 149 |
|
| 150 |
+
# Get images URLs for start and end locations
|
| 151 |
+
start_img = place_images.get(start, "https://via.placeholder.com/300?text=No+Image")
|
| 152 |
+
end_img = place_images.get(end, "https://via.placeholder.com/300?text=No+Image")
|
| 153 |
+
|
| 154 |
+
images_html = f"""
|
| 155 |
+
<div style='display:flex; justify-content:space-around; margin-top: 10px;'>
|
| 156 |
+
<div style='text-align:center;'>
|
| 157 |
+
<h4>{start}</h4>
|
| 158 |
+
<img src="{start_img}" alt="{start}" width="300" style="border-radius: 8px;"/>
|
| 159 |
+
</div>
|
| 160 |
+
<div style='text-align:center;'>
|
| 161 |
+
<h4>{end}</h4>
|
| 162 |
+
<img src="{end_img}" alt="{end}" width="300" style="border-radius: 8px;"/>
|
| 163 |
+
</div>
|
| 164 |
+
</div>
|
| 165 |
+
"""
|
| 166 |
+
|
| 167 |
+
return "Inzira ngufi ni: " + " ➔ ".join(path), m._repr_html_(), images_html
|
| 168 |
+
|
| 169 |
except Exception as e:
|
| 170 |
+
return f"Ntibishoboka kubona inzira: {str(e)}", "", ""
|
| 171 |
|
| 172 |
+
# 8. Gradio Interface
|
| 173 |
iface = gr.Interface(
|
| 174 |
fn=generate_map,
|
| 175 |
inputs=[
|
|
|
|
| 178 |
],
|
| 179 |
outputs=[
|
| 180 |
gr.Textbox(label="Ubutumwa"),
|
| 181 |
+
gr.HTML(label="Ikarita"),
|
| 182 |
+
gr.HTML(label="Amafoto y'aho hantu")
|
| 183 |
],
|
| 184 |
title="🗺️ VIATEUR AI - Rwanda Smart Route Planner",
|
| 185 |
theme="default"
|
| 186 |
)
|
| 187 |
|
| 188 |
+
if __name__ == "__main__":
|
| 189 |
+
iface.launch()
|
| 190 |
+
|