Esmaeilkianii commited on
Commit
31fcf33
·
verified ·
1 Parent(s): cfea7f9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +202 -154
app.py CHANGED
@@ -1,183 +1,231 @@
1
  import streamlit as st
2
  import pandas as pd
3
  import numpy as np
4
- import plotly.express as px
5
- import plotly.graph_objects as go
6
- from datetime import datetime, timedelta
7
  import requests
8
  import json
9
- import ee
10
- import pydeck as pdk
11
- from geopy.geocoders import Nominatim
12
- import matplotlib.pyplot as plt
 
 
13
  from reportlab.pdfgen import canvas
14
  from reportlab.lib.pagesizes import letter
15
- import io
16
 
 
17
  st.set_page_config(
18
- page_title="Dehkoda Sugar Field Monitoring",
 
19
  layout="wide",
20
  initial_sidebar_state="expanded"
21
  )
22
 
23
- # Apply dark theme
24
- def set_dark_theme():
25
- st.markdown("""
26
  <style>
27
- .stApp {
28
- background-color: #1a1a1a;
29
- color: #ffffff;
30
- }
31
- .css-1d391kg, .st-bb, .st-at, .st-ax {
32
- background-color: #2d2d2d !important;
33
- }
 
 
 
 
 
 
 
 
 
 
34
  </style>
35
- """, unsafe_allow_html=True)
36
-
37
- set_dark_theme()
38
-
39
- # Google Earth Engine Authentication
40
- service_account = "esmaeil-kiani1387-gmail-com@ee-esmaeilkiani13877.iam.gserviceaccount.com"
41
- credentials = ee.ServiceAccountCredentials(service_account, 'ee-esmaeilkiani13877-9a054809a4bb.json')
42
- ee.Initialize(credentials)
43
-
44
- # API Keys
45
- OPENWEATHER_API = "ed47316a45379e2221a75f813229fb46"
46
- WINDY_API = "ohZom14Dr9JPKOaeUoY8nBxKdiK2yURW"
47
 
 
48
  @st.cache_data
49
  def load_farm_data():
50
- return pd.read_csv("tableConvert.com_wftamx (1).csv")
51
-
52
- df_farms = load_farm_data()
53
-
54
- def get_weather(lat, lon):
55
- url = f"https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={OPENWEATHER_API}&units=metric"
56
- response = requests.get(url).json()
57
- return {
58
- 'temp': response['main']['temp'],
59
- 'humidity': response['main']['humidity'],
60
- 'wind_speed': response['wind']['speed'],
61
- 'wind_deg': response['wind']['deg'],
62
- 'weather': response['weather'][0]['main']
63
- }
64
-
65
- def fetch_ndvi_data(field_geom, start_date, end_date):
66
- collection = ee.ImageCollection('COPERNICUS/S2') \
67
- .filterBounds(field_geom) \
68
- .filterDate(start_date, end_date)
69
 
70
- def calculate_ndvi(image):
71
  ndvi = image.normalizedDifference(['B8', 'B4']).rename('NDVI')
72
  return image.addBands(ndvi)
73
 
74
- ndvi_collection = collection.map(calculate_ndvi)
75
- return ndvi_collection.select('NDVI')
76
-
77
- with st.sidebar:
78
- st.title("Field Explorer")
79
- search_query = st.text_input("Search fields")
80
- filtered_farms = df_farms[df_farms['name'].str.contains(search_query, case=False)]
81
- selected_farm = st.selectbox("Select Farm", filtered_farms['name'])
82
- selected_data = df_farms[df_farms['name'] == selected_farm].iloc[0]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
 
84
- # Right Sidebar - Weather & Info
85
- with st.expander("Farm Details", expanded=True):
86
- st.header(selected_data['name'])
87
- st.subheader("Vital Statistics")
88
- st.metric("Age", f"{selected_data['age']} years")
89
- st.metric("Variety", selected_data['variety'])
90
 
91
- # Weather Data
92
- weather = get_weather(selected_data['latitude'], selected_data['longitude'])
93
- st.subheader("Current Weather")
94
- cols = st.columns(2)
95
- cols[0].metric("Temperature", f"{weather['temp']}°C")
96
- cols[1].metric("Humidity", f"{weather['humidity']}%")
97
- cols[0].metric("Wind Speed", f"{weather['wind_speed']} m/s")
98
- cols[1].metric("Condition", weather['weather'])
99
-
100
- st.title(f"Field Monitoring Dashboard - {selected_data['name']}")
101
-
102
- # Temperature & NDVI Chart
103
- st.subheader("Temperature & NDVI Analysis")
104
- date_range = st.date_input("Select Date Range",
105
- [datetime.today() - timedelta(days=7), datetime.today()])
106
-
107
- # Generate sample temperature data
108
- dates = pd.date_range(date_range[0], date_range[1])
109
- temps = np.random.uniform(low=15, high=35, size=len(dates))
110
- ndvi = np.random.uniform(low=0.2, high=0.8, size=len(dates))
111
-
112
- fig = go.Figure()
113
- fig.add_trace(go.Scatter(x=dates, y=temps, name='Temperature'))
114
- fig.add_trace(go.Scatter(x=dates, y=ndvi, name='NDVI', yaxis='y2'))
115
- fig.update_layout(
116
- yaxis=dict(title="Temperature (°C)"),
117
- yaxis2=dict(title="NDVI", overlaying='y', side='right'),
118
- template="plotly_dark"
119
- )
120
- st.plotly_chart(fig, use_container_width=True)
121
-
122
- # NDVI Map
123
- st.subheader("Field Health Analysis")
124
- field_geom = ee.Geometry.Point([selected_data['longitude'], selected_data['latitude']]).buffer(500)
125
- ndvi_data = fetch_ndvi_data(field_geom, str(date_range[0]), str(date_range[1]))
126
- mean_ndvi = ndvi_data.mean().getInfo()['bands'][0]['stats']['mean']
127
-
128
- st.pydeck_chart(pdk.Deck(
129
- map_style='mapbox://styles/mapbox/dark-v10',
130
- initial_view_state=pdk.ViewState(
131
- latitude=selected_data['latitude'],
132
- longitude=selected_data['longitude'],
133
- zoom=12,
134
- pitch=50,
135
- ),
136
- layers=[
137
- pdk.Layer(
138
- 'ScatterplotLayer',
139
- data=pd.DataFrame({
140
- 'lat': [selected_data['latitude']],
141
- 'lon': [selected_data['longitude']],
142
- 'color': [[0, 255, 0] if mean_ndvi > 0.6 else [255, 255, 0] if mean_ndvi > 0.3 else [255, 0, 0]]
143
- }),
144
- get_position='[lon, lat]',
145
- get_color='color',
146
- get_radius=200,
147
  )
148
- ]
149
- ))
150
-
151
- # --------------------------
152
- # Report Generation
153
- # --------------------------
154
- def create_pdf_report():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  buffer = io.BytesIO()
156
  c = canvas.Canvas(buffer, pagesize=letter)
157
- c.setFillColorRGB(1,1,1)
158
- c.drawString(100, 750, f"Field Report: {selected_data['name']}")
159
- c.drawString(100, 730, f"NDVI Index: {mean_ndvi:.2f}")
160
- c.drawString(100, 710, f"Weather Condition: {weather['weather']}")
 
 
161
  c.save()
162
- return buffer.getvalue()
163
-
164
- if st.button("Generate PDF Report"):
165
- pdf = create_pdf_report()
166
- st.download_button(
167
- label="Download Report",
168
- data=pdf,
169
- file_name="field_report.pdf",
170
- mime="application/pdf"
171
- )
172
-
173
- # --------------------------
174
- # Hidden API Integration
175
- # --------------------------
176
- # Windy Map Integration (Hidden branding)
177
- st.components.v1.html(f"""
178
- <iframe src="https://embed.windy.com/embed2.html?lat={selected_data['latitude']}&lon={selected_data['longitude']}&detailLat=31.534&detailLon=48.724&width=650&height=450&zoom=12&level=surface&overlay=wind&product=ecmwf&menu=&message=&marker=true&calendar=now&pressure=&type=map&location=coordinates&detail=&metricWind=default&metricTemp=default&radarRange=-1"
179
- width="100%" height="450" frameborder="0" style="border:0; margin-top:-30px"></iframe>
180
- """, height=450)
181
 
182
- with open("requirements.txt", "w") as f:
183
- f.write("""
 
1
  import streamlit as st
2
  import pandas as pd
3
  import numpy as np
4
+ import folium
5
+ from streamlit_folium import folium_static
6
+ import ee
7
  import requests
8
  import json
9
+ from datetime import datetime, timedelta
10
+ import plotly.express as px
11
+ import plotly.graph_objects as go
12
+ from PIL import Image
13
+ import io
14
+ import base64
15
  from reportlab.pdfgen import canvas
16
  from reportlab.lib.pagesizes import letter
17
+ import os
18
 
19
+ # Page config
20
  st.set_page_config(
21
+ page_title="مانیتورینگ مزارع نیشکر دهخدا",
22
+ page_icon="🌾",
23
  layout="wide",
24
  initial_sidebar_state="expanded"
25
  )
26
 
27
+ # Apply custom CSS for dark theme
28
+ st.markdown("""
 
29
  <style>
30
+ .reportview-container {
31
+ background: #0e1117;
32
+ color: #fafafa;
33
+ }
34
+ .sidebar .sidebar-content {
35
+ background: #262730;
36
+ }
37
+ .Widget>label {
38
+ color: #fafafa;
39
+ }
40
+ .stButton>button {
41
+ background-color: #4CAF50;
42
+ color: white;
43
+ }
44
+ .stProgress .st-bo {
45
+ background-color: #4CAF50;
46
+ }
47
  </style>
48
+ """, unsafe_allow_html=True)
49
+
50
+ # Initialize Earth Engine
51
+ def initialize_ee():
52
+ try:
53
+ ee.Initialize()
54
+ except:
55
+ credentials = ee.ServiceAccountCredentials(
56
+ 'esmaeil-kiani1387-gmail-com@ee-esmaeilkiani13877.iam.gserviceaccount.com',
57
+ 'ee-esmaeilkiani13877-9a054809a4bb.json'
58
+ )
59
+ ee.Initialize(credentials)
60
 
61
+ # Load farm data
62
  @st.cache_data
63
  def load_farm_data():
64
+ df = pd.read_csv('tableConvert.com_wftamx (1).csv')
65
+ return df
66
+
67
+ # NDVI calculation function
68
+ def calculate_ndvi(farm_geometry, start_date, end_date):
69
+ collection = ee.ImageCollection('COPERNICUS/S2_SR') \
70
+ .filterBounds(farm_geometry) \
71
+ .filterDate(start_date, end_date) \
72
+ .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20))
 
 
 
 
 
 
 
 
 
 
73
 
74
+ def addNDVI(image):
75
  ndvi = image.normalizedDifference(['B8', 'B4']).rename('NDVI')
76
  return image.addBands(ndvi)
77
 
78
+ ndvi_collection = collection.map(addNDVI)
79
+ return ndvi_collection
80
+
81
+ # Weather data fetching
82
+ def get_weather_data(lat, lon, api_key):
83
+ base_url = "http://api.openweathermap.org/data/2.5/weather"
84
+ params = {
85
+ "lat": lat,
86
+ "lon": lon,
87
+ "appid": api_key,
88
+ "units": "metric"
89
+ }
90
+ response = requests.get(base_url, params=params)
91
+ return response.json()
92
+
93
+ # Windy.com API integration
94
+ def get_windy_forecast(lat, lon, api_key):
95
+ base_url = "https://api.windy.com/api/point-forecast/v2"
96
+ headers = {
97
+ "Authorization": f"Bearer {api_key}"
98
+ }
99
+ params = {
100
+ "lat": lat,
101
+ "lon": lon,
102
+ "model": "gfs",
103
+ "parameters": ["wind", "temp", "humidity"]
104
+ }
105
+ response = requests.get(base_url, headers=headers, params=params)
106
+ return response.json()
107
 
108
+ # Main function
109
+ def main():
110
+ # Initialize Earth Engine
111
+ initialize_ee()
 
 
112
 
113
+ # Load farm data
114
+ farms_df = load_farm_data()
115
+
116
+ # Sidebar
117
+ st.sidebar.title("مدیریت مزارع")
118
+
119
+ # Farm search
120
+ search_query = st.sidebar.text_input("جستجوی مزرعه", "")
121
+ filtered_farms = farms_df[farms_df['name'].str.contains(search_query, case=False, na=False)]
122
+
123
+ # Farm selection
124
+ selected_farm = st.sidebar.selectbox(
125
+ "انتخاب مزرعه",
126
+ filtered_farms['name'].tolist()
127
+ )
128
+
129
+ # Main content area
130
+ col1, col2 = st.columns([2, 1])
131
+
132
+ with col1:
133
+ st.title(f"داشبورد مزرعه {selected_farm}")
134
+
135
+ # Map
136
+ farm_data = farms_df[farms_df['name'] == selected_farm].iloc[0]
137
+ m = folium.Map(
138
+ location=[farm_data['latitude'], farm_data['longitude']],
139
+ zoom_start=15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  )
141
+
142
+ # Add farm marker
143
+ folium.Marker(
144
+ [farm_data['latitude'], farm_data['longitude']],
145
+ popup=f"مزرعه {selected_farm}\nسن: {farm_data['age']}\nواریته: {farm_data['variety']}"
146
+ ).add_to(m)
147
+
148
+ folium_static(m)
149
+
150
+ # NDVI Analysis
151
+ st.subheader("تحلیل NDVI")
152
+ date_range = st.date_input(
153
+ "بازه زمانی",
154
+ [datetime.now() - timedelta(days=30), datetime.now()]
155
+ )
156
+
157
+ if len(date_range) == 2:
158
+ farm_geometry = ee.Geometry.Point([farm_data['longitude'], farm_data['latitude']])
159
+ ndvi_collection = calculate_ndvi(farm_geometry, date_range[0], date_range[1])
160
+
161
+ # Plot NDVI time series
162
+ ndvi_values = ndvi_collection.aggregate_array('NDVI').getInfo()
163
+ dates = ndvi_collection.aggregate_array('system:time_start').getInfo()
164
+
165
+ fig = px.line(
166
+ x=[datetime.fromtimestamp(d/1000) for d in dates],
167
+ y=ndvi_values,
168
+ title="NDVI Time Series",
169
+ labels={"x": "Date", "y": "NDVI"}
170
+ )
171
+ st.plotly_chart(fig)
172
+
173
+ with col2:
174
+ st.subheader("اطلاعات آب و هوا")
175
+
176
+ # Weather data
177
+ weather_data = get_weather_data(
178
+ farm_data['latitude'],
179
+ farm_data['longitude'],
180
+ "ed47316a45379e2221a75f813229fb46"
181
+ )
182
+
183
+ # Display current weather
184
+ st.metric(
185
+ "دمای فعلی",
186
+ f"{weather_data['main']['temp']}°C",
187
+ f"{weather_data['main']['temp_max'] - weather_data['main']['temp_min']}°C"
188
+ )
189
+
190
+ st.metric(
191
+ "رطوبت",
192
+ f"{weather_data['main']['humidity']}%"
193
+ )
194
+
195
+ # Wind data from Windy.com
196
+ windy_data = get_windy_forecast(
197
+ farm_data['latitude'],
198
+ farm_data['longitude'],
199
+ "ohZom14Dr9JPKOaeUoY8nBxKdiK2yURW"
200
+ )
201
+
202
+ # AI Recommendations
203
+ st.subheader("توصیه‌های هوشمند")
204
+ if farm_data['age'] > 8:
205
+ st.warning("زمان برداشت نزدیک است")
206
+
207
+ # Generate PDF Report
208
+ if st.button("دانلود گزارش"):
209
+ pdf_buffer = generate_report(selected_farm, farm_data, weather_data, ndvi_values)
210
+ st.download_button(
211
+ "دانلود PDF",
212
+ pdf_buffer,
213
+ file_name=f"farm_report_{selected_farm}.pdf",
214
+ mime="application/pdf"
215
+ )
216
+
217
+ def generate_report(farm_name, farm_data, weather_data, ndvi_values):
218
  buffer = io.BytesIO()
219
  c = canvas.Canvas(buffer, pagesize=letter)
220
+
221
+ # Add report content
222
+ c.drawString(100, 750, f"گزارش مزرعه {farm_name}")
223
+ c.drawString(100, 700, f"سن مزرعه: {farm_data['age']}")
224
+ c.drawString(100, 650, f"واریته: {farm_data['variety']}")
225
+
226
  c.save()
227
+ buffer.seek(0)
228
+ return buffer
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
 
230
+ if __name__ == "__main__":
231
+ main()