Spaces:
Runtime error
Runtime error
merge
Browse files- app.py +19 -11
- src/utils.py +39 -9
app.py
CHANGED
|
@@ -56,9 +56,9 @@ if auto_refresh:
|
|
| 56 |
|
| 57 |
|
| 58 |
# Streamlit functions
|
| 59 |
-
def display_interventions(interventions_df, selected_statuses):
|
| 60 |
"""Display NGO interventions on the map"""
|
| 61 |
-
|
| 62 |
for index, row in interventions_df.iterrows():
|
| 63 |
village_status = row[interventions_df.columns[7]]
|
| 64 |
is_future_intervention = (
|
|
@@ -81,7 +81,7 @@ def display_interventions(interventions_df, selected_statuses):
|
|
| 81 |
|
| 82 |
else:
|
| 83 |
color_mk = "darkgreen"
|
| 84 |
-
status = "Partial
|
| 85 |
|
| 86 |
intervention_type = row[interventions_df.columns[6]]
|
| 87 |
org = row[interventions_df.columns[1]]
|
|
@@ -107,6 +107,7 @@ def display_interventions(interventions_df, selected_statuses):
|
|
| 107 |
if row["latlng"] is None:
|
| 108 |
continue
|
| 109 |
|
|
|
|
| 110 |
fg.add_child(
|
| 111 |
folium.Marker(
|
| 112 |
location=row["latlng"],
|
|
@@ -210,14 +211,16 @@ def show_requests(filtered_df):
|
|
| 210 |
)
|
| 211 |
|
| 212 |
|
| 213 |
-
def show_verified_requests(filtered_verified_df):
|
| 214 |
"""Display verified victim requests on the map"""
|
| 215 |
global fg
|
|
|
|
| 216 |
verified_color_mapping = {
|
| 217 |
"Low": "beige",
|
| 218 |
"Medium": "orange",
|
| 219 |
"High": "red",
|
| 220 |
}
|
|
|
|
| 221 |
for index, row in filtered_verified_df.iterrows():
|
| 222 |
long_lat = row["latlng"]
|
| 223 |
# we display all requests in popup text and use the first one for the icon/color
|
|
@@ -250,7 +253,11 @@ def show_verified_requests(filtered_verified_df):
|
|
| 250 |
if long_lat is None:
|
| 251 |
continue
|
| 252 |
location = row["Location Details"]
|
| 253 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 254 |
folium.Marker(
|
| 255 |
location=long_lat,
|
| 256 |
tooltip=location if not pd.isna(location) else None,
|
|
@@ -328,7 +335,7 @@ def display_dataframe(df, drop_cols, data_url, search_id=True, status=False, for
|
|
| 328 |
st.markdown(
|
| 329 |
"""
|
| 330 |
<div style="text-align: left;">
|
| 331 |
-
<a href="mailto:nt3awnoumorocco@gmail.com">nt3awnoumorocco@gmail.com</a> نحن نخفي معلومات الاتصال لحماية خصوصية الضحايا. إذا كنت جمعية وتريد الاتصال بالضحايا، يرجى الاتصال بنا على
|
| 332 |
</div>
|
| 333 |
""",
|
| 334 |
unsafe_allow_html=True,
|
|
@@ -364,7 +371,7 @@ st.markdown(LOGO, unsafe_allow_html=True)
|
|
| 364 |
# st.title("Nt3awnou نتعاونو")
|
| 365 |
st.markdown(SLOGAN, unsafe_allow_html=True)
|
| 366 |
|
| 367 |
-
m = init_map()
|
| 368 |
fg = folium.FeatureGroup(name="Markers")
|
| 369 |
|
| 370 |
# Selection of requests
|
|
@@ -465,15 +472,16 @@ status_mapping = {
|
|
| 465 |
selected_statuses = [status_mapping[status] for status in selected_village_types]
|
| 466 |
|
| 467 |
if show_interventions:
|
| 468 |
-
display_interventions(interventions_df, selected_statuses)
|
| 469 |
display_solved(solved_verified_requests, selected_statuses)
|
|
|
|
|
|
|
| 470 |
|
| 471 |
# Show requests
|
| 472 |
if show_unverified:
|
| 473 |
show_requests(filtered_df)
|
| 474 |
|
| 475 |
# Show verified requests
|
| 476 |
-
show_verified_requests(verified_df)
|
| 477 |
|
| 478 |
# Add legend
|
| 479 |
legend_macro = get_legend_macro(show_unverified)
|
|
@@ -491,7 +499,7 @@ with st.expander("💻 For Developers only, embed code for the map | للمطو
|
|
| 491 |
st.code(
|
| 492 |
"""
|
| 493 |
<iframe id="nt3awnou-map"
|
| 494 |
-
src="https://nt3awnou-embed-rescue-map.hf.space/?embed=true" width="1200" height="720"
|
| 495 |
frameborder="0"
|
| 496 |
width="850"
|
| 497 |
height="450"
|
|
@@ -563,7 +571,7 @@ with tab_fr:
|
|
| 563 |
"# Nombre de demandes résolues",
|
| 564 |
len_solved_verified_requests,
|
| 565 |
)
|
| 566 |
-
|
| 567 |
|
| 568 |
# Verified Requests table
|
| 569 |
st.divider()
|
|
|
|
| 56 |
|
| 57 |
|
| 58 |
# Streamlit functions
|
| 59 |
+
def display_interventions(interventions_df, selected_statuses, map_obj, intervention_fgs):
|
| 60 |
"""Display NGO interventions on the map"""
|
| 61 |
+
|
| 62 |
for index, row in interventions_df.iterrows():
|
| 63 |
village_status = row[interventions_df.columns[7]]
|
| 64 |
is_future_intervention = (
|
|
|
|
| 81 |
|
| 82 |
else:
|
| 83 |
color_mk = "darkgreen"
|
| 84 |
+
status = "Partial 📝"
|
| 85 |
|
| 86 |
intervention_type = row[interventions_df.columns[6]]
|
| 87 |
org = row[interventions_df.columns[1]]
|
|
|
|
| 107 |
if row["latlng"] is None:
|
| 108 |
continue
|
| 109 |
|
| 110 |
+
fg = intervention_fgs[status]
|
| 111 |
fg.add_child(
|
| 112 |
folium.Marker(
|
| 113 |
location=row["latlng"],
|
|
|
|
| 211 |
)
|
| 212 |
|
| 213 |
|
| 214 |
+
def show_verified_requests(filtered_verified_df, emergency_fgs):
|
| 215 |
"""Display verified victim requests on the map"""
|
| 216 |
global fg
|
| 217 |
+
|
| 218 |
verified_color_mapping = {
|
| 219 |
"Low": "beige",
|
| 220 |
"Medium": "orange",
|
| 221 |
"High": "red",
|
| 222 |
}
|
| 223 |
+
|
| 224 |
for index, row in filtered_verified_df.iterrows():
|
| 225 |
long_lat = row["latlng"]
|
| 226 |
# we display all requests in popup text and use the first one for the icon/color
|
|
|
|
| 253 |
if long_lat is None:
|
| 254 |
continue
|
| 255 |
location = row["Location Details"]
|
| 256 |
+
|
| 257 |
+
# Select the correct feature group
|
| 258 |
+
fg_emergency_group = emergency_fgs[emergency]
|
| 259 |
+
|
| 260 |
+
fg_emergency_group.add_child(
|
| 261 |
folium.Marker(
|
| 262 |
location=long_lat,
|
| 263 |
tooltip=location if not pd.isna(location) else None,
|
|
|
|
| 335 |
st.markdown(
|
| 336 |
"""
|
| 337 |
<div style="text-align: left;">
|
| 338 |
+
<a href="mailto:nt3awnoumorocco@gmail.com">nt3awnoumorocco@gmail.com</a> نحن نخفي معلومات الاتصال لحماية خصوصية الضحايا. إذا كنت جمعية وتريد الاتصال بالضحايا، يرجى الاتصال بنا على
|
| 339 |
</div>
|
| 340 |
""",
|
| 341 |
unsafe_allow_html=True,
|
|
|
|
| 371 |
# st.title("Nt3awnou نتعاونو")
|
| 372 |
st.markdown(SLOGAN, unsafe_allow_html=True)
|
| 373 |
|
| 374 |
+
m, emergency_fgs, intervention_fgs = init_map()
|
| 375 |
fg = folium.FeatureGroup(name="Markers")
|
| 376 |
|
| 377 |
# Selection of requests
|
|
|
|
| 472 |
selected_statuses = [status_mapping[status] for status in selected_village_types]
|
| 473 |
|
| 474 |
if show_interventions:
|
|
|
|
| 475 |
display_solved(solved_verified_requests, selected_statuses)
|
| 476 |
+
display_interventions(interventions_df, selected_statuses, m, intervention_fgs)
|
| 477 |
+
|
| 478 |
|
| 479 |
# Show requests
|
| 480 |
if show_unverified:
|
| 481 |
show_requests(filtered_df)
|
| 482 |
|
| 483 |
# Show verified requests
|
| 484 |
+
show_verified_requests(verified_df, emergency_fgs)
|
| 485 |
|
| 486 |
# Add legend
|
| 487 |
legend_macro = get_legend_macro(show_unverified)
|
|
|
|
| 499 |
st.code(
|
| 500 |
"""
|
| 501 |
<iframe id="nt3awnou-map"
|
| 502 |
+
src="https://nt3awnou-embed-rescue-map.hf.space/?embed=true" width="1200" height="720"
|
| 503 |
frameborder="0"
|
| 504 |
width="850"
|
| 505 |
height="450"
|
|
|
|
| 571 |
"# Nombre de demandes résolues",
|
| 572 |
len_solved_verified_requests,
|
| 573 |
)
|
| 574 |
+
|
| 575 |
|
| 576 |
# Verified Requests table
|
| 577 |
st.divider()
|
src/utils.py
CHANGED
|
@@ -67,7 +67,7 @@ def parse_latlng(latlng):
|
|
| 67 |
if latlng.count(',') > 2:
|
| 68 |
d1, d2, d3, d4 = latlng.split(",")[:4]
|
| 69 |
return [float(".".join([d1, d2])), float(".".join([d3, d4]))]
|
| 70 |
-
|
| 71 |
# case of more than one dot 30.98. -7.10
|
| 72 |
if latlng.count('.') > 2:
|
| 73 |
d1, d2, d3, d4 = latlng.split(".")[:4]
|
|
@@ -79,7 +79,7 @@ def parse_latlng(latlng):
|
|
| 79 |
lat = re.sub(r"[^\d\.\-]", "", lat)
|
| 80 |
lng = re.sub(r"[^\d\.\-]", "", lng)
|
| 81 |
return [float(lat), float(lng)]
|
| 82 |
-
|
| 83 |
except Exception as e:
|
| 84 |
print(f"Error parsing latlng: {latlng} Reason: {e}")
|
| 85 |
return None
|
|
@@ -93,16 +93,16 @@ def add_epicentre_to_map(fg):
|
|
| 93 |
text_color='white'
|
| 94 |
)
|
| 95 |
|
| 96 |
-
fg.add_child(folium.Marker(location=EPICENTER_LOCATION,
|
| 97 |
-
# popup="Epicenter مركز الزلزال",
|
| 98 |
tooltip="Epicenter مركز الزلزال",
|
| 99 |
icon=icon_epicentre))
|
| 100 |
-
|
| 101 |
|
| 102 |
|
| 103 |
def add_danger_distances_to_map(map_obj):
|
| 104 |
Danger_Distances_group = folium.FeatureGroup(name='Danger distances - earthquake magnitude 7 | مسافات الخطر - قوة الزلازل 7').add_to(map_obj)
|
| 105 |
-
|
| 106 |
zones = [
|
| 107 |
{"radius": 100000, "fill_opacity": 0.1, "weight": 1, "fill_color": "yellow", "tooltip": "50 to 100 km - Moderate risk area | منطقة خطر معتدلة"},
|
| 108 |
{"radius": 50000, "fill_opacity": 0.1, "weight": 1, "fill_color": "orange", "tooltip": "30 to 50 km - High risk zone | منطقة عالية المخاطر"},
|
|
@@ -123,7 +123,7 @@ def add_danger_distances_to_map(map_obj):
|
|
| 123 |
).add_to(Danger_Distances_group)
|
| 124 |
|
| 125 |
|
| 126 |
-
def add_village_names(douar_df, map_obj):
|
| 127 |
village_fgroup = folium.FeatureGroup(name='🔵 All the Villages / Tous les villages / جميع القرى', show=False).add_to(map_obj)
|
| 128 |
|
| 129 |
for _, row in douar_df.iterrows():
|
|
@@ -137,13 +137,41 @@ def add_village_names(douar_df, map_obj):
|
|
| 137 |
folium.CircleMarker(
|
| 138 |
location=[lat, lng],
|
| 139 |
radius=0.1,
|
| 140 |
-
tooltip = dour_name, # we might remove the tooltip to avoid crowding the map
|
| 141 |
popup=folium.Popup(display_text, max_width=200),
|
| 142 |
color= "#0046C8",
|
| 143 |
opacity = 0.7
|
| 144 |
).add_to(village_fgroup)
|
| 145 |
|
| 146 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 147 |
def init_map():
|
| 148 |
m = folium.Map(
|
| 149 |
location=[31.228674, -7.992047],
|
|
@@ -185,6 +213,8 @@ def init_map():
|
|
| 185 |
# Add danger zones
|
| 186 |
add_epicentre_to_map(m)
|
| 187 |
add_danger_distances_to_map(m)
|
|
|
|
|
|
|
| 188 |
|
| 189 |
# Add a LayerControl to the map to toggle between layers (Satellite View and Default One)
|
| 190 |
folium.LayerControl().add_to(m)
|
|
@@ -197,4 +227,4 @@ def init_map():
|
|
| 197 |
strings={"title": "My location | موقعي", "popup": "My location | موقعي"},
|
| 198 |
).add_to(m)
|
| 199 |
|
| 200 |
-
return m
|
|
|
|
| 67 |
if latlng.count(',') > 2:
|
| 68 |
d1, d2, d3, d4 = latlng.split(",")[:4]
|
| 69 |
return [float(".".join([d1, d2])), float(".".join([d3, d4]))]
|
| 70 |
+
|
| 71 |
# case of more than one dot 30.98. -7.10
|
| 72 |
if latlng.count('.') > 2:
|
| 73 |
d1, d2, d3, d4 = latlng.split(".")[:4]
|
|
|
|
| 79 |
lat = re.sub(r"[^\d\.\-]", "", lat)
|
| 80 |
lng = re.sub(r"[^\d\.\-]", "", lng)
|
| 81 |
return [float(lat), float(lng)]
|
| 82 |
+
|
| 83 |
except Exception as e:
|
| 84 |
print(f"Error parsing latlng: {latlng} Reason: {e}")
|
| 85 |
return None
|
|
|
|
| 93 |
text_color='white'
|
| 94 |
)
|
| 95 |
|
| 96 |
+
fg.add_child(folium.Marker(location=EPICENTER_LOCATION,
|
| 97 |
+
# popup="Epicenter مركز الزلزال",
|
| 98 |
tooltip="Epicenter مركز الزلزال",
|
| 99 |
icon=icon_epicentre))
|
| 100 |
+
|
| 101 |
|
| 102 |
|
| 103 |
def add_danger_distances_to_map(map_obj):
|
| 104 |
Danger_Distances_group = folium.FeatureGroup(name='Danger distances - earthquake magnitude 7 | مسافات الخطر - قوة الزلازل 7').add_to(map_obj)
|
| 105 |
+
|
| 106 |
zones = [
|
| 107 |
{"radius": 100000, "fill_opacity": 0.1, "weight": 1, "fill_color": "yellow", "tooltip": "50 to 100 km - Moderate risk area | منطقة خطر معتدلة"},
|
| 108 |
{"radius": 50000, "fill_opacity": 0.1, "weight": 1, "fill_color": "orange", "tooltip": "30 to 50 km - High risk zone | منطقة عالية المخاطر"},
|
|
|
|
| 123 |
).add_to(Danger_Distances_group)
|
| 124 |
|
| 125 |
|
| 126 |
+
def add_village_names(douar_df, map_obj):
|
| 127 |
village_fgroup = folium.FeatureGroup(name='🔵 All the Villages / Tous les villages / جميع القرى', show=False).add_to(map_obj)
|
| 128 |
|
| 129 |
for _, row in douar_df.iterrows():
|
|
|
|
| 137 |
folium.CircleMarker(
|
| 138 |
location=[lat, lng],
|
| 139 |
radius=0.1,
|
| 140 |
+
tooltip = dour_name, # we might remove the tooltip to avoid crowding the map
|
| 141 |
popup=folium.Popup(display_text, max_width=200),
|
| 142 |
color= "#0046C8",
|
| 143 |
opacity = 0.7
|
| 144 |
).add_to(village_fgroup)
|
| 145 |
|
| 146 |
|
| 147 |
+
def init_intervention_fgs(m):
|
| 148 |
+
intervention_fgs = {}
|
| 149 |
+
|
| 150 |
+
fg_done = folium.FeatureGroup(name="Done ✅", show=True).add_to(m)
|
| 151 |
+
fg_planned = folium.FeatureGroup(name="Planned ⏳", show=True).add_to(m)
|
| 152 |
+
fg_partial = folium.FeatureGroup(name="Partial 📝", show=True).add_to(m)
|
| 153 |
+
|
| 154 |
+
intervention_fgs["Done ✅"] = fg_done
|
| 155 |
+
intervention_fgs["Planned ⌛"] = fg_planned
|
| 156 |
+
intervention_fgs["Partial 📝"] = fg_partial
|
| 157 |
+
|
| 158 |
+
return intervention_fgs
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
def init_emergency_fgs(m):
|
| 162 |
+
emergency_fgs = {}
|
| 163 |
+
|
| 164 |
+
fg_high = folium.FeatureGroup(name="High 🔴", show=True).add_to(m)
|
| 165 |
+
fg_medium = folium.FeatureGroup(name="Medium 🟠", show=True).add_to(m)
|
| 166 |
+
fg_low = folium.FeatureGroup(name="Low 🟡", show=True).add_to(m)
|
| 167 |
+
|
| 168 |
+
emergency_fgs["High"] = fg_high
|
| 169 |
+
emergency_fgs["Medium"] = fg_medium
|
| 170 |
+
emergency_fgs["Low"] = fg_low
|
| 171 |
+
|
| 172 |
+
return emergency_fgs
|
| 173 |
+
|
| 174 |
+
|
| 175 |
def init_map():
|
| 176 |
m = folium.Map(
|
| 177 |
location=[31.228674, -7.992047],
|
|
|
|
| 213 |
# Add danger zones
|
| 214 |
add_epicentre_to_map(m)
|
| 215 |
add_danger_distances_to_map(m)
|
| 216 |
+
emergency_fgs = init_emergency_fgs(m)
|
| 217 |
+
intervention_fgs = init_intervention_fgs(m)
|
| 218 |
|
| 219 |
# Add a LayerControl to the map to toggle between layers (Satellite View and Default One)
|
| 220 |
folium.LayerControl().add_to(m)
|
|
|
|
| 227 |
strings={"title": "My location | موقعي", "popup": "My location | موقعي"},
|
| 228 |
).add_to(m)
|
| 229 |
|
| 230 |
+
return m, emergency_fgs, intervention_fgs
|