Spaces:
Sleeping
Sleeping
very minimalvp
Browse files- .env_template +2 -0
- .gitignore +2 -0
- README.md +16 -2
- app/pages/1_π_Flood_extent_analysis.py +5 -65
- app/src/gfm.py +85 -0
- requirements.txt +2 -1
.env_template
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
gfm_username=your-gfm-username
|
2 |
+
gfm_password=your-gfm-password
|
.gitignore
CHANGED
@@ -1,3 +1,5 @@
|
|
|
|
|
|
1 |
# Byte-compiled / optimized / DLL files
|
2 |
__pycache__/
|
3 |
*.py[cod]
|
|
|
1 |
+
.env
|
2 |
+
|
3 |
# Byte-compiled / optimized / DLL files
|
4 |
__pycache__/
|
5 |
*.py[cod]
|
README.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1 |
# Flood Mapping Tool
|
2 |
-
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
# Flood Mapping Tool
|
2 |
+
|
3 |
+
## Installation & Running
|
4 |
+
### GFM account
|
5 |
+
To run the app you will need a (free) GFM account. To get one register at https://portal.gfm.eodc.eu/login . Once you have an account create a file `.env` with the content of `.env_template` where you will need to fill out your GFM username and password. The `.env` file will be gitignored.
|
6 |
+
|
7 |
+
### Python
|
8 |
+
For now kept on python 3.10 like original Mapaction app. Create and activate your python3.10 venv in your preferred way, then:
|
9 |
+
```
|
10 |
+
pip install -r requirements.txt
|
11 |
+
streamlit run app/Home.py
|
12 |
+
```
|
13 |
+
For now its kept on python 3.10 like original Mapaction app and packages have not yet been updated.
|
14 |
+
Just create venv and pip install requirements. Then `streamlit run app/Home.py`
|
15 |
+
|
16 |
+
## Project
|
17 |
+
TODO: Add more complete documentation.
|
app/pages/1_π_Flood_extent_analysis.py
CHANGED
@@ -1,21 +1,16 @@
|
|
1 |
"""Flood extent analysis page for Streamlit app."""
|
2 |
|
3 |
-
import datetime as dt
|
4 |
-
|
5 |
import folium
|
6 |
-
import geemap.foliumap as geemap
|
7 |
-
import requests
|
8 |
import streamlit as st
|
9 |
-
import streamlit_ext as ste
|
10 |
from folium.plugins import Draw, Geocoder, MiniMap
|
11 |
from src.config_parameters import params
|
|
|
12 |
from src.utils import (
|
13 |
add_about,
|
14 |
add_logo,
|
15 |
set_tool_page_style,
|
16 |
toggle_menu_button,
|
17 |
)
|
18 |
-
from src.utils_flood_analysis import derive_flood_extents
|
19 |
from streamlit_folium import st_folium
|
20 |
|
21 |
# Page configuration
|
@@ -37,14 +32,14 @@ set_tool_page_style()
|
|
37 |
# Output_created is useful to decide whether the bottom panel with the
|
38 |
# output map should be visualised or not
|
39 |
if "output_created" not in st.session_state:
|
40 |
-
st.session_state.output_created =
|
41 |
|
42 |
|
43 |
# Function to be used to hide bottom panel (when setting parameters for a
|
44 |
# new analysis)
|
45 |
def callback():
|
46 |
"""Set output created to zero: reset tool."""
|
47 |
-
st.session_state.output_created =
|
48 |
|
49 |
|
50 |
# Create two rows: top and bottom panel
|
@@ -119,6 +114,7 @@ if submitted:
|
|
119 |
coords = output["all_drawings"][-1]["geometry"]["coordinates"][0]
|
120 |
print(f"Coords: {coords}")
|
121 |
# Create geometry from coordinates
|
|
|
122 |
st.session_state.output_created = True
|
123 |
|
124 |
# If computation was successful, create output map in bottom panel
|
@@ -126,60 +122,4 @@ if st.session_state.output_created:
|
|
126 |
with row2:
|
127 |
# Add collapsable container for output map
|
128 |
with st.expander("Output map", expanded=True):
|
129 |
-
|
130 |
-
# # Export Map2 to streamlit
|
131 |
-
# st.session_state.Map2.to_streamlit()
|
132 |
-
# # Create button to export to file
|
133 |
-
# submitted2 = st.button("Export to file")
|
134 |
-
# # What happens if button is clicked on?
|
135 |
-
# if submitted2:
|
136 |
-
# # Add output for computation
|
137 |
-
# with st.spinner("Computing... Please wait..."):
|
138 |
-
# try:
|
139 |
-
# # Get download url for raster data
|
140 |
-
# raster = st.session_state.detected_flood_raster
|
141 |
-
# url_r = raster.getDownloadUrl(
|
142 |
-
# {
|
143 |
-
# "region": st.session_state.ee_geom_region,
|
144 |
-
# "scale": 30,
|
145 |
-
# "format": "GEO_TIFF",
|
146 |
-
# }
|
147 |
-
# )
|
148 |
-
# except Exception:
|
149 |
-
# st.error(
|
150 |
-
# """
|
151 |
-
# The image size is too big for the image to
|
152 |
-
# be exported to file. Select a smaller area
|
153 |
-
# of interest (side <~ 150km) and repeat the
|
154 |
-
# analysis.
|
155 |
-
# """
|
156 |
-
# )
|
157 |
-
# else:
|
158 |
-
# response_r = requests.get(url_r)
|
159 |
-
# # Get download url for raster data
|
160 |
-
# vector = st.session_state.detected_flood_vector
|
161 |
-
# url_v = vector.getDownloadUrl("GEOJSON")
|
162 |
-
# response_v = requests.get(url_v)
|
163 |
-
# filename = "flood_extent"
|
164 |
-
# timestamp = dt.datetime.now().strftime("%Y-%m-%d_%H-%M")
|
165 |
-
# with row2:
|
166 |
-
# # Create download buttons for raster and vector
|
167 |
-
# # data
|
168 |
-
# with open("flood_extent.tif", "wb"):
|
169 |
-
# ste.download_button(
|
170 |
-
# label="Download Raster Extent",
|
171 |
-
# data=response_r.content,
|
172 |
-
# file_name=(f"{filename}_raster_{timestamp}.tif"),
|
173 |
-
# mime="image/tif",
|
174 |
-
# )
|
175 |
-
# with open("flood_extent.geojson", "wb"):
|
176 |
-
# ste.download_button(
|
177 |
-
# label="Download Vector Extent",
|
178 |
-
# data=response_v.content,
|
179 |
-
# file_name=(
|
180 |
-
# f"{filename}_vector_{timestamp}.geojson"
|
181 |
-
# ),
|
182 |
-
# mime="text/json",
|
183 |
-
# )
|
184 |
-
# # Output for computation complete
|
185 |
-
# st.success("Computation complete")
|
|
|
1 |
"""Flood extent analysis page for Streamlit app."""
|
2 |
|
|
|
|
|
3 |
import folium
|
|
|
|
|
4 |
import streamlit as st
|
|
|
5 |
from folium.plugins import Draw, Geocoder, MiniMap
|
6 |
from src.config_parameters import params
|
7 |
+
from src.gfm import download_stuff, visualise_stuff
|
8 |
from src.utils import (
|
9 |
add_about,
|
10 |
add_logo,
|
11 |
set_tool_page_style,
|
12 |
toggle_menu_button,
|
13 |
)
|
|
|
14 |
from streamlit_folium import st_folium
|
15 |
|
16 |
# Page configuration
|
|
|
32 |
# Output_created is useful to decide whether the bottom panel with the
|
33 |
# output map should be visualised or not
|
34 |
if "output_created" not in st.session_state:
|
35 |
+
st.session_state.output_created = True
|
36 |
|
37 |
|
38 |
# Function to be used to hide bottom panel (when setting parameters for a
|
39 |
# new analysis)
|
40 |
def callback():
|
41 |
"""Set output created to zero: reset tool."""
|
42 |
+
st.session_state.output_created = True
|
43 |
|
44 |
|
45 |
# Create two rows: top and bottom panel
|
|
|
114 |
coords = output["all_drawings"][-1]["geometry"]["coordinates"][0]
|
115 |
print(f"Coords: {coords}")
|
116 |
# Create geometry from coordinates
|
117 |
+
download_stuff(coords)
|
118 |
st.session_state.output_created = True
|
119 |
|
120 |
# If computation was successful, create output map in bottom panel
|
|
|
122 |
with row2:
|
123 |
# Add collapsable container for output map
|
124 |
with st.expander("Output map", expanded=True):
|
125 |
+
visualise_stuff()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/src/gfm.py
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import io
|
2 |
+
import json
|
3 |
+
import os
|
4 |
+
import zipfile
|
5 |
+
from pathlib import Path
|
6 |
+
|
7 |
+
import folium
|
8 |
+
import requests
|
9 |
+
from dotenv import load_dotenv
|
10 |
+
from streamlit_folium import st_folium
|
11 |
+
|
12 |
+
load_dotenv()
|
13 |
+
|
14 |
+
|
15 |
+
def download_stuff(coordinates):
|
16 |
+
username = os.environ["gfm_username"]
|
17 |
+
password = os.environ["gfm_password"]
|
18 |
+
base_url = "https://api.gfm.eodc.eu/v1"
|
19 |
+
|
20 |
+
# Get token, setup header
|
21 |
+
token_url = f"{base_url}/auth/login"
|
22 |
+
|
23 |
+
payload = {"email": username, "password": password}
|
24 |
+
|
25 |
+
response = requests.post(token_url, json=payload)
|
26 |
+
user_id = response.json()["client_id"]
|
27 |
+
access_token = response.json()["access_token"]
|
28 |
+
header = {"Authorization": f"bearer {access_token}"}
|
29 |
+
print("logged in")
|
30 |
+
|
31 |
+
# Create area of impact
|
32 |
+
create_aoi_url = f"{base_url}/aoi/create"
|
33 |
+
|
34 |
+
payload = {
|
35 |
+
"aoi_name": "new_area",
|
36 |
+
"description": "new_area",
|
37 |
+
"user_id": user_id,
|
38 |
+
"geoJSON": {"type": "Polygon", "coordinates": [coordinates]},
|
39 |
+
}
|
40 |
+
|
41 |
+
r = requests.post(url=create_aoi_url, json=payload, headers=header)
|
42 |
+
print(r.text)
|
43 |
+
print("Posted new AOI")
|
44 |
+
# Get Area of Impact
|
45 |
+
aoi_url = f"{base_url}/aoi/user/{user_id}"
|
46 |
+
|
47 |
+
response = requests.get(aoi_url, headers=header)
|
48 |
+
for aoi in response.json()["aois"]:
|
49 |
+
if aoi["aoi_name"] == "new_area":
|
50 |
+
aoi_id = aoi["aoi_id"]
|
51 |
+
break
|
52 |
+
|
53 |
+
# Get product id
|
54 |
+
prod_url = f"{base_url}/aoi/{aoi_id}/products"
|
55 |
+
response = requests.get(prod_url, headers=header)
|
56 |
+
product_id = response.json()["products"][0]["product_id"]
|
57 |
+
print(f"got product_id {product_id}")
|
58 |
+
|
59 |
+
# Get download link
|
60 |
+
download_url = f"{base_url}/download/product/{product_id}"
|
61 |
+
response = requests.get(download_url, headers=header)
|
62 |
+
download_link = response.json()["download_link"]
|
63 |
+
print("Got download link")
|
64 |
+
|
65 |
+
# Download and unzip file
|
66 |
+
for f in Path("./output").glob("*"):
|
67 |
+
f.unlink()
|
68 |
+
r = requests.get(download_link)
|
69 |
+
z = zipfile.ZipFile(io.BytesIO(r.content))
|
70 |
+
z.extractall("./output")
|
71 |
+
|
72 |
+
|
73 |
+
def visualise_stuff():
|
74 |
+
# get geosjon with floods
|
75 |
+
for f in Path("./output").glob("*"):
|
76 |
+
if "FLOOD" in str(f) and "geojson" in str(f):
|
77 |
+
geojson_path = f
|
78 |
+
|
79 |
+
# Create map
|
80 |
+
flood_geojson = json.load(open(geojson_path))
|
81 |
+
|
82 |
+
m = folium.Map([54, -2], zoom_start=7)
|
83 |
+
folium.GeoJson(flood_geojson, name="geojson").add_to(m)
|
84 |
+
m
|
85 |
+
st_folium(m, width=800, height=450, returned_objects=[])
|
requirements.txt
CHANGED
@@ -5,4 +5,5 @@ streamlit==1.14.1
|
|
5 |
streamlit_ext==0.1.4
|
6 |
streamlit-folium==0.7.0
|
7 |
pre-commit==2.18.1
|
8 |
-
altair<5
|
|
|
|
5 |
streamlit_ext==0.1.4
|
6 |
streamlit-folium==0.7.0
|
7 |
pre-commit==2.18.1
|
8 |
+
altair<5
|
9 |
+
python-dotenv==1.0.1
|