|
import os |
|
import utils |
|
import streamlit as st |
|
import geopandas as gpd |
|
from streamlit_folium import st_folium, folium_static |
|
from authentication import greeting, check_password |
|
import folium |
|
from senHub import SenHub |
|
from datetime import datetime |
|
from sentinelhub import SHConfig, MimeType |
|
import requests |
|
import process |
|
import joblib |
|
from zipfile import ZipFile |
|
import matplotlib.pyplot as plt |
|
from plotly.subplots import make_subplots |
|
import plotly.graph_objects as go |
|
import pydeck as pdk |
|
import pandas as pd |
|
import plotly.express as px |
|
|
|
def check_authentication(): |
|
if not check_password(): |
|
st.stop() |
|
|
|
|
|
|
|
config = SHConfig() |
|
config.instance_id = '6c220beb-90c4-4131-b658-10cddd8d97b9' |
|
config.sh_client_id = '17e7c154-7f2d-4139-b1af-cef762385079' |
|
config.sh_client_secret = 'KvbQMKZB85ZWEgWuxqiWIVEvTAQEfoF9' |
|
|
|
|
|
def select_field(gdf): |
|
st.markdown(""" |
|
<style> |
|
.stSelectbox > div > div {cursor: pointer;} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
names = gdf['name'].tolist() |
|
names.append("Select Field") |
|
field_name = st.selectbox("Select Field", options=names, key="field_name_monitor", help="Select the field to edit", index=len(names)-1) |
|
return field_name |
|
|
|
|
|
def calculate_bbox(df, field): |
|
bbox = df.loc[df['name'] == field].bounds |
|
r = bbox.iloc[0] |
|
return [r.minx, r.miny, r.maxx, r.maxy] |
|
|
|
def get_available_dates_for_field(df, field, year, start_date='', end_date=''): |
|
bbox = calculate_bbox(df, field) |
|
token = SenHub(config).token |
|
headers = utils.get_bearer_token_headers(token) |
|
if start_date == '' or end_date == '': |
|
start_date = f'{year}-01-01' |
|
end_date = f'{year}-12-31' |
|
data = f'{{ "collections": [ "sentinel-2-l2a" ], "datetime": "{start_date}T00:00:00Z/{end_date}T23:59:59Z", "bbox": {bbox}, "limit": 100, "distinct": "date" }}' |
|
response = requests.post('https://services.sentinel-hub.com/api/v1/catalog/search', headers=headers, data=data) |
|
try: |
|
features = response.json()['features'] |
|
except: |
|
print(response.json()) |
|
features = [] |
|
return features |
|
|
|
@st.cache_data |
|
def get_and_cache_available_dates(_df, field, year, start_date, end_date): |
|
dates = get_available_dates_for_field(_df, field, year, start_date, end_date) |
|
print(f'Caching Dates for {field}') |
|
return dates |
|
|
|
|
|
|
|
|
|
def get_cuarted_df_for_field(df, field, date, metric, clientName): |
|
curated_date_path = utils.get_curated_location_img_path(clientName, metric, date, field) |
|
if curated_date_path is not None: |
|
curated_df = gpd.read_file(curated_date_path) |
|
else: |
|
process.Download_image_in_given_date(clientName, metric, df, field, date) |
|
process.mask_downladed_image(clientName, metric, df, field, date) |
|
process.convert_maske_image_to_geodataframe(clientName, metric, df, field, date, df.crs) |
|
curated_date_path = utils.get_curated_location_img_path(clientName, metric, date, field) |
|
curated_df = gpd.read_file(curated_date_path) |
|
return curated_df |
|
|
|
|
|
def track(metric, field_name, src_df, client_name): |
|
|
|
dates = [] |
|
date = -1 |
|
if 'dates' not in st.session_state: |
|
st.session_state['dates'] = dates |
|
else: |
|
dates = st.session_state['dates'] |
|
if 'date' not in st.session_state: |
|
st.session_state['date'] = date |
|
else: |
|
date = st.session_state['date'] |
|
|
|
if True: |
|
start_date = '2024-01-01' |
|
today = datetime.today() |
|
end_date = today.strftime('%Y-%m-%d') |
|
year = '2024' |
|
|
|
dates = get_and_cache_available_dates(src_df, field_name, year, start_date, end_date) |
|
|
|
|
|
dates = sorted(dates) |
|
|
|
|
|
st.session_state['dates'] = dates |
|
|
|
|
|
if len(dates) > 0: |
|
st.markdown(""" |
|
<style> |
|
.stSelectbox > div > div {cursor: pointer;} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
date = st.selectbox('Select Observation Date: ', dates, index=len(dates)-1, key=f'Select Date Dropdown Menu - {metric}') |
|
if date != -1: |
|
st.write('You selected:', date) |
|
|
|
st.session_state['date'] = date |
|
else: |
|
st.write('Please Select A Date') |
|
else: |
|
st.info('No dates available for the selected field and dates range, select a different range or click the button to fetch the dates again') |
|
|
|
|
|
st.markdown('---') |
|
st.header('Show Field Data') |
|
|
|
|
|
if date != -1: |
|
|
|
|
|
with st.spinner('Loading Field Data...'): |
|
|
|
metric_data = get_cuarted_df_for_field(src_df, field_name, date, metric, client_name) |
|
cloud_cover_data = get_cuarted_df_for_field(src_df, field_name, date, 'CLP', client_name) |
|
|
|
|
|
field_data = metric_data.merge(cloud_cover_data, on='geometry') |
|
|
|
|
|
st.write(f'Field Data for {field_name} (Field ID: {field_name}) on {date}') |
|
st.write(field_data.head(2)) |
|
|
|
|
|
avg_clp = field_data[f'CLP_{date}'].mean() *100 |
|
|
|
|
|
if avg_clp > 80: |
|
st.warning(f'β οΈ The Avarage Cloud Cover is {avg_clp}%') |
|
st.info('Please Select A Different Date') |
|
|
|
|
|
|
|
|
|
title = f'{metric} for selected field {field_name} (Field ID: {field_name}) in {date}' |
|
cmap = 'RdYlGn' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
df = field_data.copy() |
|
df['latitude'] = df['geometry'].y |
|
df['longitude'] = df['geometry'].x |
|
|
|
|
|
fig = px.scatter_mapbox( |
|
df, |
|
lat='latitude', |
|
lon='longitude', |
|
color=f'{metric}_{date}', |
|
color_continuous_scale='RdYlGn', |
|
range_color=(0, 1), |
|
size_max=15, |
|
zoom=13, |
|
) |
|
|
|
|
|
fig.update_layout(mapbox_style="open-street-map") |
|
st.plotly_chart(fig) |
|
|
|
|
|
|
|
|
|
if len(field_data) > 0: |
|
|
|
download_as_shp_col, download_as_tiff_col = st.columns(2) |
|
|
|
|
|
with download_as_shp_col: |
|
|
|
|
|
extension = 'shp' |
|
shapefilename = f"{field_name}_{metric}_{date}.{extension}" |
|
path = f'./shapefiles/{field_name}/{metric}/{extension}' |
|
|
|
|
|
os.makedirs(path, exist_ok=True) |
|
|
|
|
|
field_data.to_file(f'{path}/{shapefilename}') |
|
|
|
|
|
files = [] |
|
for i in os.listdir(path): |
|
if os.path.isfile(os.path.join(path,i)): |
|
if i[0:len(shapefilename)] == shapefilename: |
|
files.append(os.path.join(path,i)) |
|
zipFileName = f'{path}/{field_name}_{metric}_{date}.zip' |
|
zipObj = ZipFile(zipFileName, 'w') |
|
for file in files: |
|
zipObj.write(file) |
|
zipObj.close() |
|
|
|
|
|
with open(zipFileName, 'rb') as f: |
|
st.download_button('Download as ShapeFile', f,file_name=zipFileName) |
|
|
|
|
|
with download_as_tiff_col: |
|
|
|
tiff_path = utils.get_masked_location_img_path(client_name, metric, date, field_name) |
|
|
|
donwnload_filename = f'{metric}_{field_name}_{date}.tiff' |
|
with open(tiff_path, 'rb') as f: |
|
st.download_button('Download as Tiff File', f,file_name=donwnload_filename) |
|
|
|
else: |
|
st.info('Please Select A Field and A Date') |
|
|
|
|
|
def monitor_fields(): |
|
current_user = greeting("Let's take a look how these fields are doing") |
|
if os.path.exists(f"fields_{current_user}.parquet"): |
|
gdf = gpd.read_parquet(f"fields_{current_user}.parquet") |
|
else: |
|
st.info("No Fields Added Yet!") |
|
return |
|
|
|
|
|
with st.expander("Existing Fields List", expanded=False): |
|
st.write(gdf) |
|
|
|
field_name = select_field(gdf) |
|
if field_name == "Select Field": |
|
st.info("No Field Selected Yet!") |
|
|
|
else: |
|
with st.expander("Metrics Explanation", expanded=False): |
|
st.write("NDVI: Normalized Difference Vegetation Index, Mainly used to monitor the health of vegetation") |
|
st.write("LAI: Leaf Area Index, Mainly used to monitor the productivity of vegetation") |
|
st.write("CAB: Chlorophyll Absorption in the Blue band, Mainly used to monitor the chlorophyll content in vegetation") |
|
|
|
st.success("More metrics and analysis features will be added soon") |
|
metric = st.radio("Select Metric to Monitor", ["NDVI", "LAI", "CAB"], key="metric", index=0, help="Select the metric to monitor") |
|
st.write(f"Monitoring {metric} for {field_name}") |
|
|
|
track(metric, field_name, gdf, current_user) |
|
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
check_authentication() |
|
monitor_fields() |