Esmaeilkiani commited on
Commit
dae6b2b
·
verified ·
1 Parent(s): dbeceab

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -433
app.py CHANGED
@@ -1,439 +1,56 @@
1
- import streamlit as st
2
  import pandas as pd
 
3
  import folium
4
  from streamlit_folium import folium_static
5
- import jdatetime
6
- import plotly.express as px
7
- from folium.plugins import HeatMap, Fullscreen, Search
8
- import branca.colormap as cm
9
- from datetime import datetime
10
- import base64
11
-
12
- # تنظیمات اولیه صفحه
13
- st.set_page_config(
14
- page_title="مدیریت چاهک‌های مزارع نیشکر",
15
- page_icon="🌱",
16
- layout="wide",
17
- initial_sidebar_state="expanded"
18
- )
19
-
20
- # CSS برای ظاهر جذاب و متحرک
21
- st.markdown(
22
- """
23
- <style>
24
- @import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;700&display=swap');
25
-
26
- * {
27
- font-family: 'Vazirmatn', sans-serif !important;
28
- }
29
-
30
- .css-1d391kg {
31
- direction: rtl;
32
- }
33
-
34
- .stButton>button {
35
- float: right;
36
- background: linear-gradient(45deg, #1CB5E0 0%, #000851 100%);
37
- color: white;
38
- transition: all 0.3s ease;
39
- }
40
-
41
- .stButton>button:hover {
42
- transform: translateY(-2px);
43
- box-shadow: 0 5px 15px rgba(0,0,0,0.2);
44
- }
45
-
46
- .css-1y4p8pa {
47
- padding: 2rem;
48
- border-radius: 15px;
49
- background: rgba(255,255,255,0.95);
50
- box-shadow: 0 8px 32px 0 rgba(31,38,135,0.37);
51
- backdrop-filter: blur(4px);
52
- margin: 1rem 0;
53
- }
54
-
55
- .css-1v0mbdj {
56
- border-radius: 15px;
57
- box-shadow: 0 4px 12px rgba(0,0,0,0.1);
58
- transition: all 0.3s ease;
59
- }
60
-
61
- .css-1v0mbdj:hover {
62
- transform: translateY(-3px);
63
- box-shadow: 0 6px 15px rgba(0,0,0,0.2);
64
- }
65
-
66
- /* انیمیشن برای عناوین */
67
- @keyframes slideIn {
68
- from {
69
- transform: translateX(50px);
70
- opacity: 0;
71
- }
72
- to {
73
- transform: translateX(0);
74
- opacity: 1;
75
- }
76
- }
77
-
78
- h1, h2, h3 {
79
- animation: slideIn 0.5s ease-out;
80
- }
81
-
82
- /* استایل برای کارت‌های آمار */
83
- .metric-card {
84
- background: linear-gradient(135deg, #00B4DB 0%, #0083B0 100%);
85
- color: white;
86
- padding: 20px;
87
- border-radius: 10px;
88
- text-align: center;
89
- transition: all 0.3s ease;
90
- }
91
-
92
- .metric-card:hover {
93
- transform: scale(1.05);
94
- }
95
- </style>
96
- """,
97
- unsafe_allow_html=True
98
- )
99
-
100
- # تعریف داده‌های اولیه با چاهک نصب شده
101
- @st.cache_data
102
- def load_initial_data():
103
- data = {
104
- 'مزرعه': ['06-10', '10-15', '12-27', '24-04', '22-21', '20-05', '14-21', '14-19', '14-24', '14-18', '22-17', '16-13', '16-27', '02-19', '02-27', '17-02', '15-22', '15-12', '15-04', '23-07'],
105
- 'کانال': ['06', '10', '12', '24', '22', '20', '14', '14', '14', '14', '22', '16', '16', '02', '02', '17', '15', '15', '15', '23'],
106
- 'چاهک_1_نصب': [True] * 20,
107
- 'چاهک_1_تکنسین': ['علی دغاغله', 'علی دغاغله', 'علی دغاغله', 'مسعود بن موسی', 'مسعود بن موسی', 'مسعود بن موسی',
108
- 'علی دغاغله', 'علی دغاغله', 'مسعود بن موسی', 'علی دغاغله', 'مسعود بن موسی', 'علی دغاغله',
109
- 'مسعود بن موسی', 'مسعود بن موسی', 'مسعود بن موسی', 'علی دغاغله', 'علی دغاغله', 'علی دغاغله',
110
- 'علی دغاغله', 'علی دغاغله'],
111
- 'چاهک_1_تاریخ': ['1404/01/10', '1404/01/09', '1404/01/08', '1404/01/12', '1404/01/12', '1404/01/11',
112
- '1404/01/10', '1404/01/09', '1404/01/11', '1404/01/09', '1404/01/10', '1404/01/12',
113
- '1404/01/12', '1404/01/16', '1404/01/16', '1404/01/16', '1404/01/16', '1404/01/16',
114
- '1404/01/16', '1404/01/16'],
115
- 'چاهک_1_lat': [31.578944, 31.551778, 31.535056, 31.446083, 31.459917, 31.459861, 31.516472, 31.515722,
116
- 31.525056, 31.525472, 31.458528, 31.496722, 31.498083, 31.597933, 31.600053, 31.494345,
117
- 31.510917, 31.512250, 31.513139, 31.448096],
118
- 'چاهک_1_lon': [48.731222, 48.721556, 48.703139, 48.713444, 48.703972, 48.722472, 48.707083, 48.711778,
119
- 48.707583, 48.713778, 48.706861, 48.715639, 48.698889, 48.721920, 48.711327, 48.737393,
120
- 48.766361, 48.750944, 48.740556, 48.738048],
121
- 'چاهک_2_نصب': [False] * 20,
122
- 'چاهک_2_تکنسین': [''] * 20,
123
- 'چاهک_2_تاریخ': [''] * 20,
124
- 'چاهک_2_lat': [0.0] * 20,
125
- 'چاهک_2_lon': [0.0] * 20,
126
- 'اداره': [1] * 20, # Placeholder value
127
- 'واریته': ['CP69'] * 20, # Placeholder value
128
- 'مساحت': [24.0] * 20, # Placeholder value
129
- }
130
- return pd.DataFrame(data)
131
-
132
- # لود داده‌ها
133
- if 'farms_data' not in st.session_state:
134
- st.session_state.farms_data = load_initial_data()
135
-
136
- # تعریف تکنسین‌ها
137
- TECHNICIANS = [
138
- 'علی دغاغله',
139
- 'علیرضا حمیدی',
140
- 'مسعود بن موسی',
141
- 'امین هنری'
142
- ]
143
-
144
- # عنوان اصلی با افکت گرادیان
145
- st.markdown(
146
- """
147
- <h1 style='text-align: center; color: #0083B0; background: -webkit-linear-gradient(45deg, #1CB5E0, #000851);
148
- -webkit-background-clip: text; -webkit-text-fill-color: transparent; padding: 20px;'>
149
- 🌱 سامانه مدیریت چاهک‌های مزارع نیشکر
150
- </h1>
151
- """,
152
- unsafe_allow_html=True
153
- )
154
-
155
- # ساید‌بار با استایل جدید
156
- with st.sidebar:
157
- st.markdown(
158
- """
159
- <div style='background: linear-gradient(45deg, #1CB5E0 0%, #000851 100%); padding: 20px; border-radius: 10px; color: white;'>
160
- <h2 style='text-align: center; margin: 0;'>🔍 فیلترها</h2>
161
- </div>
162
- """,
163
- unsafe_allow_html=True
164
- )
165
- selected_department = st.selectbox(
166
- "انتخاب اداره",
167
- options=[0, 1, 2, 3, 4],
168
- format_func=lambda x: "همه ادارات" if x == 0 else f"اداره {x}",
169
- )
170
-
171
- search_term = st.text_input("جستجو بر اساس نام مزرعه یا کانال")
172
-
173
- # فیلتر کردن داده‌ها
174
- filtered_data = st.session_state.farms_data.copy()
175
- if selected_department != 0:
176
- filtered_data = filtered_data[filtered_data['اداره'] == selected_department]
177
- if search_term:
178
- mask = (filtered_data['مزرعه'].str.contains(search_term)) | (filtered_data['کانال'].str.contains(search_term))
179
- filtered_data = filtered_data[mask]
180
-
181
- # نمایش آمار کلی با کارت‌های متحرک
182
- col1, col2, col3 = st.columns(3)
183
- with col1:
184
- st.markdown(
185
- f"""
186
- <div class='metric-card'>
187
- <h2>{len(filtered_data) * 2}</h2>
188
- <p>کل چاهک‌ها</p>
189
- </div>
190
- """,
191
- unsafe_allow_html=True
192
- )
193
-
194
- with col2:
195
- installed_wells = filtered_data['چاهک_1_نصب'].sum() + filtered_data['چاهک_2_نصب'].sum()
196
- st.markdown(
197
- f"""
198
- <div class='metric-card' style='background: linear-gradient(135deg, #00B09B 0%, #96C93D 100%);'>
199
- <h2>{installed_wells}</h2>
200
- <p>چاهک‌های نصب شده</p>
201
- </div>
202
- """,
203
- unsafe_allow_html=True
204
- )
205
-
206
- with col3:
207
- st.markdown(
208
- f"""
209
- <div class='metric-card' style='background: linear-gradient(135deg, #FF416C 0%, #FF4B2B 100%);'>
210
- <h2>{len(filtered_data) * 2 - installed_wells}</h2>
211
- <p>چاهک‌های باقی‌مانده</p>
212
- </div>
213
- """,
214
- unsafe_allow_html=True
215
- )
216
-
217
- # نمایش نقشه با تصویر ماهواره‌ای
218
- st.markdown(
219
- """
220
- <h2 style='text-align: right; color: #0083B0;'>🗺️ نقشه چاهک‌ها</h2>
221
- """,
222
- unsafe_allow_html=True
223
- )
224
 
225
- # Calculate the center of all points
226
- center_lat = filtered_data[filtered_data['چاهک_1_نصب']]['چاهک_1_lat'].mean()
227
- center_lon = filtered_data[filtered_data['چاهک_1_نصب']]['چاهک_1_lon'].mean()
228
-
229
- m = folium.Map(
230
- location=[center_lat, center_lon],
231
- zoom_start=12,
232
- tiles='https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
233
- attr='Esri',
234
- name='Satellite'
235
- )
236
-
237
- # اضافه کردن لایه OpenStreetMap برای خوانایی بهتر
238
- folium.TileLayer('OpenStreetMap').add_to(m)
239
-
240
- # اضافه کردن کنترل لایه‌ها
241
- folium.LayerControl().add_to(m)
242
-
243
- # اضافه کردن دکمه تمام صفحه
244
- Fullscreen().add_to(m)
245
-
246
- # تعریف CSS برای مارکر چشمک‌زن
247
- pulse_css = """
248
- @keyframes pulse {
249
- 0% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(0, 131, 176, 0.7); }
250
- 70% { transform: scale(1); box-shadow: 0 0 0 10px rgba(0, 131, 176, 0); }
251
- 100% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(0, 131, 176, 0); }
252
- }
253
- .pulsing-marker {
254
- width: 20px;
255
- height: 20px;
256
- background: rgba(0, 131, 176, 0.9);
257
- border-radius: 50%;
258
- animation: pulse 2s infinite;
259
- }
260
- """
261
-
262
- # اضافه کردن استایل به نقشه
263
- m.get_root().header.add_child(folium.Element(f'<style>{pulse_css}</style>'))
264
-
265
- for idx, row in filtered_data.iterrows():
266
- if row['چاهک_1_نصب'] and row['چاهک_1_lat'] != 0:
267
- popup_html = f"""
268
- <div style='direction: rtl; text-align: right; padding: 10px; min-width: 200px;'>
269
- <h4 style='color: #0083B0; margin: 0; border-bottom: 2px solid #0083B0; padding-bottom: 5px;'>
270
- کانال {row['کانال']} مزرعه {row['مزرعه']}
271
- </h4>
272
- <div style='margin-top: 10px;'>
273
- <p style='margin: 5px 0;'><strong>👨‍🌾 تکنسین:</strong> {row['چاهک_1_تکنسین']}</p>
274
- <p style='margin: 5px 0;'><strong>📅 تاریخ نصب:</strong> {row['چاهک_1_تاریخ']}</p>
275
- <p style='margin: 5px 0;'><strong>📍 موقعیت:</strong></p>
276
- <p style='margin: 5px 0; direction: ltr;'>{row['چاهک_1_lat']:.6f}°N, {row['چاهک_1_lon']:.6f}°E</p>
277
- </div>
278
- </div>
279
- """
280
-
281
- folium.CircleMarker(
282
- location=[row['چاهک_1_lat'], row['چاهک_1_lon']],
283
- radius=8,
284
- popup=folium.Popup(popup_html, max_width=300),
285
- color='#0083B0',
286
- fill=True,
287
- fill_color='#0083B0',
288
- fill_opacity=0.7,
289
- weight=2,
290
- className='pulsing-marker'
291
  ).add_to(m)
292
-
293
- if row['چاهک_2_نصب'] and row['چاهک_2_lat'] != 0:
294
- popup_html = f"""
295
- <div style='direction: rtl; text-align: right; padding: 10px;'>
296
- <h4 style='color: #FF416C; margin: 0;'>مزرعه {row['مزرعه']}</h4>
297
- <p><strong>چاهک:</strong> 2</p>
298
- <p><strong>تکنسین:</strong> {row['چاهک_2_تکنسین']}</p>
299
- <p><strong>تاریخ نصب:</strong> {row['چاهک_2_تاریخ']}</p>
300
- <p><strong>موقعیت:</strong> {row['چاهک_2_lat']:.6f}°N, {row['چاهک_2_lon']:.6f}°E</p>
301
- </div>
302
- """
303
-
304
- folium.CircleMarker(
305
- location=[row['چاهک_2_lat'], row['چاهک_2_lon']],
306
- radius=10,
307
- popup=folium.Popup(popup_html, max_width=300),
308
- color='#FF416C',
309
- fill=True,
310
- fill_color='#FF416C',
311
- fill_opacity=0.7,
312
- weight=2,
313
- className='pulsing-marker'
314
- ).add_to(m)
315
-
316
- # نمایش نقشه با اندازه بزرگتر
317
- folium_static(m, width=1200, height=600)
318
-
319
- # لیست مزارع و ثبت چاهک با ظاهر جدید
320
- st.markdown(
321
- """
322
- <h2 style='text-align: right; color: #0083B0;'>📝 لیست مزارع و ثبت چاهک</h2>
323
- """,
324
- unsafe_allow_html=True
325
- )
326
-
327
- for idx, row in filtered_data.iterrows():
328
- with st.expander(f"🌾 مزرعه {row['مزرعه']} - کانال {row['کانال']}", expanded=False):
329
- st.markdown(
330
- f"""
331
- <div style='background: linear-gradient(135deg, #f6f9fc 0%, #f0f4f8 100%); padding: 15px; border-radius: 10px;'>
332
- <p><strong>واریته:</strong> {row['واریته']}</p>
333
- <p><strong>مساحت:</strong> {row['مساحت']} هکتار</p>
334
- </div>
335
- """,
336
- unsafe_allow_html=True
337
- )
338
-
339
- col1, col2 = st.columns(2)
340
-
341
- # چاهک 1
342
- with col1:
343
- st.markdown("<h3 style='color: #0083B0;'>چاهک 1</h3>", unsafe_allow_html=True)
344
- if not row['چاهک_1_نصب']:
345
- if st.button(f"ثبت نصب چاهک 1 - مزرعه {row['مزرعه']}", key=f"well1_{idx}"):
346
- technician = st.selectbox(
347
- "انتخاب تکنسین",
348
- options=TECHNICIANS,
349
- key=f"tech1_{idx}"
350
- )
351
- lat = st.number_input("عرض جغرافیایی", value=31.504, key=f"lat1_{idx}")
352
- lon = st.number_input("طول جغرافیایی", value=48.752, key=f"lon1_{idx}")
353
- if st.button("ثبت نهایی", key=f"save1_{idx}"):
354
- st.session_state.farms_data.at[idx, 'چاهک_1_نصب'] = True
355
- st.session_state.farms_data.at[idx, 'چاهک_1_تکنسین'] = technician
356
- st.session_state.farms_data.at[idx, 'چاهک_1_تاریخ'] = jdatetime.datetime.now().strftime("%Y/%m/%d")
357
- st.session_state.farms_data.at[idx, 'چاهک_1_lat'] = lat
358
- st.session_state.farms_data.at[idx, 'چاهک_1_lon'] = lon
359
- st.success("چاهک 1 با موفقیت ثبت شد")
360
- st.rerun()
361
- else:
362
- st.markdown(
363
- f"""
364
- <div style='background: #e3f2fd; padding: 15px; border-radius: 10px;'>
365
- <p>✅ نصب شده توسط {row['چاهک_1_تکنسین']}</p>
366
- <p>📅 تاریخ نصب: {row['چاهک_1_تاریخ']}</p>
367
- <p>📍 موقعیت: {row['چاهک_1_lat']:.6f}°N, {row['چاهک_1_lon']:.6f}°E</p>
368
- </div>
369
- """,
370
- unsafe_allow_html=True
371
- )
372
-
373
- # چاهک 2 (مشابه چاهک 1)
374
- with col2:
375
- st.markdown("<h3 style='color: #FF416C;'>چاهک 2</h3>", unsafe_allow_html=True)
376
- if not row['چاهک_2_نصب']:
377
- if st.button(f"ثبت نصب چاهک 2 - مزرعه {row['مزرعه']}", key=f"well2_{idx}"):
378
- technician = st.selectbox(
379
- "انتخاب تکنسین",
380
- options=TECHNICIANS,
381
- key=f"tech2_{idx}"
382
- )
383
- lat = st.number_input("عرض جغرافیایی", value=31.504, key=f"lat2_{idx}")
384
- lon = st.number_input("طول جغرافیایی", value=48.752, key=f"lon2_{idx}")
385
- if st.button("ثبت نهایی", key=f"save2_{idx}"):
386
- st.session_state.farms_data.at[idx, 'چاهک_2_نصب'] = True
387
- st.session_state.farms_data.at[idx, 'چاهک_2_تکنسین'] = technician
388
- st.session_state.farms_data.at[idx, 'چاهک_2_تاریخ'] = jdatetime.datetime.now().strftime("%Y/%m/%d")
389
- st.session_state.farms_data.at[idx, 'چاهک_2_lat'] = lat
390
- st.session_state.farms_data.at[idx, 'چاهک_2_lon'] = lon
391
- st.success("چاهک 2 با موفقیت ثبت شد")
392
- st.rerun()
393
- else:
394
- st.markdown(
395
- f"""
396
- <div style='background: #ffe0e6; padding: 15px; border-radius: 10px;'>
397
- <p>✅ نصب شده توسط {row['چاهک_2_تکنسین']}</p>
398
- <p>📅 تاریخ نصب: {row['چاهک_2_تاریخ']}</p>
399
- <p>📍 موقعیت: {row['چاهک_2_lat']:.6f}°N, {row['چاهک_2_lon']:.6f}°E</p>
400
- </div>
401
- """,
402
- unsafe_allow_html=True
403
- )
404
-
405
- # نمودار پیشرفت نصب به تفکیک اداره
406
- st.markdown(
407
- """
408
- <h2 style='text-align: right; color: #0083B0;'>📊 گزارش پیشرفت نصب</h2>
409
- """,
410
- unsafe_allow_html=True
411
- )
412
-
413
- progress_data = []
414
- for dept in range(1, 5):
415
- dept_data = st.session_state.farms_data[st.session_state.farms_data['اداره'] == dept]
416
- total = len(dept_data) * 2
417
- installed = dept_data['چاهک_1_نصب'].sum() + dept_data['چاهک_2_نصب'].sum()
418
- progress_data.append({
419
- 'اداره': f'اداره {dept}',
420
- 'درصد پیشرفت': (installed / total * 100) if total > 0 else 0
421
- })
422
 
423
- progress_df = pd.DataFrame(progress_data)
424
- fig = px.bar(
425
- progress_df,
426
- x='اداره',
427
- y='درصد پیشرفت',
428
- title='درصد پیشرفت نصب چاهک‌ها به تفکیک اداره',
429
- color='درصد پیشرفت',
430
- color_continuous_scale='Viridis',
431
- template='plotly_white'
432
- )
433
- fig.update_layout(
434
- plot_bgcolor='rgba(0,0,0,0)',
435
- paper_bgcolor='rgba(0,0,0,0)',
436
- font_family='Vazirmatn',
437
- title_x=0.5
438
- )
439
- st.plotly_chart(fig, use_container_width=True)
 
 
1
  import pandas as pd
2
+ import streamlit as st
3
  import folium
4
  from streamlit_folium import folium_static
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
+ # خواندن داده‌ها
7
+ df_representative = pd.read_csv('مزارع نماینده راتون.csv')
8
+ df_coordinates = pd.read_csv('مختصات و مشخصات کامل مزارع (4).csv')
9
+
10
+ # استخراج لیست مزارع نماینده
11
+ representatives = df_representative['مزرعه نماینده'].unique().tolist()
12
+
13
+ # دیکشنری برای نگاشت مزرعه نماینده به زیرمجموعه‌ها
14
+ sub_farms_dict = df_representative.groupby('مزرعه نماینده')['زیر مجموعه'].apply(list).to_dict()
15
+
16
+ # رابط کاربری
17
+ st.title('داشبورد پایش هفتگی مزارع نماینده')
18
+ selected_representative = st.selectbox('انتخاب مزرعه نماینده', representatives)
19
+
20
+ if selected_representative:
21
+ # نمایش زیرمجموعه‌ها
22
+ sub_farms = sub_farms_dict[selected_representative]
23
+ st.write('**زیرمجموعه‌های مزرعه انتخاب شده:**', sub_farms)
24
+
25
+ # استخراج مختصات مزرعه نماینده
26
+ rep_coords = df_coordinates[df_coordinates['مزرعه'] == selected_representative][['عرض جغرافیایی', 'طول جغرافیایی]].values
27
+ if len(rep_coords) > 0:
28
+ rep_lat, rep_lon = rep_coords[0]
29
+ else:
30
+ st.error('مختصات مزرعه نماینده یافت نشد!')
31
+ st.stop()
32
+
33
+ # استخراج مختصات زیرمجموعه‌ها
34
+ sub_coords = df_coordinates[df_coordinates['مزرعه'].isin(sub_farms)][['عرض جغرافیایی', 'طول جغرافیایی', 'مزرعه']]
35
+
36
+ # ایجاد نقشه
37
+ m = folium.Map(location=[rep_lat, rep_lon], zoom_start=10, tiles='Satellite')
38
+
39
+ # مارکر مزرعه نماینده
40
+ folium.Marker(
41
+ [rep_lat, rep_lon],
42
+ popup=selected_representative,
43
+ icon=folium.Icon(color='blue', icon='info-sign')
44
+ ).add_to(m)
45
+
46
+ # مارکرهای زیرمجموعه‌ها
47
+ for idx, row in sub_coords.iterrows():
48
+ folium.Marker(
49
+ [row['عرض جغرافیایی'], row['طول جغرافیایی']],
50
+ popup=row['مزرعه'],
51
+ icon=folium.Icon(color='red', icon='info-sign')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  ).add_to(m)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
+ # نمایش نقشه
55
+ st.write('**نقشه مزرعه و زیرمجموعه‌ها:**')
56
+ folium_static(m)