A-O98 commited on
Commit
49ee313
1 Parent(s): 9664c31

Updated Layout

Browse files
Files changed (5) hide show
  1. app.py +51 -20
  2. authentication.py +1 -1
  3. pag/add_field.py +3 -3
  4. pag/edit.py +15 -18
  5. pag/monitor.py +38 -57
app.py CHANGED
@@ -1,27 +1,56 @@
1
  # main.py
2
  import streamlit as st
3
  import authentication
 
4
  import streamlit as st
5
- from pag import add_field, edit, monitor
 
6
 
7
 
8
  def authenticate_user():
9
- st.title("Welcome to :orange[Field Monitoring App]")
10
  st.markdown("""
11
  <style>
12
  .stSelectbox > div > div {cursor: pointer;}
13
  </style>
14
  """, unsafe_allow_html=True)
15
  if not st.session_state.authenticated:
16
- choice = st.selectbox("Interested? Sign up or log in if you have an account",options=["Home","Login","SignUp"])
 
17
 
18
- if choice == "Home":
19
- st.write("App Description")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
- elif choice == "Login":
22
- authentication.login()
23
- elif choice == "SignUp":
24
- authentication.signup()
25
 
26
  return False
27
 
@@ -33,19 +62,21 @@ def main():
33
 
34
  if st.session_state.authenticated:
35
  st.sidebar.title("Navigation")
 
 
36
  options = st.sidebar.radio("Choose an option:",
37
- ("Add Field", "Manage Fields", "Monitor Fields"))
38
-
39
- if options == "Add Field":
40
- st.title("Welcome to :orange[Field Monitoring App]")
41
-
42
- add_field.add_drawing()
43
-
44
- elif options == "Manage Fields":
45
- st.title(":orange[Field Management]")
46
- edit.edit_fields()
 
47
  elif options == "Monitor Fields":
48
- st.title(":orange[Field Monitoring]")
49
  monitor.monitor_fields()
50
  else:
51
  authenticate_user()
 
1
  # main.py
2
  import streamlit as st
3
  import authentication
4
+ from authentication import greeting
5
  import streamlit as st
6
+ from pag import add_field, edit, monitor,contact_form
7
+ st. set_page_config(layout="wide")
8
 
9
 
10
  def authenticate_user():
 
11
  st.markdown("""
12
  <style>
13
  .stSelectbox > div > div {cursor: pointer;}
14
  </style>
15
  """, unsafe_allow_html=True)
16
  if not st.session_state.authenticated:
17
+ st.title("Welcome to :orange[Field Monitoring App]")
18
+ row1_col1, row1_col2 = st.columns([2, 1])
19
 
20
+ with row1_col1:
21
+ choice = st.selectbox("Interested? Sign up or log in if you have an account",options=["Login","SignUp","Contact Us"])
22
+ if choice == "SignUp":
23
+ authentication.signup()
24
+ elif choice == "Login":
25
+ st.title("Have an account? :orange[Sign In]")
26
+ st.toast("Use your username and password to access our services", icon='😍')
27
+ authentication.login()
28
+ elif choice == "Contact Us":
29
+ contact_form.main()
30
+
31
+
32
+
33
+ with row1_col2:
34
+ st.title(":orange[App Description]")
35
+
36
+ st.markdown("""
37
+ Our application is designed to empower farmers and land managers with precise, up-to-date information about their fields. Leveraging the power of advanced satellite imagery analysis, our tool provides key metrics like the Normalized Difference Vegetation Index (NDVI) to assess plant health, moisture levels, and overall field conditions.
38
+
39
+ #### :orange[Key Features]
40
+
41
+ - **:orange[Real-time Field Data]**: Access the latest satellite data to monitor your fields in real-time.
42
+ - **:orange[Field Health Analysis]**: Utilize NDVI and other indices to make informed decisions about crop health and management strategies.
43
+ - **:orange[Interactive Map Views]**: Explore your fields with interactive maps, get detailed insights with just a click.
44
+ - **:orange[Field History Tracking]**: Review historical data to track changes and adapt your farming practices accordingly.
45
+ - **:orange[Data-Driven Insights]**: Make better decisions with insights driven by accurate, reliable data.
46
+
47
+ We are committed to providing you with the tools you need to manage your fields more effectively and increase your yields. Get started by adding your fields and see the immediate benefits of precision agriculture.
48
+
49
+ For any questions or assistance, feel free to reach out through our contact page.
50
+
51
+ Happy Farming!
52
+ """, unsafe_allow_html=True)
53
 
 
 
 
 
54
 
55
  return False
56
 
 
62
 
63
  if st.session_state.authenticated:
64
  st.sidebar.title("Navigation")
65
+ row1_col1, row1_col2 = st.columns([2, 1])
66
+
67
  options = st.sidebar.radio("Choose an option:",
68
+ ("Add and Manage Fields", "Monitor Fields"))
69
+ if options == "Add and Manage Fields":
70
+ with row1_col1:
71
+ st.title("Welcome to :orange[Field Monitoring App]")
72
+ add_field.add_drawing()
73
+ with row1_col2:
74
+ st.title(":orange[Field Management]")
75
+ current_user = greeting("Manage your fields")
76
+
77
+ edit.edit_fields(current_user)
78
+
79
  elif options == "Monitor Fields":
 
80
  monitor.monitor_fields()
81
  else:
82
  authenticate_user()
authentication.py CHANGED
@@ -172,4 +172,4 @@ def login():
172
  st.warning("Incorrect Username/Password")
173
 
174
  # Call create_usertable to ensure the table is created/updated when the script runs
175
- create_usertable()
 
172
  st.warning("Incorrect Username/Password")
173
 
174
  # Call create_usertable to ensure the table is created/updated when the script runs
175
+ create_usertable()
pag/add_field.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import utils
2
  import os
3
  import folium
@@ -8,12 +9,10 @@ from folium.plugins import Draw
8
  from shapely.geometry import Polygon
9
  from streamlit_folium import st_folium
10
  from authentication import greeting, check_password
11
- from functools import partial
12
  import geopy
13
  from pyproj import Transformer
14
  from shapely.ops import transform
15
  from geopy.geocoders import Nominatim
16
- from streamlit_folium import folium_static
17
  from shapely.ops import transform
18
  from geopy.geocoders import Nominatim
19
 
@@ -38,7 +37,7 @@ def display_existing_fields(current_user):
38
  with st.expander("Existing Fields", expanded=False):
39
  if os.path.exists(f"fields_{current_user}.parquet"):
40
  gdf = gpd.read_parquet(f"fields_{current_user}.parquet")
41
- st.write(gdf)
42
  mm = gdf.explore()
43
  st_folium(mm)
44
  else:
@@ -80,6 +79,7 @@ def display_map_and_drawing_controls(field_map, center_start):
80
  st.info("IMPORTANT: Click on the drawing to confirm the drawn field", icon="🚨")
81
  sat_basemap = utils.basemaps['Google Satellite Hybrid'] # Change this line to use 'Google Satellite Hybrid'
82
  sat_basemap.add_to(field_map)
 
83
  folium.LayerControl().add_to(field_map)
84
  output = st_folium(field_map, center=center_start, zoom=zoom_start, key="new", width=800)
85
  active_drawing = output['last_active_drawing']
 
1
+ # add_field.py
2
  import utils
3
  import os
4
  import folium
 
9
  from shapely.geometry import Polygon
10
  from streamlit_folium import st_folium
11
  from authentication import greeting, check_password
 
12
  import geopy
13
  from pyproj import Transformer
14
  from shapely.ops import transform
15
  from geopy.geocoders import Nominatim
 
16
  from shapely.ops import transform
17
  from geopy.geocoders import Nominatim
18
 
 
37
  with st.expander("Existing Fields", expanded=False):
38
  if os.path.exists(f"fields_{current_user}.parquet"):
39
  gdf = gpd.read_parquet(f"fields_{current_user}.parquet")
40
+ st.table(gdf.name.tolist())
41
  mm = gdf.explore()
42
  st_folium(mm)
43
  else:
 
79
  st.info("IMPORTANT: Click on the drawing to confirm the drawn field", icon="🚨")
80
  sat_basemap = utils.basemaps['Google Satellite Hybrid'] # Change this line to use 'Google Satellite Hybrid'
81
  sat_basemap.add_to(field_map)
82
+ folium.plugins.Geocoder().add_to(field_map)
83
  folium.LayerControl().add_to(field_map)
84
  output = st_folium(field_map, center=center_start, zoom=zoom_start, key="new", width=800)
85
  active_drawing = output['last_active_drawing']
pag/edit.py CHANGED
@@ -1,15 +1,13 @@
 
1
  import os
2
  import utils
3
  import streamlit as st
4
  import geopandas as gpd
5
- from streamlit_folium import st_folium, folium_static
6
- from authentication import greeting, check_password
7
  import folium
8
- import json
9
  import time
10
  import pandas as pd
11
 
12
-
13
  def add_properties(df, col_name, value, field_name):
14
  if col_name not in df.columns:
15
  df[col_name] = None
@@ -41,8 +39,8 @@ def read_custom_property():
41
  return custom_property_name, custom_property_value
42
 
43
 
44
- def edit_fields():
45
- current_user = greeting("Manage your fields")
46
  fields_file_path = f"fields_{current_user}.parquet"
47
  history_file_path = f"history_{current_user}.csv"
48
 
@@ -60,21 +58,21 @@ def edit_fields():
60
  history_df = pd.DataFrame(columns=['field_name', 'start_date', 'end_date', 'crop', 'irrigation_method'])
61
 
62
  st.info("Hover over the field to show the properties or check the Existing Fields List below")
63
- fields_map = gdf.explore()
64
- sat_basemap = utils.basemaps['Google Satellite']
65
- sat_basemap.add_to(fields_map)
66
- folium.LayerControl().add_to(fields_map)
67
- folium_static(fields_map, height=300, width=600)
68
-
69
- with st.expander("Existing Fields List", expanded=False):
70
- # lis = [(f"Name:{gdf.iloc[i]['name']}",f"location: {gdf.iloc[i]['geometry']}" )for i in range(len(gdf))]
71
- st.write(gdf)
72
-
73
  field_name = select_field(gdf)
74
  if field_name == "Select Field":
 
 
 
 
 
75
  st.info("No Field Selected Yet!")
76
  else:
77
- st.subheader(field_name)
 
 
 
 
 
78
  option_menu = st.radio(f"Please add your {field_name} field information, historical data will help train our AI model", options=["View Field Info", "Add Field Information","Add Field Cultivation History", "Delete"], key="option_menu", help="Select the operation to perform")
79
  if option_menu == "View Field Info":
80
  field = gdf[gdf['name'] == field_name]
@@ -105,7 +103,6 @@ def edit_fields():
105
  if custom_property_name != "" and custom_property_value != "":
106
  gdf = add_properties(gdf, custom_property_name, custom_property_value, field_name)
107
  gdf.to_parquet(f"fields_{current_user}.parquet")
108
- # st.rerun()
109
  st.success("Field Information Updated Successfully!")
110
  st.info("Please Select View above to see the updated field information")
111
 
 
1
+ # edit.py
2
  import os
3
  import utils
4
  import streamlit as st
5
  import geopandas as gpd
6
+ from streamlit_folium import folium_static
 
7
  import folium
 
8
  import time
9
  import pandas as pd
10
 
 
11
  def add_properties(df, col_name, value, field_name):
12
  if col_name not in df.columns:
13
  df[col_name] = None
 
39
  return custom_property_name, custom_property_value
40
 
41
 
42
+ def edit_fields(current_user):
43
+ # current_user = greeting("Manage your fields")
44
  fields_file_path = f"fields_{current_user}.parquet"
45
  history_file_path = f"history_{current_user}.csv"
46
 
 
58
  history_df = pd.DataFrame(columns=['field_name', 'start_date', 'end_date', 'crop', 'irrigation_method'])
59
 
60
  st.info("Hover over the field to show the properties or check the Existing Fields List below")
 
 
 
 
 
 
 
 
 
 
61
  field_name = select_field(gdf)
62
  if field_name == "Select Field":
63
+ fields_map = gdf.explore()
64
+ sat_basemap = utils.basemaps['Google Satellite']
65
+ sat_basemap.add_to(fields_map)
66
+ folium.LayerControl().add_to(fields_map)
67
+ folium_static(fields_map, height=300, width=400)
68
  st.info("No Field Selected Yet!")
69
  else:
70
+ fields_map = gdf[gdf['name'] == field_name].explore()
71
+ sat_basemap = utils.basemaps['Google Satellite']
72
+ sat_basemap.add_to(fields_map)
73
+ folium.LayerControl().add_to(fields_map)
74
+ folium_static(fields_map, height=300, width=400)
75
+ st.subheader(f":green[{field_name}]")
76
  option_menu = st.radio(f"Please add your {field_name} field information, historical data will help train our AI model", options=["View Field Info", "Add Field Information","Add Field Cultivation History", "Delete"], key="option_menu", help="Select the operation to perform")
77
  if option_menu == "View Field Info":
78
  field = gdf[gdf['name'] == field_name]
 
103
  if custom_property_name != "" and custom_property_value != "":
104
  gdf = add_properties(gdf, custom_property_name, custom_property_value, field_name)
105
  gdf.to_parquet(f"fields_{current_user}.parquet")
 
106
  st.success("Field Information Updated Successfully!")
107
  st.info("Please Select View above to see the updated field information")
108
 
pag/monitor.py CHANGED
@@ -1,22 +1,15 @@
 
1
  import os
2
  import utils
3
  import streamlit as st
4
  import geopandas as gpd
5
- from streamlit_folium import st_folium, folium_static
6
  from authentication import greeting, check_password
7
- import folium
8
  from senHub import SenHub
9
  from datetime import datetime
10
- from sentinelhub import SHConfig, MimeType
11
  import requests
12
  import process
13
- import joblib
14
  from zipfile import ZipFile
15
- import matplotlib.pyplot as plt
16
- from plotly.subplots import make_subplots
17
- import plotly.graph_objects as go
18
- import pydeck as pdk
19
- import pandas as pd
20
  import plotly.express as px
21
 
22
  def check_authentication():
@@ -87,7 +80,7 @@ def get_cuarted_df_for_field(df, field, date, metric, clientName):
87
 
88
 
89
  def track(metric, field_name, src_df, client_name):
90
-
91
  dates = []
92
  date = -1
93
  if 'dates' not in st.session_state:
@@ -147,38 +140,22 @@ def track(metric, field_name, src_df, client_name):
147
  field_data = metric_data.merge(cloud_cover_data, on='geometry')
148
 
149
  # Display the field data
150
- st.write(f'Field Data for {field_name} (Field ID: {field_name}) on {date}')
151
- st.write(field_data.head(2))
 
 
 
 
152
 
153
  #Get Avarage Cloud Cover
154
- avg_clp = field_data[f'CLP_{date}'].mean() *100
155
 
156
  # If the avarage cloud cover is greater than 80%, display a warning message
157
  if avg_clp > 80:
158
  st.warning(f'⚠️ The Avarage Cloud Cover is {avg_clp}%')
159
  st.info('Please Select A Different Date')
160
 
161
- ## Generate the field data Map ##
162
-
163
- #Title, Colormap and Legend
164
- title = f'{metric} for selected field {field_name} (Field ID: {field_name}) in {date}'
165
- cmap = 'RdYlGn'
166
-
167
- # Create a map of the field data
168
- # field_data_map = field_data.explore(
169
- # column=f'{metric}_{date}',
170
- # cmap=cmap,
171
- # legend=True,
172
- # vmin=0,
173
- # vmax=1,
174
- # marker_type='circle', marker_kwds={'radius':5.3, 'fill':True})
175
-
176
- # Add Google Satellite as a base map
177
- # google_map = utils.basemaps['Google Satellite']
178
- # google_map.add_to(field_data_map)
179
 
180
- # # Display the map
181
- # st_folium(field_data_map, width = 725, key=f'Field Data Map - {metric}')
182
  df = field_data.copy()
183
  df['latitude'] = df['geometry'].y
184
  df['longitude'] = df['geometry'].x
@@ -191,6 +168,8 @@ def track(metric, field_name, src_df, client_name):
191
  color=f'{metric}_{date}',
192
  color_continuous_scale='RdYlGn',
193
  range_color=(0, 1),
 
 
194
  size_max=15,
195
  zoom=13,
196
  )
@@ -251,32 +230,34 @@ def track(metric, field_name, src_df, client_name):
251
 
252
 
253
  def monitor_fields():
254
- current_user = greeting("Let's take a look how these fields are doing")
255
- if os.path.exists(f"fields_{current_user}.parquet"):
256
- gdf = gpd.read_parquet(f"fields_{current_user}.parquet")
257
- else:
258
- st.info("No Fields Added Yet!")
259
- return
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
 
261
-
262
- with st.expander("Existing Fields List", expanded=False):
263
- st.write(gdf)
264
 
265
- field_name = select_field(gdf)
266
- if field_name == "Select Field":
267
- st.info("No Field Selected Yet!")
268
-
269
- else:
270
- with st.expander("Metrics Explanation", expanded=False):
271
- st.write("NDVI: Normalized Difference Vegetation Index, Mainly used to monitor the health of vegetation")
272
- st.write("LAI: Leaf Area Index, Mainly used to monitor the productivity of vegetation")
273
- st.write("CAB: Chlorophyll Absorption in the Blue band, Mainly used to monitor the chlorophyll content in vegetation")
274
- # st.write("NDMI: Normalized Difference Moisture Index, Mainly used to monitor the moisture content in vegetation")
275
- st.success("More metrics and analysis features will be added soon")
276
- metric = st.radio("Select Metric to Monitor", ["NDVI", "LAI", "CAB"], key="metric", index=0, help="Select the metric to monitor")
277
- st.write(f"Monitoring {metric} for {field_name}")
278
-
279
- track(metric, field_name, gdf, current_user)
280
 
281
 
282
 
 
1
+ # monitor.py
2
  import os
3
  import utils
4
  import streamlit as st
5
  import geopandas as gpd
 
6
  from authentication import greeting, check_password
 
7
  from senHub import SenHub
8
  from datetime import datetime
9
+ from sentinelhub import SHConfig
10
  import requests
11
  import process
 
12
  from zipfile import ZipFile
 
 
 
 
 
13
  import plotly.express as px
14
 
15
  def check_authentication():
 
80
 
81
 
82
  def track(metric, field_name, src_df, client_name):
83
+ st.title(":green[Select Date and Start Monitoring]")
84
  dates = []
85
  date = -1
86
  if 'dates' not in st.session_state:
 
140
  field_data = metric_data.merge(cloud_cover_data, on='geometry')
141
 
142
  # Display the field data
143
+ avg_clp = field_data[f'CLP_{date}'].mean() *100
144
+ avg_metric = field_data[f'{metric}_{date}'].mean()
145
+ st.write(f'Field Data for (Field ID: {field_name}) on {date}')
146
+ col1,col3,col5,col2,col4 = st.columns(5)
147
+ col1.metric(f":orange[Average {metric}]", value=f"{avg_metric :.2f}")
148
+ col2.metric(":green[Cloud Cover]", value=f"{avg_clp :.2f}%")
149
 
150
  #Get Avarage Cloud Cover
 
151
 
152
  # If the avarage cloud cover is greater than 80%, display a warning message
153
  if avg_clp > 80:
154
  st.warning(f'⚠️ The Avarage Cloud Cover is {avg_clp}%')
155
  st.info('Please Select A Different Date')
156
 
157
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
 
 
 
159
  df = field_data.copy()
160
  df['latitude'] = df['geometry'].y
161
  df['longitude'] = df['geometry'].x
 
168
  color=f'{metric}_{date}',
169
  color_continuous_scale='RdYlGn',
170
  range_color=(0, 1),
171
+ width= 800,
172
+ height=600,
173
  size_max=15,
174
  zoom=13,
175
  )
 
230
 
231
 
232
  def monitor_fields():
233
+ row1,row2 = st.columns([1,2])
234
+ with row1:
235
+ st.title(":orange[Field Monitoring]")
236
+
237
+ current_user = greeting("Let's take a look how these fields are doing")
238
+ if os.path.exists(f"fields_{current_user}.parquet"):
239
+ gdf = gpd.read_parquet(f"fields_{current_user}.parquet")
240
+ field_name = select_field(gdf)
241
+ if field_name == "Select Field":
242
+ st.info("No Field Selected Yet!")
243
+ else:
244
+ metric = st.radio("Select Metric to Monitor", ["NDVI", "LAI", "CAB"], key="metric", index=0, help="Select the metric to monitor")
245
+ st.success(f"Monitoring {metric} for {field_name}")
246
+ with st.expander("Metrics Explanation", expanded=False):
247
+ st.write("NDVI: Normalized Difference Vegetation Index, Mainly used to monitor the health of vegetation")
248
+ st.write("LAI: Leaf Area Index, Mainly used to monitor the productivity of vegetation")
249
+ st.write("CAB: Chlorophyll Absorption in the Blue band, Mainly used to monitor the chlorophyll content in vegetation")
250
+ # st.write("NDMI: Normalized Difference Moisture Index, Mainly used to monitor the moisture content in vegetation")
251
+ st.info("More metrics and analysis features will be added soon")
252
+ else:
253
+ st.info("No Fields Added Yet!")
254
+ return
255
 
256
+
 
 
257
 
258
+ with row2:
259
+ if field_name != "Select Field":
260
+ track(metric, field_name, gdf, current_user)
 
 
 
 
 
 
 
 
 
 
 
 
261
 
262
 
263