giswqs commited on
Commit
bbea6a9
·
1 Parent(s): 93b383c

Added MODIS timelapse

Browse files
Files changed (3) hide show
  1. apps/home.py +1 -1
  2. apps/rois.py +71 -6
  3. apps/timelapse.py +96 -25
apps/home.py CHANGED
@@ -7,7 +7,7 @@ def app():
7
 
8
  st.markdown(
9
  """
10
- This multi-page web app demonstrates various interative web apps created using [streamlit](https://streamlit.io) and open-source mapping libraries,
11
  such as [leafmap](https://leafmap.org), [geemap](https://geemap.org), [pydeck](https://deckgl.readthedocs.io), and [kepler.gl](https://docs.kepler.gl/docs/keplergl-jupyter).
12
  This is an open-source project and you are very welcome to contribute your comments, questions, resources, and apps as [issues](https://github.com/giswqs/streamlit-geospatial/issues) or
13
  [pull requests](https://github.com/giswqs/streamlit-geospatial/pulls) to the [GitHub repository](https://github.com/giswqs/streamlit-geospatial).
 
7
 
8
  st.markdown(
9
  """
10
+ This multi-page web app demonstrates various interactive web apps created using [streamlit](https://streamlit.io) and open-source mapping libraries,
11
  such as [leafmap](https://leafmap.org), [geemap](https://geemap.org), [pydeck](https://deckgl.readthedocs.io), and [kepler.gl](https://docs.kepler.gl/docs/keplergl-jupyter).
12
  This is an open-source project and you are very welcome to contribute your comments, questions, resources, and apps as [issues](https://github.com/giswqs/streamlit-geospatial/issues) or
13
  [pull requests](https://github.com/giswqs/streamlit-geospatial/pulls) to the [GitHub repository](https://github.com/giswqs/streamlit-geospatial).
apps/rois.py CHANGED
@@ -5,12 +5,27 @@ from shapely.geometry import Polygon
5
 
6
  goes_rois = {
7
  "Creek Fire, CA (2020-09-05)": {
8
- "region": Polygon([[-121.003418, 36.848857], [-121.003418, 39.049052], [-117.905273, 39.049052], [-117.905273, 36.848857], [-121.003418, 36.848857]]),
 
 
 
 
 
 
 
 
9
  "start_time": "2020-09-05T15:00:00",
10
  "end_time": "2020-09-06T02:00:00",
11
  },
12
  "Bomb Cyclone (2021-10-24)": {
13
- "region": Polygon([[-159.5954, 60.4088], [-159.5954, 24.5178], [-114.2438, 24.5178], [-114.2438, 60.4088]]),
 
 
 
 
 
 
 
14
  "start_time": "2021-10-24T14:00:00",
15
  "end_time": "2021-10-25T01:00:00",
16
  },
@@ -18,9 +33,59 @@ goes_rois = {
18
 
19
 
20
  landsat_rois = {
21
- "Aral Sea": Polygon([[57.667236, 43.834527], [57.667236, 45.996962], [61.12793, 45.996962], [61.12793, 43.834527], [57.667236, 43.834527]]),
22
- "Dubai": Polygon([[54.541626, 24.763044], [54.541626, 25.427152], [55.632019, 25.427152], [55.632019, 24.763044], [54.541626, 24.763044]]),
23
- "Las Vegas, NV": Polygon([[-115.554199, 35.804449], [-115.554199, 36.558188], [-113.903503, 36.558188], [-113.903503, 35.804449], [-115.554199, 35.804449]]),
24
- "Pucallpa, Peru": Polygon([[-74.672699, -8.600032], [-74.672699, -8.254983], [-74.279938, -8.254983], [-74.279938, -8.600032]]),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  }
 
5
 
6
  goes_rois = {
7
  "Creek Fire, CA (2020-09-05)": {
8
+ "region": Polygon(
9
+ [
10
+ [-121.003418, 36.848857],
11
+ [-121.003418, 39.049052],
12
+ [-117.905273, 39.049052],
13
+ [-117.905273, 36.848857],
14
+ [-121.003418, 36.848857],
15
+ ]
16
+ ),
17
  "start_time": "2020-09-05T15:00:00",
18
  "end_time": "2020-09-06T02:00:00",
19
  },
20
  "Bomb Cyclone (2021-10-24)": {
21
+ "region": Polygon(
22
+ [
23
+ [-159.5954, 60.4088],
24
+ [-159.5954, 24.5178],
25
+ [-114.2438, 24.5178],
26
+ [-114.2438, 60.4088],
27
+ ]
28
+ ),
29
  "start_time": "2021-10-24T14:00:00",
30
  "end_time": "2021-10-25T01:00:00",
31
  },
 
33
 
34
 
35
  landsat_rois = {
36
+ "Aral Sea": Polygon(
37
+ [
38
+ [57.667236, 43.834527],
39
+ [57.667236, 45.996962],
40
+ [61.12793, 45.996962],
41
+ [61.12793, 43.834527],
42
+ [57.667236, 43.834527],
43
+ ]
44
+ ),
45
+ "Dubai": Polygon(
46
+ [
47
+ [54.541626, 24.763044],
48
+ [54.541626, 25.427152],
49
+ [55.632019, 25.427152],
50
+ [55.632019, 24.763044],
51
+ [54.541626, 24.763044],
52
+ ]
53
+ ),
54
+ "Las Vegas, NV": Polygon(
55
+ [
56
+ [-115.554199, 35.804449],
57
+ [-115.554199, 36.558188],
58
+ [-113.903503, 36.558188],
59
+ [-113.903503, 35.804449],
60
+ [-115.554199, 35.804449],
61
+ ]
62
+ ),
63
+ "Pucallpa, Peru": Polygon(
64
+ [
65
+ [-74.672699, -8.600032],
66
+ [-74.672699, -8.254983],
67
+ [-74.279938, -8.254983],
68
+ [-74.279938, -8.600032],
69
+ ]
70
+ ),
71
+ }
72
 
73
+ modis_rois = {
74
+ "Africa": Polygon(
75
+ [
76
+ [-18.6983, 38.1446],
77
+ [-18.6983, -36.1630],
78
+ [52.2293, -36.1630],
79
+ [52.2293, 38.1446],
80
+ ]
81
+ ),
82
+ "USA": Polygon(
83
+ [
84
+ [-127.177734, 23.725012],
85
+ [-127.177734, 50.792047],
86
+ [-66.269531, 50.792047],
87
+ [-66.269531, 23.725012],
88
+ [-127.177734, 23.725012],
89
+ ]
90
+ ),
91
  }
apps/timelapse.py CHANGED
@@ -5,8 +5,7 @@ import folium
5
  import streamlit as st
6
  import geemap.foliumap as geemap
7
  from datetime import date
8
- from shapely.geometry import Polygon
9
- from .rois import goes_rois, landsat_rois
10
 
11
 
12
  @st.cache
@@ -17,8 +16,7 @@ def uploaded_file_to_gdf(data):
17
 
18
  _, file_extension = os.path.splitext(data.name)
19
  file_id = str(uuid.uuid4())
20
- file_path = os.path.join(tempfile.gettempdir(),
21
- f"{file_id}{file_extension}")
22
 
23
  with open(file_path, "wb") as file:
24
  file.write(data.getbuffer())
@@ -70,6 +68,7 @@ def app():
70
  [
71
  "Landsat TM-ETM-OLI Surface Reflectance",
72
  "Geostationary Operational Environmental Satellites (GOES)",
 
73
  ],
74
  index=0,
75
  )
@@ -78,9 +77,11 @@ def app():
78
  roi_options = ["Uploaded GeoJSON"] + list(landsat_rois.keys())
79
 
80
  elif collection == "Geostationary Operational Environmental Satellites (GOES)":
81
-
82
  roi_options = ["Uploaded GeoJSON"] + list(goes_rois.keys())
83
 
 
 
 
84
  sample_roi = st.selectbox(
85
  "Select a sample ROI or upload a GeoJSON file:",
86
  roi_options,
@@ -91,7 +92,9 @@ def app():
91
  # m = geemap.Map(basemap="HYBRID", plugin_Draw=True, draw_export=True)
92
  # m.add_basemap("ROADMAP")
93
 
94
- with st.expander("Steps: Draw a rectangle on the map -> Export it as a GeoJSON -> Upload it back to the app -> Click the Submit button. Expand this tab to see a demo 👉"):
 
 
95
  video_empty = st.empty()
96
 
97
  data = st.file_uploader(
@@ -105,12 +108,14 @@ def app():
105
  # st.info(
106
  # "Steps to create a timelapse: Draw a rectangle on the map -> Export it as a GeoJSON -> Upload it back to the app -> Click Submit button"
107
  # )
108
- if collection == "Landsat TM-ETM-OLI Surface Reflectance" and (not keyword):
109
- try:
110
- # lat, lon = geemap.get_current_latlon()
111
- m.set_center(4.20, 18.63, zoom=2)
112
- except:
113
- pass
 
 
114
  else:
115
  if collection == "Landsat TM-ETM-OLI Surface Reflectance":
116
  gdf = gpd.GeoDataFrame(
@@ -123,6 +128,10 @@ def app():
123
  gdf = gpd.GeoDataFrame(
124
  index=[0], crs=crs, geometry=[goes_rois[sample_roi]["region"]]
125
  )
 
 
 
 
126
 
127
  if sample_roi != "Uploaded GeoJSON":
128
 
@@ -137,6 +146,10 @@ def app():
137
  gdf = gpd.GeoDataFrame(
138
  index=[0], crs=crs, geometry=[goes_rois[sample_roi]["region"]]
139
  )
 
 
 
 
140
  st.session_state["roi"] = geemap.geopandas_to_ee(gdf)
141
  m.add_gdf(gdf, "ROI")
142
  elif data:
@@ -186,8 +199,7 @@ def app():
186
  "Progress bar color:", "#0000ff"
187
  )
188
  years = st.slider(
189
- "Start and end year:", 1984, today.year, (
190
- 1984, today.year - 1)
191
  )
192
  months = st.slider("Start and end month:", 1, 12, (5, 10))
193
  font_size = st.slider("Font size:", 10, 50, 30)
@@ -271,8 +283,7 @@ def app():
271
  roi = st.session_state.get("roi")
272
  out_gif = geemap.temp_file_path(".gif")
273
 
274
- satellite = st.selectbox("Select a satellite:", [
275
- "GOES-17", "GOES-16"])
276
  earliest_date = datetime.date(2017, 7, 10)
277
  latest_date = datetime.date.today()
278
 
@@ -287,8 +298,7 @@ def app():
287
  roi_start_date = datetime.datetime.strptime(
288
  roi_start[:10], "%Y-%m-%d"
289
  )
290
- roi_end_date = datetime.datetime.strptime(
291
- roi_end[:10], "%Y-%m-%d")
292
  roi_start_time = datetime.time(
293
  int(roi_start[11:13]), int(roi_start[14:16])
294
  )
@@ -296,18 +306,15 @@ def app():
296
  int(roi_end[11:13]), int(roi_end[14:16])
297
  )
298
 
299
- start_date = st.date_input(
300
- "Select the start date:", roi_start_date)
301
  end_date = st.date_input("Select the end date:", roi_end_date)
302
 
303
  with st.expander("Customize timelapse"):
304
 
305
- add_fire = st.checkbox(
306
- "Add Fire/Hotspot Characterization", False)
307
 
308
  scan_type = st.selectbox(
309
- "Select a scan type:", [
310
- "Full Disk", "CONUS", "Mesoscale"]
311
  )
312
 
313
  start_time = st.time_input(
@@ -379,7 +386,8 @@ def app():
379
  if add_fire:
380
  out_fire_gif = geemap.temp_file_path(".gif")
381
  empty_fire_text.text(
382
- "Delineating Fire Hotspot... Please wait...")
 
383
  geemap.goes_fire_timelapse(
384
  out_fire_gif,
385
  start_date=start,
@@ -406,3 +414,66 @@ def app():
406
  empty_text.text(
407
  "Something went wrong, either the ROI is too big or there are no data available for the specified date range. Please try a smaller ROI or different date range."
408
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  import streamlit as st
6
  import geemap.foliumap as geemap
7
  from datetime import date
8
+ from .rois import *
 
9
 
10
 
11
  @st.cache
 
16
 
17
  _, file_extension = os.path.splitext(data.name)
18
  file_id = str(uuid.uuid4())
19
+ file_path = os.path.join(tempfile.gettempdir(), f"{file_id}{file_extension}")
 
20
 
21
  with open(file_path, "wb") as file:
22
  file.write(data.getbuffer())
 
68
  [
69
  "Landsat TM-ETM-OLI Surface Reflectance",
70
  "Geostationary Operational Environmental Satellites (GOES)",
71
+ "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km",
72
  ],
73
  index=0,
74
  )
 
77
  roi_options = ["Uploaded GeoJSON"] + list(landsat_rois.keys())
78
 
79
  elif collection == "Geostationary Operational Environmental Satellites (GOES)":
 
80
  roi_options = ["Uploaded GeoJSON"] + list(goes_rois.keys())
81
 
82
+ elif collection == "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km":
83
+ roi_options = ["Uploaded GeoJSON"] + list(modis_rois.keys())
84
+
85
  sample_roi = st.selectbox(
86
  "Select a sample ROI or upload a GeoJSON file:",
87
  roi_options,
 
92
  # m = geemap.Map(basemap="HYBRID", plugin_Draw=True, draw_export=True)
93
  # m.add_basemap("ROADMAP")
94
 
95
+ with st.expander(
96
+ "Steps: Draw a rectangle on the map -> Export it as a GeoJSON -> Upload it back to the app -> Click the Submit button. Expand this tab to see a demo 👉"
97
+ ):
98
  video_empty = st.empty()
99
 
100
  data = st.file_uploader(
 
108
  # st.info(
109
  # "Steps to create a timelapse: Draw a rectangle on the map -> Export it as a GeoJSON -> Upload it back to the app -> Click Submit button"
110
  # )
111
+ if (
112
+ collection
113
+ == "Geostationary Operational Environmental Satellites (GOES)"
114
+ and (not keyword)
115
+ ):
116
+ m.set_center(-100, 40, 3)
117
+ else:
118
+ m.set_center(4.20, 18.63, zoom=2)
119
  else:
120
  if collection == "Landsat TM-ETM-OLI Surface Reflectance":
121
  gdf = gpd.GeoDataFrame(
 
128
  gdf = gpd.GeoDataFrame(
129
  index=[0], crs=crs, geometry=[goes_rois[sample_roi]["region"]]
130
  )
131
+ elif collection == "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km":
132
+ gdf = gpd.GeoDataFrame(
133
+ index=[0], crs=crs, geometry=[modis_rois[sample_roi]]
134
+ )
135
 
136
  if sample_roi != "Uploaded GeoJSON":
137
 
 
146
  gdf = gpd.GeoDataFrame(
147
  index=[0], crs=crs, geometry=[goes_rois[sample_roi]["region"]]
148
  )
149
+ elif collection == "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km":
150
+ gdf = gpd.GeoDataFrame(
151
+ index=[0], crs=crs, geometry=[modis_rois[sample_roi]]
152
+ )
153
  st.session_state["roi"] = geemap.geopandas_to_ee(gdf)
154
  m.add_gdf(gdf, "ROI")
155
  elif data:
 
199
  "Progress bar color:", "#0000ff"
200
  )
201
  years = st.slider(
202
+ "Start and end year:", 1984, today.year, (1984, today.year)
 
203
  )
204
  months = st.slider("Start and end month:", 1, 12, (5, 10))
205
  font_size = st.slider("Font size:", 10, 50, 30)
 
283
  roi = st.session_state.get("roi")
284
  out_gif = geemap.temp_file_path(".gif")
285
 
286
+ satellite = st.selectbox("Select a satellite:", ["GOES-17", "GOES-16"])
 
287
  earliest_date = datetime.date(2017, 7, 10)
288
  latest_date = datetime.date.today()
289
 
 
298
  roi_start_date = datetime.datetime.strptime(
299
  roi_start[:10], "%Y-%m-%d"
300
  )
301
+ roi_end_date = datetime.datetime.strptime(roi_end[:10], "%Y-%m-%d")
 
302
  roi_start_time = datetime.time(
303
  int(roi_start[11:13]), int(roi_start[14:16])
304
  )
 
306
  int(roi_end[11:13]), int(roi_end[14:16])
307
  )
308
 
309
+ start_date = st.date_input("Select the start date:", roi_start_date)
 
310
  end_date = st.date_input("Select the end date:", roi_end_date)
311
 
312
  with st.expander("Customize timelapse"):
313
 
314
+ add_fire = st.checkbox("Add Fire/Hotspot Characterization", False)
 
315
 
316
  scan_type = st.selectbox(
317
+ "Select a scan type:", ["Full Disk", "CONUS", "Mesoscale"]
 
318
  )
319
 
320
  start_time = st.time_input(
 
386
  if add_fire:
387
  out_fire_gif = geemap.temp_file_path(".gif")
388
  empty_fire_text.text(
389
+ "Delineating Fire Hotspot... Please wait..."
390
+ )
391
  geemap.goes_fire_timelapse(
392
  out_fire_gif,
393
  start_date=start,
 
414
  empty_text.text(
415
  "Something went wrong, either the ROI is too big or there are no data available for the specified date range. Please try a smaller ROI or different date range."
416
  )
417
+
418
+ elif collection == "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km":
419
+
420
+ video_empty.video("https://youtu.be/16fA2QORG4A")
421
+
422
+ satellite = st.selectbox("Select a satellite:", ["Terra", "Aqua"])
423
+ band = st.selectbox("Select a band:", ["NDVI", "EVI"])
424
+
425
+ with st.form("submit_modis_form"):
426
+
427
+ roi = None
428
+ if st.session_state.get("roi") is not None:
429
+ roi = st.session_state.get("roi")
430
+ out_gif = geemap.temp_file_path(".gif")
431
+
432
+ with st.expander("Customize timelapse"):
433
+
434
+ start = st.date_input(
435
+ "Select a start date:", datetime.date(2000, 2, 8)
436
+ )
437
+ end = st.date_input("Select an end date:", datetime.date.today())
438
+
439
+ start_date = start.strftime("%Y-%m-%d")
440
+ end_date = end.strftime("%Y-%m-%d")
441
+
442
+ speed = st.slider("Frames per second:", 1, 30, 10)
443
+ add_progress_bar = st.checkbox("Add a progress bar", True)
444
+ progress_bar_color = st.color_picker(
445
+ "Progress bar color:", "#0000ff"
446
+ )
447
+ font_size = st.slider("Font size:", 10, 50, 20)
448
+ font_color = st.color_picker("Font color:", "#ffffff")
449
+ empty_text = st.empty()
450
+ empty_image = st.empty()
451
+
452
+ submitted = st.form_submit_button("Submit")
453
+ if submitted:
454
+ if sample_roi == "Uploaded GeoJSON" and data is None:
455
+ empty_text.warning(
456
+ "Steps to create a timelapse: Draw a rectangle on the map -> Export it as a GeoJSON -> Upload it back to the app -> Click the Submit button. Alternatively, you can select a sample ROI from the dropdown list."
457
+ )
458
+ else:
459
+
460
+ empty_text.text("Computing... Please wait...")
461
+
462
+ print(roi.getInfo())
463
+ geemap.modis_ndvi_timelapse(
464
+ out_gif,
465
+ satellite,
466
+ band,
467
+ start_date,
468
+ end_date,
469
+ roi,
470
+ 768,
471
+ speed,
472
+ )
473
+
474
+ geemap.reduce_gif_size(out_gif)
475
+
476
+ empty_text.text(
477
+ "Right click the GIF to save it to your computer👇"
478
+ )
479
+ empty_image.image(out_gif)