diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 71e7777..15ee8a4 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -10,7 +10,7 @@ All contribution is welcome (_adding features✨, bug fix🔧, bug report🐛, d - Open a new issue stating the subject of your upcoming contribution if no already existing open issue is related to the subject. - If it's a **one-time issue**, ask a maintainer to assign you to the issue before starting to work on it. - Always make sure your own fork of the repo is up to date (sync) with the original repo. - +- Updating the `Streamlit` package changes the class names of elements > Requires updating CSS class names. ### Issues - Issues are labbeled to make them easier for contributors/mantainers to identify. @@ -19,7 +19,7 @@ All contribution is welcome (_adding features✨, bug fix🔧, bug report🐛, d ### Branches -I'm using integrated GitFfow for this project, so the setup is: +I'm using integrated GitFlow for this project, so the setup is: **Branches:** - Master = streamlit-app diff --git a/README.md b/README.md index f72ca44..2ff70c5 100644 --- a/README.md +++ b/README.md @@ -40,4 +40,6 @@ This project was first developed as a submission to the Environemental Data Chal ### Credit -The app was developped by [IndigoWizard](https://github.com/IndigoWizard) and [Emmarie-Ahtunan](https://github.com/Emmarie-Ahtunan) using; Streamlit, Google Earth Engine Python API, geemap, Folium. Agriculture icons created by dreamicons - Flaticon +The app was developped by [IndigoWizard](https://github.com/IndigoWizard) using; Streamlit, Google Earth Engine Python API, geemap, Folium. Agriculture icons created by dreamicons - Flaticon + +**Contributors**: [Emmarie-Ahtunan](https://github.com/Emmarie-Ahtunan) diff --git a/app.py b/app.py index b1b2348..d09edff 100644 --- a/app.py +++ b/app.py @@ -23,7 +23,7 @@ """ """, unsafe_allow_html=True) @@ -148,27 +175,46 @@ def clipCollection(image): collection = collection.map(clipCollection) return collection -# Uplaod function +# Upload function +# Define a global variable to store the centroid of the last uploaded geometry +last_uploaded_centroid = None def upload_files_proc(upload_files): + # A global variable to track the latest geojson uploaded + global last_uploaded_centroid + # Setting up a variable that takes all polygons/geometries within the same/different geojson geometry_aoi_list = [] + for upload_file in upload_files: bytes_data = upload_file.read() - # Parse GeoJSON data geojson_data = json.loads(bytes_data) - # Extract the coordinates from the GeoJSON data - coordinates = geojson_data['features'][0]['geometry']['coordinates'] - # Creating gee geometry object based on coordinates - geometry = ee.Geometry.Polygon(coordinates) - # Adding geometry to the list - geometry_aoi_list.append(geometry) - # Combine multiple geometries from same/different files + + if 'features' in geojson_data and isinstance(geojson_data['features'], list): + # Handle GeoJSON files with a 'features' list + features = geojson_data['features'] + elif 'geometries' in geojson_data and isinstance(geojson_data['geometries'], list): + # Handle GeoJSON files with a 'geometries' list + features = [{'geometry': geo} for geo in geojson_data['geometries']] + else: + # handling cases of unexpected file format or missing 'features' or 'geometries' + continue + + for feature in features: + if 'geometry' in feature and 'coordinates' in feature['geometry']: + coordinates = feature['geometry']['coordinates'] + geometry = ee.Geometry.Polygon(coordinates) if feature['geometry']['type'] == 'Polygon' else ee.Geometry.MultiPolygon(coordinates) + geometry_aoi_list.append(geometry) + + # Update the last uploaded centroid + last_uploaded_centroid = geometry.centroid(maxError=1).getInfo()['coordinates'] + if geometry_aoi_list: geometry_aoi = ee.Geometry.MultiPolygon(geometry_aoi_list) else: - # Set default geometry if no file uploaded geometry_aoi = ee.Geometry.Point([27.98, 36.13]) + return geometry_aoi + # Time input processing function def date_input_proc(input_date, time_range): end_date = input_date @@ -196,8 +242,8 @@ def main(): - [Interpreting the Results](#interpreting-the-results) - [Environmental Index](#using-an-environmental-index-ndvi) - [Data](#data-sentinel-2-imagery-and-l2a-product) - - [About](#about) - [Contribution](#contribute-to-the-app) + - [About](#about) - [Credit](#credit) """) @@ -272,8 +318,17 @@ def main(): #### User input section - END #### Map section - START - # Setting up main map - m = folium.Map(location=[36.45, 2.85], tiles=None, zoom_start=9, control_scale=True) + global last_uploaded_centroid + + # Create the initial map + if last_uploaded_centroid is not None: + latitude = last_uploaded_centroid[1] + longitude = last_uploaded_centroid[0] + m = folium.Map(location=[latitude, longitude], tiles=None, zoom_start=12, control_scale=True) + else: + # Default location if no file is uploaded + m = folium.Map(location=[36.45, 10.85], tiles=None, zoom_start=4, control_scale=True) + ### BASEMAPS - START ## Primary basemaps @@ -347,7 +402,7 @@ def satImageMask(sat_image): updated_ndvi = satImageMask(updated_ndvi) # ##### NDVI classification: 7 classes - def classify_ndvi(masked_image): # better used an masked image to avoid water bodies obstracting the result + def classify_ndvi(masked_image): # better use a masked image to avoid water bodies obstracting the result as possible ndvi_classified = ee.Image(masked_image) \ .where(masked_image.gte(0).And(masked_image.lt(0.15)), 1) \ .where(masked_image.gte(0.15).And(masked_image.lt(0.25)), 2) \ @@ -414,7 +469,7 @@ def classify_ndvi(masked_image): # better used an masked image to avoid water bo with col3: # Create an HTML legend for NDVI classes ndvi_legend_html = """ -
+
Raw NDVI
@@ -432,8 +487,8 @@ def classify_ndvi(masked_image): # better used an masked image to avoid water bo with col4: # Create an HTML legend for NDVI classes reclassified_ndvi_legend_html = """ -
-
Reclassified NDVI
+
+
NDVI Classes
  • Absent Vegetation. (Water/Clouds/Built-up/Rocks/Sand Surfaces..)
  • Bare Soil.
  • @@ -499,17 +554,16 @@ def classify_ndvi(masked_image): # better used an masked image to avoid water bo #### Miscs Info - END - #### About App - START - st.subheader("About:") - st.markdown("This project was first developed by me ([IndigoWizard](https://github.com/IndigoWizard)) and [Emmarie-Ahtunan](https://github.com/Emmarie-Ahtunan) as a submission to the **Environemental Data Challenge** of [Global Hack Week: Data](https://ghw.mlh.io/) by [Major League Hacking](https://mlh.io/).
    I continued developing the base project to make it a feature-complete app. Check the project's GitHub Repo here: [IndigoWizard/NDVI-Viewer](https://github.com/IndigoWizard/NDVI-Viewer)", unsafe_allow_html=True) - st.image("https://www.pixenli.com/image/Hn1xkB-6") - #### About App - END - #### Contributiuon - START st.header("Contribute to the App") - st.markdown(""" + con1, con2 = st.columns(2) + con1.image("https://www.pixenli.com/image/SoL3iZMG") + con2.markdown(""" Contributions are welcome from the community to help improve this app! Whether you're interested in fixing bugs 🐞, implementing a new feature 🌟, or enhancing the user experience 🪄, your contributions are valuable. - + + The project is listed under **Hacktoberfest** lalbel for those of you [Hacktoberfest](https://hacktoberfest.com/) enthusiasts! Since the reward for contributing 4 PRs is getting a tree planted in your name through [TreeNation](https://tree-nation.com/), I see it fits the theme of this project. + """) + st.markdown(""" #### Ways to Contribute - **Report Issues**: If you come across any bugs, issues, or unexpected behavior, please report them in the [GitHub Issue Tracker](https://github.com/IndigoWizard/NDVI-Viewer/issues). @@ -521,6 +575,12 @@ def classify_ndvi(masked_image): # better used an masked image to avoid water bo #### Contributiuon - START + #### About App - START + st.subheader("About:") + st.markdown("This project was first developed by me ([IndigoWizard](https://github.com/IndigoWizard)) and [Emmarie-Ahtunan](https://github.com/Emmarie-Ahtunan) as a submission to the **Environemental Data Challenge** of [Global Hack Week: Data](https://ghw.mlh.io/) by [Major League Hacking](https://mlh.io/).
    I continued developing the base project to make it a feature-complete app. Check the project's GitHub Repo here: [IndigoWizard/NDVI-Viewer](https://github.com/IndigoWizard/NDVI-Viewer)", unsafe_allow_html=True) + st.image("https://www.pixenli.com/image/Hn1xkB-6") + #### About App - END + #### Credit - START st.subheader("Credit:") st.markdown("""The app was developped by [IndigoWizard](https://github.com/IndigoWizard) using; [Streamlit](https://streamlit.io/), [Google Earth Engine](https://github.com/google/earthengine-api) Python API, [geemap](https://github.com/gee-community/geemap), [Folium](https://github.com/python-visualization/folium). Agriculture icons created by dreamicons - Flaticon""", unsafe_allow_html=True) diff --git a/requirements.txt b/requirements.txt index 03a1275..efb2a05 100644 Binary files a/requirements.txt and b/requirements.txt differ