Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
File size: 19,216 Bytes
549a2cc b10dbaa 549a2cc b10dbaa ebc2ece 549a2cc a04f639 b10dbaa 549a2cc a8969c3 b10dbaa 01defef b10dbaa 01defef 1df563c b10dbaa 01defef b10dbaa 01defef b10dbaa 49d14ca e2c81e5 49d14ca edb7355 01defef 4618b5e d72c3e5 5f1dd3f e28246a 5f1dd3f bdfe087 d72c3e5 5f1dd3f a472331 01defef ebc2ece 6d4d03f 86f908d 6d4d03f b10dbaa 01defef 86f908d 01defef b10dbaa bbbf293 01defef b10dbaa 86f908d 01defef 6d4d03f 86f908d 6d4d03f b10dbaa 6d4d03f 5f1dd3f caddedc a49ed6f caddedc a49ed6f caddedc 6d4d03f 8a8cff3 5f1dd3f a472331 8a8cff3 96da45a 8a8cff3 5f1dd3f 8a8cff3 caddedc 5f1dd3f 6d4d03f 5f1dd3f 8a8cff3 1df563c 15d58ea 1df563c b10dbaa 68160ae 886bf76 391cfe9 886bf76 6d4d03f a49ed6f 6d4d03f 34dfd2a 6d4d03f caddedc 8a8cff3 1fb0b3b c072865 6d4d03f 01defef b10dbaa 4482a4e b10dbaa 01defef 0db7492 4482a4e 6d4d03f b10dbaa ebc2ece b10dbaa 1e7a1cd bd8b954 01defef 5f1dd3f 01defef bbbf293 5f1dd3f bbbf293 15d58ea 5f1dd3f bbbf293 bdfe087 bbbf293 549a2cc 8d5e1fd ea7434c 549a2cc 01defef 49d14ca d8404d9 49d14ca d8404d9 bfad8fc 15d58ea 49d14ca b10dbaa 4482a4e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 |
import os
import time
import requests
import folium
import pandas as pd
from datetime import datetime
import streamlit as st
from streamlit_folium import st_folium
from utils import legend_macro
from huggingface_hub import HfApi
from folium import plugins
TOKEN = os.environ.get("HF_TOKEN", None)
api = HfApi(token=TOKEN)
st.set_page_config(layout="wide", initial_sidebar_state="collapsed")
if "sleep_time" not in st.session_state:
st.session_state.sleep_time = 2
if "auto_refresh" not in st.session_state:
st.session_state.auto_refresh = False
auto_refresh = st.sidebar.checkbox("Auto Refresh?", st.session_state.auto_refresh)
if auto_refresh:
number = st.sidebar.number_input("Refresh rate in seconds", value=st.session_state.sleep_time)
st.session_state.sleep_time = number
#Logo
st.markdown(
"""
<div style="text-align: center;">
<img src="https://storage.googleapis.com/storage-annarabic/Nt3awnou(1).png" width="200" height="200">
</div>
""",
unsafe_allow_html=True,
)
st.title("Nt3awnou نتعاونو ")
# middle slogan
st.markdown(
"""
<div style="text-align: center;">
<h4>وَمَنْ أَحْيَاهَا فَكَأَنَّمَا أَحْيَا النَّاسَ جَمِيعاً</h4>
</div>
""",
unsafe_allow_html=True,
)
# Have different streamlit tabs for each language
st.sidebar.title("Language / اللغة")
tab_ar, tab_en, tab_fr = st.tabs(["العربية", "English", "Français"])
with tab_en:
st.markdown("""
<div style="text-align: left;">
Nt3awnou نتعاونو is a collaborative platform dedicated to aiding individuals impacted by the recent earthquake in Morocco. Our core mission is to streamline and coordinate timely assistance for everyone affected. How do we achieve this? We assist those in need by allowing them to communicate their location and the specific aid they require, either by completing a form or sending a voice message via WhatsApp to a designated number. Once we receive and process this information, it can be viewed in our dashboard, which allows NGOs to organize and precisely target their interventions, ensuring swift assistance reaches those in need. Any organization that has taken initiative in a particular area can notify us by completing a dedicated form. This data is also incorporated into the dashboard so that other NGOs can help affected areas that still haven't received help.
Warning : There are still rocks falling down the mountains, making the roads to the affected areas very dangerous. We advise volunteers to donate directly to specialized NGOs.
✉️ You can contact us via email at nt3awnou@annarabic.com <br>
📝 Help us report more people in need by filling this form: https://forms.gle/nZNCUVog9ka2Vdqu6 <br>
📝 NGOs can report their interventions by filling this form: https://forms.gle/PsNSuHHjTTgwQMmVA
</div>
""",
unsafe_allow_html=True,
)
with tab_ar:
st.markdown(
"""
<div style="text-align: right;">
نتعاونو هي منصة تعاونية لمساعدة الأفراد المتضررين من الزلزال الأخير في المغرب. مهمتنا هي تسهيل تقديم المساعدة في الوقت المناسب و بفاعلية و تنظيم لجميع المتضررين. كيفاش؟ كنعاونو الناس لي محتاجين للمساعدة إعلمونا بمكانهم و نوع المساعدة لي محتاجين ليها سواء عن طريق ملأ الاستمارة أو عن طريق إرسال تسجيل صوتي عبر واتساب إلى رقم مخصص. بعد معالجة هاد المعلومات، كنجمعوهم فخريطة كتمكن الجمعيات من تنظيم و استهداف تدخلاتهم بدقة باش توصل المساعدة للناس لي محتاجين في وقت أسرع. و كل جمعية قامت باللازم في منطقة معينة تقدر تعلمنا عن طريق ملأ استمارة مخصصة لهاد الأمر. هاد المعلومات كذلك كتضاف للخريطة باش باقي الجمعيات يتاجهو لمناطق أخرى مازال ماوصلاتهم مساعدة.
تحذير : نظرا لخطورة الطرقان بسبب الحجر اللي كيطيح من الجبال، ننصح المتطوعين اللي بغاو يساعدو المناطق المتضررة يتبرعو عن طريق الجمعيات المختصة.
nt3awnou@annarabic.com المتطوعين ليبغاو يعاونوا يقدرو يتصلوا معنا عبر البريد ✉️
https://forms.gle/nZNCUVog9ka2Vdqu6 : ساعدونا نبلغو الناس ليمحتاجين فهاد الاستمارة 📝<br>
https://forms.gle/PsNSuHHjTTgwQMmVA : الجمعيات لي عندهم تدخلات يقدرو يبلغونا عبر هاد الاستمار ة📝
</div>
""",
unsafe_allow_html=True,
)
with tab_fr:
st.markdown("""
<div style="text-align: left;">
Nt3awnou نتعاونو est une plateforme collaborative dédiée à l'aide aux personnes touchées par le récent tremblement de terre au Maroc. Notre mission principale est de rationaliser et de coordonner une assistance rapide pour toutes les personnes touchées. Comment y parvenons-nous ? Nous aidons les personnes dans le besoin en leur permettant de communiquer leur localisation et l'aide spécifique dont elles ont besoin, soit en remplissant un formulaire, soit en envoyant un message vocal via WhatsApp à un numéro désigné. Une fois reçues et traitées, ces informations peuvent être consultées dans notre tableau de bord, qui permet aux associations d'organiser et de cibler précisément leurs interventions, afin que l'aide parvienne rapidement à ceux qui en ont besoin. Toute organisation ayant pris une initiative dans une zone particulière peut nous en informer en remplissant un formulaire prévu à cet effet. Ces données sont également intégrées au tableau de bord afin que d'autres associations puissent aider les zones touchées qui n'ont pas encore reçu d'aide.
Avertissement : Il y a encore des chutes de pierres dans les montagnes, ce qui rend les routes vers les zones touchées très dangereuses. Nous conseillons aux volontaires de faire des dons directement aux associations spécialisées.
✉️ Vous pouvez nous contacter par courrier électronique à l'adresse suivante : nt3awnou@annarabic.com <br>
📝 Aidez-nous à signaler plus de personnes dans le besoin en remplissant ce formulaire : https://forms.gle/nZNCUVog9ka2Vdqu6 <br>
📝 Les associations peuvent signaler leurs interventions en remplissant ce formulaire : https://forms.gle/PsNSuHHjTTgwQMmVA
</div>
"""
, unsafe_allow_html=True)
session = requests.Session()
@st.cache_data(persist=True)
def parse_latlng_from_link(url):
try:
# extract latitude and longitude from gmaps link
if "@" not in url:
# We first need to get the redirect URL
resp = session.head(url, allow_redirects=True)
url = resp.url
latlng = url.split('@')[1].split(',')[0:2]
return [float(latlng[0]), float(latlng[1])]
except Exception as e:
print(f"Error parsing latlng from link: {e}")
return None
def parse_gg_sheet_interventions(url):
url = url.replace("edit#gid=", "export?format=csv&gid=")
print(url)
df = pd.read_csv(url, on_bad_lines='skip')
return df.assign(latlng=df.iloc[:, 3].apply(parse_latlng_from_link))
def parse_gg_sheet(url):
url = url.replace("edit#gid=", "export?format=csv&gid=")
print(url)
df = pd.read_csv(url, on_bad_lines='warn')
# parse latlng (column 4) to [lat, lng]
def parse_latlng(latlng):
try:
lat, lng = latlng.split(",")
return [float(lat), float(lng)]
except Exception as e:
print(f"Error parsing latlng: {e}")
return None
if df.shape[1] > 4:
df = df.assign(latlng=df.iloc[:, 4].apply(parse_latlng))
return df
df = parse_gg_sheet(
"https://docs.google.com/spreadsheets/d/1gYoBBiBo1L18IVakHkf3t1fOGvHWb23loadyFZUeHJs/edit#gid=966953708"
)
interventions_df = parse_gg_sheet_interventions(
"https://docs.google.com/spreadsheets/d/1eXOTqunOWWP8FRdENPs4cU9ulISm4XZWYJJNR1-SrwY/edit#gid=2089222765"
)
# select requests
with tab_ar:
headers_mapping = {
"إغاثة": "Rescue/إغاثة",
"مساعدة طبية": "Medical Assistance/مساعدة طبية",
"مأوى": "Shelter/مأوى",
"طعام وماء": "Food & Water/طعام وماء",
"مخاطر (تسرب الغاز، تلف في الخدمات العامة...)": "Danger/مخاطر (تسرب الغاز، تلف في الخدمات العامة...)",
}
with tab_en:
headers_mapping = {
"إغاثة" : "Rescue | إغاثة | Secours",
"مساعدة طبية": "Medical Assistance | مساعدة طبية | Assistance médicale",
"مأوى": "Shelter | مأوى | Abri",
"طعام وماء": "Food & Water | طعام وماء | Nourriture et eau",
"مخاطر (تسرب الغاز، تلف في الخدمات العامة...)": "Danger | مخاطر (تسرب الغاز، تلف في الخدمات العامة...) | Danger",
}
colors_mapping = {
"إغاثة": "red",
"مساعدة طبية": "orange",
"مأوى": "beige",
"طعام وماء": "blue",
"مخاطر (تسرب الغاز، تلف في الخدمات العامة...)": "gray",
}
icon_mapping = {
"إغاثة": "bell", # life ring icon for rescue
"مساعدة طبية": "heart", # medical kit for medical assistance
"مأوى": "home", # home icon for shelter
"طعام وماء": "cutlery", # cutlery (fork and knife) for food & water
"مخاطر (تسرب الغاز، تلف في الخدمات العامة...)": "Warning" # warning triangle for dangers
}
options = ["إغاثة", "مساعدة طبية", "مأوى", "طعام وماء", "مخاطر (تسرب الغاز، تلف في الخدمات العامة...)"]
selected_options = []
with tab_en:
st.markdown("👉 **Choose request type**")
with tab_ar:
st.markdown("👉 **اختر نوع الطلب**")
with tab_fr:
st.markdown("👉 **Choisissez le type de demande**")
col1, col2, col3, col4, col5 = st.columns([2, 3, 2, 3, 4])
cols = [col1, col2, col3, col4, col5]
for i, option in enumerate(options):
checked = cols[i].checkbox(headers_mapping[option], value=True)
if checked:
selected_options.append(option)
df['id'] = df.index
filtered_df = df[df['ما هي احتياجاتك؟ (أضفها إذا لم يتم ذكرها)'].isin(selected_options)]
selected_headers = [headers_mapping[request] for request in selected_options]
# select interventions
show_interventions = st.checkbox("Display Interventions | عرض عمليات المساعدة | Afficher les interventions", value=True)
m = folium.Map(
location=[31.228674, -7.992047],
zoom_start=8.5,
min_zoom=8.5,
max_lat=35.628674,
min_lat=29.628674,
max_lon=-4.992047,
min_lon=-10.992047,
max_bounds=True,
)
# Add a search bar to the map
plugins.Geocoder(
collapsed=False,
position="topright",
placeholder="Search | البحث",
).add_to(m)
# Add Fullscreen button to the map
plugins.Fullscreen(
position='topright',
title='Expand me | تكبير الخريطة',
title_cancel='Exit me | تصغير الخريطة',
force_separate_button=True
).add_to(m)
#Satellite View from Mapbox
tileurl = 'https://api.mapbox.com/styles/v1/phd2020/clmer2mra01d001pbgjkictpt/tiles/256/{z}/{x}/{y}@2x?access_token=pk.eyJ1IjoicGhkMjAyMCIsImEiOiJja29lZzFwZmUwNHkzMm5wMjZnYjVvcGltIn0.tE0ritrelQOyLdKUH6hgOw'
folium.TileLayer(
tiles = tileurl,
attr = 'Satellite View',
name = 'Satellite View | عرض القمر الصناعي',
overlay = False,
control = True
).add_to(m)
# Marker for the epicentre
icon_epicentre = folium.plugins.BeautifyIcon(
icon='spinner',
spin='true',
border_color='#b3334f',
background_color = '#b3334f',
text_color = 'white'
)
folium.Marker(location=[31.12210171476489, -8.42945837915193], popup="Epicenter زلزال المغرب 2023 (مركز الزلزال)", icon=icon_epicentre).add_to(m)
# Danger Distances Feature
Danger_Distances_group = folium.FeatureGroup(name='Danger distances - earthquake magnitude 7 | مسافات الخطر - قوة الزلازل 7').add_to(m)
radius = 100000 # in meters
folium.Circle(
location=[31.12210171476489, -8.42945837915193],
radius=radius,
color="black",
weight=1,
fill_opacity=0.1,
opacity=0.1,
fill_color="yellow",
tooltip="50 to 100 km -Moderate risk area | منطقة خطر معتدلة",
).add_to(Danger_Distances_group)
radius = 50000 # in meters
folium.Circle(
location=[31.12210171476489, -8.42945837915193],
radius=radius,
color="black",
weight=1,
fill_opacity=0.1,
opacity=0.1,
fill_color="orange",
tooltip="30 to 50 km - High risk zone | منطقة عالية المخاطر",
).add_to(Danger_Distances_group)
radius = 30000 # in meters
folium.Circle(
location=[31.12210171476489, -8.42945837915193],
radius=radius,
color="black",
weight=1,
fill_opacity=0.2,
opacity=0.2,
fill_color="#FF0000",
tooltip="10 to 30 km - Very high risk zone | منطقة شديدة الخطورة ",
).add_to(Danger_Distances_group)
radius = 10000 # in meters
folium.Circle(
location=[31.12210171476489, -8.42945837915193],
radius=radius,
color="black",
weight=0.2,
fill_opacity=0.2,
opacity=0.2,
fill_color="#8B0000",
tooltip="0 to 10km - direct impact zone | منطقة التأثير المباشر",
).add_to(Danger_Distances_group)
# Add a LayerControl to the map to toggle between layers (Satellite View and Default One)
folium.LayerControl().add_to(m)
if show_interventions:
for index, row in interventions_df.iterrows():
status = "Done ✅" if row[interventions_df.columns[5]]!="Intervention prévue dans le futur / Planned future intervention" else "Planned ⌛"
color_mk = "green" if row[interventions_df.columns[5]]!="Intervention prévue dans le futur / Planned future intervention" else "pink"
intervention_type = row[interventions_df.columns[6]].split("/")[0].strip()
org = row[interventions_df.columns[1]]
city = row[interventions_df.columns[9]]
date = row[interventions_df.columns[4]]
intervention_info = f"<b>Status:</b> {status}<br><b>Org:</b> {org}<br><b>Intervention:</b> {intervention_type}<br><b>📅 Date:</b> {date}"
if row["latlng"] is None:
continue
folium.Marker(
location=row["latlng"],
tooltip=city,
popup=folium.Popup(intervention_info, max_width=300),
icon=folium.Icon(color=color_mk)
).add_to(m)
for index, row in filtered_df.iterrows():
request_type = row['ما هي احتياجاتك؟ (أضفها إذا لم يتم ذكرها)']
long_lat = row["هل يمكنك تقديم الإحداثيات الدقيقة للموقع؟ (ادا كنت لا توجد بعين المكان) متلاً \n31.01837503440344, -6.781405948842175"]
maps_url = f"https://maps.google.com/?q={long_lat}"
display_text = f'<b>Request Type:</b> {request_type}<br><b>Id:</b> {row["id"]}<br><a href="{maps_url}" target="_blank" rel="noopener noreferrer"><b>Google Maps</b></a>'
icon_name = icon_mapping.get(request_type, 'info-sign')
if row["latlng"] is None:
continue
folium.Marker(
location=row["latlng"],
tooltip=row[' لأي جماعة / قيادة / دوار تنتمون ؟'] if not pd.isna(row[' لأي جماعة / قيادة / دوار تنتمون ؟']) else None,
popup=folium.Popup(display_text, max_width=300),
icon=folium.Icon(color=colors_mapping.get(request_type, "blue"), icon=icon_name)
).add_to(m)
# Macro to add legend
m.get_root().add_child(legend_macro)
st_data = st_folium(m, use_container_width=True)
# Google Sheet Table
st.subheader("📝 **Table of requests / جدول الطلبات** https://forms.gle/nZNCUVog9ka2Vdqu6")
st.markdown(
"""
<iframe src="https://docs.google.com/spreadsheets/d/1gYoBBiBo1L18IVakHkf3t1fOGvHWb23loadyFZUeHJs/" width="100%" height="600px"></iframe>
<br>
""",
unsafe_allow_html=True,
)
# Google Sheet Table
st.subheader("📝 **Table of interventions / جدول عمليات المساعدة** https://forms.gle/PsNSuHHjTTgwQMmVA")
st.markdown(
"""
<iframe src="https://docs.google.com/spreadsheets/d/1eXOTqunOWWP8FRdENPs4cU9ulISm4XZWYJJNR1-SrwY/?single=true&gid=419657423&range=f2:g6&widget=false&chrome=false" width="100%" height="600px"></iframe>
<br>
""",
unsafe_allow_html=True,
)
# chat.sendMessage(`https://www.google.com/maps/search/?api=1&query=${location.latitude},${location.longitude}`);
# Submit an id for review
st.subheader("🔍 Review of requests")
st.markdown("If you intervened to solve a request, please fill this [form](https://docs.google.com/forms/d/e/1FAIpQLSe8D6T__DJDTVGMrIWMT-H-hQ0qDUWVOncKnrSXgv4NbwHCrQ/viewform)")
st.markdown("إذا تدخلت لحل طلب، يرجى ملء هذا [النموذج](https://docs.google.com/forms/d/e/1FAIpQLSe8D6T__DJDTVGMrIWMT-H-hQ0qDUWVOncKnrSXgv4NbwHCrQ/viewform)")
st.markdown("**If a request should be reviewed or dropped submit its id here/ إذا كان يجب مراجعة أو حذف طلب، أدخل رقمه هنا:**")
id_to_review = st.number_input("Enter id / أدخل الرقم", min_value=0, max_value=len(df), value=0, step=1)
reason_for_review = st.text_area("Explain why / أدخل سبب المراجعة")
if st.button("Submit / أرسل"):
if reason_for_review == "":
st.error("Please enter a reason / الرجاء إدخال سبب")
else:
filename = f"review_id_{id_to_review}_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.txt"
with open(filename, "w") as f:
f.write(f"id: {id_to_review}, explanation: {reason_for_review}\n")
api.upload_file(
path_or_fileobj=filename,
path_in_repo=filename,
repo_id="nt3awnou/review_requests",
repo_type="dataset",
)
st.success("Submitted at https://huggingface.co/datasets/nt3awnou/review_requests/ تم الإرسال")
# Credits
st.markdown(
"""
<hr>
<div style="text-align: center;">
<p>By <b>Moroccans</b> for <b>Moroccans</b> 🤝</p>
<p>Bot powered by <a href="https://www.annarabic.com/">Annarabic</a></p>
<p>Collaboration made possible thanks to <a href="https://summerschool.morocco.ai/">AI Summer School</a></p>
""",
unsafe_allow_html=True,
)
if auto_refresh:
time.sleep(number)
st.experimental_rerun() |