Simon Riezebos commited on
Commit
e7d92dc
Β·
1 Parent(s): bd1f455

Put images in lfs

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ *.png filter=lfs diff=lfs merge=lfs -text
app/Home.py CHANGED
@@ -26,8 +26,77 @@ st.markdown("# Home")
26
 
27
  # First section
28
  st.markdown("## Introduction")
29
- st.markdown("TODO: new introduction")
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
  # Second section
32
  st.markdown("## How to use the tool")
33
- st.markdown("TODO: new how to use the tool")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
  # First section
28
  st.markdown("## Introduction")
29
+ st.markdown(
30
+ """
31
+ The goal of this Flood Mapping Tool is to provide visual insight into the extent of flood events.
32
+ This tool does not produce its own forecasts; it leverages the flood forecasts created
33
+ by the GloFAS Global Flood Monitoring (GFM) tool and aims to make them conveniently accessible.
34
+ GFM uses satellite data from Sentinel-1 as the basis of its forecasts. More information on GFM
35
+ and Sentinel-1 can be found on the Methodology page.
36
+
37
+ How to use the Areas Of Interest and Flood Analysis pages is described below. The image below shows what
38
+ you can expect a typical usage of the app to look like.
39
+ """
40
+ )
41
+
42
+ st.image("app/img/application_example.png")
43
 
44
  # Second section
45
  st.markdown("## How to use the tool")
46
+ st.markdown("### Areas Of Interest")
47
+ st.markdown(
48
+ """
49
+ Because GFM internally works with Areas Of Interest (AOIs) our Flood Mapping Tool does as well.
50
+ An AOI is basically the rectangular bounding box within which you will want to analyze floods.
51
+ AOIs are shared among all users of the tool. If you create or delete an AOI, you will create or delete it
52
+ for all users, so keep that in mind.
53
+
54
+ There are three options on the Areas Of Interest page:
55
+ - **See Areas**: You will see all AOIs that are already available in the tool, created by you or other users.
56
+ When you hover over them you will see its name, which can be used to select it on the Flood Analysis page.
57
+ - **Create New Area**: You can create a new AOI. To create a new area do the following:
58
+ - Please first check whether an AOI that covers the area you are interested in exists already using "See Areas"
59
+ - Find the location on the map either by zooming to it or by using the looking glass icon to search for a location and jump to it
60
+ - Click the square icon, then hold down you mouse button and drag a rectangle shape on the screen
61
+ - If you are unhappy with the shape, click the trash bin icon and then your shape to remove it and start again
62
+ - If you are happy with the shape give it a (unique) name and hit the Save Area button
63
+ - Saving can take up to minute, it is externally saved to GFM which takes some time
64
+ - **Delete Area**: Select an area by name and hit the Delete button to delete it. This will not delete
65
+ the related flood products (see next section), only the AOI.
66
+ """
67
+ )
68
+ st.markdown("### Flood Analysis")
69
+ st.markdown(
70
+ """
71
+ The flood analysis page is used to analyze the forecasted extent of floods. It is a forecast because the
72
+ floods shown are the result of a forecasting model based on satellite data, as described on the Methodology page.
73
+ They are forecasts of floods in the past though, it is the likely extent of a flood at the selected date and time.
74
+ The tool does not forecast into the future.
75
+
76
+ We will define a couple of terms you will see on this page first and then visually show how to use the page.
77
+
78
+ - **AOI**: Area Of Interest as described in the previous section.
79
+ - **Sentinel Footprint**: The bounding box of the Sentinel-1 satellite image. Floods are retrieved within the footprint.
80
+ This will be a rectangle but it can be at an angle depending on the orbit path of the satellite. It is possible
81
+ that a footprint only covers part of your AOI, so it is displayed to show you for which part of the AOI
82
+ information is available.
83
+ - **Product**: As described on the Methodology page this application shows flood extents forecasted by GFM.
84
+ GFM offers their forecasts as products so we use the same terminology. A product contains the flood extents
85
+ within a specific Sentinel Footprint, as described above, on a specific date and time, the time when the
86
+ Sentinel measurements were taken.
87
+ - **Product Time Group**: Sometimes your AOI will be large enough to have multiple products associated with it
88
+ with timestamps just a couple seconds apart. This happens because the satellite first collected data for
89
+ the first product and a few seconds later created the second product adjacent to it. In this case we group
90
+ the products together and label them with the first timestamp of the group. In this case you can possibly see
91
+ a more oddly shaped footprint, because it is multiple nearby footprints stitched together.
92
+
93
+ Using the page is more easily described visually. Below are some screenshots of the page with how-to-use
94
+ descriptions in red.
95
+ """
96
+ )
97
+
98
+ st.image("app/img/flood_analysis_doc1.png")
99
+ st.image("app/img/flood_analysis_doc2.png")
100
+ st.image("app/img/flood_analysis_doc3.png")
101
+ st.image("app/img/flood_analysis_doc4.png")
102
+ st.image("app/img/flood_analysis_doc5.png")
app/img/MA-logo.png ADDED

Git LFS Details

  • SHA256: 4b798cb8f88ed3d429d458baa01b8efc7606e3d5f803d228d83712ac776c039d
  • Pointer size: 130 Bytes
  • Size of remote file: 21.2 kB
app/img/application_example.png ADDED

Git LFS Details

  • SHA256: a4258b268b20afa897e62c279739649475c1199ba89e1ba87a3127cc9908513c
  • Pointer size: 131 Bytes
  • Size of remote file: 523 kB
app/img/flood_analysis_doc1.png ADDED

Git LFS Details

  • SHA256: cc0de0ecfc869ea8d6568938022abb476eeca9137daa47e02572e9a0ae3f51f8
  • Pointer size: 131 Bytes
  • Size of remote file: 745 kB
app/img/flood_analysis_doc2.png ADDED

Git LFS Details

  • SHA256: 838682226236ddc95b6a57838647fc6650dcbe416d1717fc360b93f1280e1457
  • Pointer size: 131 Bytes
  • Size of remote file: 825 kB
app/img/flood_analysis_doc3.png ADDED

Git LFS Details

  • SHA256: 9a723f10ffad5dfab936a72492bc45fcedf4ab078d2ae33703b4352c92d22d7c
  • Pointer size: 131 Bytes
  • Size of remote file: 824 kB
app/img/flood_analysis_doc4.png ADDED

Git LFS Details

  • SHA256: 0b9adeecb6802d5b4049214b519915d0bbf7871e066758f2200d515c57b4bd41
  • Pointer size: 131 Bytes
  • Size of remote file: 812 kB
app/img/flood_analysis_doc5.png ADDED

Git LFS Details

  • SHA256: 3c23aa7b3856d0cf6faf20a12745a9d257c34c22b3642cfeab01fcceeb2d56f6
  • Pointer size: 131 Bytes
  • Size of remote file: 836 kB
app/pages/{0_🌍_AOIs.py β†’ 0_🌍_Areas_Of_Interest.py} RENAMED
@@ -21,7 +21,7 @@ toggle_menu_button()
21
  add_about()
22
 
23
  # Page title
24
- st.markdown("# AOIs")
25
 
26
  # Set page style
27
  set_tool_page_style()
 
21
  add_about()
22
 
23
  # Page title
24
+ st.markdown("# Areas Of Interest")
25
 
26
  # Set page style
27
  set_tool_page_style()
app/pages/{1_πŸ’§_Flood_extent_analysis.py β†’ 1_πŸ’§_Flood_Analysis.py} RENAMED
@@ -58,13 +58,13 @@ def on_area_selector_change():
58
 
59
  # Contains AOI selector
60
  with col1:
61
- selected_area_name_id = st.selectbox(
62
- "Select saved AOI",
63
- options=[aoi["name_id_preview"] for aoi in aois.values()],
64
  on_change=on_area_selector_change,
65
  )
66
 
67
- selected_area_id = get_aoi_id_from_selector_preview(aois, selected_area_name_id)
68
 
69
  # Contain datepickers
70
  with col2:
@@ -86,7 +86,7 @@ with col4:
86
  it will not trigger any product downloads.
87
  """,
88
  )
89
- show_available_products = st.button("Show GFM products")
90
 
91
  # If button above is triggered, get products from GFM
92
  # Then save all products to the session state and rerun the app to display them
@@ -166,45 +166,49 @@ with row_buttons:
166
 
167
  # Contains the "Download Products" button
168
  with below_checkbox_col1:
169
- st.text(
170
- "Button info",
171
- help=""
172
- """
173
- Will download the selected products from GFM to the Floodmap app
174
- (click "Show available products" first if there are none).
175
- Products that show that they have already been downloaded can be left checked,
176
- they will be skipped.
177
- """,
178
- )
179
- download_products = st.button("Download to Floodmap")
180
-
181
- # If the button is clicked download all checked products that have not been downloaded yet
182
- if download_products:
183
- index_df = hf_utils.get_geojson_index_df()
184
- # Get selected time groups from the table
185
- selected_time_groups = product_groups_st_df[product_groups_st_df["Check"]][
186
- "Product time"
187
- ].tolist()
188
-
189
- # For each selected time group
190
- for time_group in selected_time_groups:
191
- # Get all products for this time group
192
- products_in_group = [
193
- p
194
- for p in st.session_state["all_products"]
195
- if p["product_time_group"] == time_group
196
- ]
197
-
198
- # Download each product in the group that hasn't been downloaded yet
199
- for product_to_download in products_in_group:
200
- if product_to_download["product_id"] not in index_df["product"].values:
201
- with st.spinner(
202
- f"Getting GFM files for {product_to_download['product_time']}, this may take a couple of minutes"
 
203
  ):
204
- gfm.download_flood_product(
205
- selected_area_id, product_to_download
206
- )
207
- st.rerun()
 
 
 
208
 
209
  # For all the selected products add them to the map if they are available
210
  feature_groups = []
@@ -309,7 +313,7 @@ with col2_1:
309
  <div style="display: flex; align-items: center; gap: 20px;">
310
  <div style="display: flex; align-items: center;">
311
  <div style="width: 20px; height: 20px; background: rgba(51, 136, 255, .2); border: 1px solid #3388ff;"></div>
312
- <div style="margin-left: 5px;">AOI</div>
313
  </div>
314
  {flood_part_of_legend}
315
  </div>
 
58
 
59
  # Contains AOI selector
60
  with col1:
61
+ selected_area_name = st.selectbox(
62
+ "Select saved area (AOI)",
63
+ options=[aoi["name"] for aoi in aois.values()],
64
  on_change=on_area_selector_change,
65
  )
66
 
67
+ selected_area_id = get_aoi_id_from_selector_preview(aois, selected_area_name)
68
 
69
  # Contain datepickers
70
  with col2:
 
86
  it will not trigger any product downloads.
87
  """,
88
  )
89
+ show_available_products = st.button("Show available products")
90
 
91
  # If button above is triggered, get products from GFM
92
  # Then save all products to the session state and rerun the app to display them
 
166
 
167
  # Contains the "Download Products" button
168
  with below_checkbox_col1:
169
+ if st.session_state["all_products"]:
170
+ st.text(
171
+ "Button info",
172
+ help=""
173
+ """
174
+ Will download the selected products from GFM to the Floodmap app
175
+ (click "Show available products" first if there are none).
176
+ Products that show that they have already been downloaded can be left checked,
177
+ they will be skipped.
178
+ """,
179
+ )
180
+ download_products = st.button("Download product to tool")
181
+
182
+ # If the button is clicked download all checked products that have not been downloaded yet
183
+ if download_products:
184
+ index_df = hf_utils.get_geojson_index_df()
185
+ # Get selected time groups from the table
186
+ selected_time_groups = product_groups_st_df[product_groups_st_df["Check"]][
187
+ "Product time"
188
+ ].tolist()
189
+
190
+ # For each selected time group
191
+ for time_group in selected_time_groups:
192
+ # Get all products for this time group
193
+ products_in_group = [
194
+ p
195
+ for p in st.session_state["all_products"]
196
+ if p["product_time_group"] == time_group
197
+ ]
198
+
199
+ # Download each product in the group that hasn't been downloaded yet
200
+ for product_to_download in products_in_group:
201
+ if (
202
+ product_to_download["product_id"]
203
+ not in index_df["product"].values
204
  ):
205
+ with st.spinner(
206
+ f"Getting GFM files for {product_to_download['product_time']}, this may take a couple of minutes"
207
+ ):
208
+ gfm.download_flood_product(
209
+ selected_area_id, product_to_download
210
+ )
211
+ st.rerun()
212
 
213
  # For all the selected products add them to the map if they are available
214
  feature_groups = []
 
313
  <div style="display: flex; align-items: center; gap: 20px;">
314
  <div style="display: flex; align-items: center;">
315
  <div style="width: 20px; height: 20px; background: rgba(51, 136, 255, .2); border: 1px solid #3388ff;"></div>
316
+ <div style="margin-left: 5px;">Area Of Interest</div>
317
  </div>
318
  {flood_part_of_legend}
319
  </div>
app/pages/{2_πŸ“–_Documentation.py β†’ 2_πŸ“–_Methodology.py} RENAMED
@@ -26,7 +26,36 @@ st.markdown("# Documentation")
26
  # First section
27
  st.markdown("## Methodology")
28
  st.markdown(
29
- "TODO: new documentation, only kept in Sentinel 1 section unchanged from the Mapaction tool"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  )
31
 
32
 
@@ -34,37 +63,13 @@ st.markdown(
34
  st.markdown("## Radar imagery for flood detection")
35
  st.markdown(
36
  """
37
- While there are multiple change detections techniques for radar imagery,
38
- the one used by Sentinel-1 is one of the simplest. Active radar satellites
39
- produce active radiation directed at the land, and images are formed as a
40
- function of the time it takes for that radiation to reach back to the
41
- satellite. Because of this, radar systems are side-looking (otherwise
42
- radiation from multiple areas would reach back at the same time). To be
43
- detected and imaged, radiation needs to be scattered back, but not all
44
- surfaces are equally able to scatter back, and that ability is also
45
- influenced by the radiation's wavelength (shorter wavelengths are better at
46
- detecting smaller objects, while longer wavelengths allow penetration,
47
- which is good for forest canopies for example, and biomass studies).
48
- Sentinel-1 satellites are C-band (~ 6 cm).<br><br>
49
- Water is characterised by a mirror-like reflection mechanism, meaning that
50
- no or very little radiation is scattered back to the satellite, so pixels
51
- on the image will appear very dark. This very simple change detection takes
52
- a "before" image, and looks for drops in intensity, dark spots, in the
53
- "after" image.<br><br>
54
  Sentinel-1 data is the result of measurements from a constellation of two
55
  satellites, assing over the same areas following the same orbit on average
56
- every 6 days. On Google Earth Engine, the processing level is Ground Range
57
- Detected (GRD), meaning that it has been detected, multi-looked and
58
- projected to ground range using an Earth ellipsoid model. GRD products
59
- report on intensity of radiation, but have lost the phase and amplitude
60
- information which is needed for other applications (interferometry for
61
- example). These satellites emits in different polarizations, and can
62
- acquire both single horizonal or vertical, or dual polarizations. Flood
63
- water is best detected by using VH (vertical transmit and horizontal
64
- receive), although VV (vertical transmit and vertical receive) can be
65
- effective to identify partially submerged features. This tool uses VH
66
- polarization. Figure 2 shows an overview of the Sentinel-1 observation
67
  plan, where pass directions and coverage frequencies are highlighted.
 
 
68
  """,
69
  unsafe_allow_html=True,
70
  )
@@ -74,13 +79,3 @@ st.image(
74
  "%s" % params["url_sentinel_img"],
75
  width=1000,
76
  )
77
- st.markdown(
78
- """
79
- <p style="font-size:%s;">
80
- Figure 2. Overview of the Sentinel-1 observation plan (<a href=
81
- '%s'>source</a>).
82
- </p>
83
- """
84
- % (params["docs_caption_fontsize"], params["url_sentinel_img_location"]),
85
- unsafe_allow_html=True,
86
- )
 
26
  # First section
27
  st.markdown("## Methodology")
28
  st.markdown(
29
+ """
30
+ This tool does not produce its own forecasts; it leverages the flood forecasts created
31
+ by the GloFAS Global Flood Monitoring tool and aims to make them conveniently accessible.
32
+
33
+ The GFM products are generated using flood detection algorithms applied to Sentinel-1 satellite data,
34
+ which captures radar imagery in all weather conditions. Sentinel-1 data,
35
+ acquired in Interferometric Wide-swath mode and VV-polarization, is preprocessed into Analysis-Ready Data
36
+ (ARD) with a 10x10 m pixel resolution. Three flood detection algorithms are then run in parallel on
37
+ this ARD:
38
+
39
+ - **HASARD (by LIST)**: Uses image comparison and statistical modeling to detect changes in
40
+ flood-related signals.
41
+ - **Alg2 (by DLR)**: Applies fuzzy logic and hierarchical thresholding to classify flooded areas.
42
+ - **Alg3 (by TUW)**: Leverages long-term signal history and statistical modeling for efficient
43
+ global flood mapping.
44
+
45
+ Each algorithm independently classifies flooded pixels, and their results are
46
+ combined into a consensus map. A pixel is marked as flooded if at least two of the three algorithms
47
+ agree. This ensemble approach improves accuracy and ensures near-real-time flood monitoring globally.
48
+
49
+ Detailed documentation on the methodology is available on the GloFAS
50
+ website: https://global-flood.emergency.copernicus.eu/technical-information/glofas-gfm/
51
+
52
+ The GloFAS documentation mentions 11 products that are published. The products used in this tool are
53
+
54
+ - **The observed flood extent**: these are the floods shown in red when analyzing floods on the
55
+ "Flood Analysis" page
56
+ - **The Sentinel-1 footprint**: this is the bounding box of the Sentinel-1 satellite image that contains the
57
+ flood, shown in yellow when analyzing floods
58
+ """
59
  )
60
 
61
 
 
63
  st.markdown("## Radar imagery for flood detection")
64
  st.markdown(
65
  """
66
+ As described above, GFM uses Sentinel-1 data as the basis for its flood forecast.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  Sentinel-1 data is the result of measurements from a constellation of two
68
  satellites, assing over the same areas following the same orbit on average
69
+ every 6 days. The figure below shows an overview of the Sentinel-1 observation
 
 
 
 
 
 
 
 
 
 
70
  plan, where pass directions and coverage frequencies are highlighted.
71
+ More detailed documentation on Sentinel-1 can be found on the Copernicus website:
72
+ https://sentiwiki.copernicus.eu/web/sentinel-1
73
  """,
74
  unsafe_allow_html=True,
75
  )
 
79
  "%s" % params["url_sentinel_img"],
80
  width=1000,
81
  )
 
 
 
 
 
 
 
 
 
 
app/src/config_parameters.py CHANGED
@@ -8,7 +8,7 @@ params = {
8
  "Daniele": "[email protected]",
9
  },
10
  # Urls
11
- "url_github_repo": "https://github.com/mapaction/flood-extent-tool",
12
  "url_sentinel_dataset": (
13
  "https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S1_GRD"
14
  ),
 
8
  "Daniele": "[email protected]",
9
  },
10
  # Urls
11
+ "url_github_repo": "https://github.com/rodekruis/flood-mapping-tool",
12
  "url_sentinel_dataset": (
13
  "https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S1_GRD"
14
  ),
app/src/utils.py CHANGED
@@ -10,9 +10,9 @@ from src import hf_utils
10
  from src.config_parameters import params
11
 
12
 
13
- def get_aoi_id_from_selector_preview(all_aois, name_id_preview):
14
  for aoi_id, aoi in all_aois.items():
15
- if aoi["name_id_preview"] == name_id_preview:
16
  return aoi_id
17
 
18
 
@@ -111,11 +111,10 @@ def add_about():
111
  None
112
  """
113
  # About textbox
114
- st.sidebar.markdown("## About")
115
  st.sidebar.markdown(
116
  f"""
117
  <p>
118
- Todo: general about stuff <br />
119
  <a href='{params["url_github_repo"]}'>
120
  Github Repo</a>
121
  </p>
 
10
  from src.config_parameters import params
11
 
12
 
13
+ def get_aoi_id_from_selector_preview(all_aois, name):
14
  for aoi_id, aoi in all_aois.items():
15
+ if aoi["name"] == name:
16
  return aoi_id
17
 
18
 
 
111
  None
112
  """
113
  # About textbox
114
+ st.sidebar.markdown("## Source Code")
115
  st.sidebar.markdown(
116
  f"""
117
  <p>
 
118
  <a href='{params["url_github_repo"]}'>
119
  Github Repo</a>
120
  </p>