aassiiyAA123 commited on
Commit
14619f9
·
verified ·
1 Parent(s): fa7fd4f

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +5 -1531
app.py CHANGED
@@ -1,1534 +1,8 @@
1
- import ee
2
- import json
3
- import os
4
- import warnings
5
- import datetime
6
- import fiona
7
- import geopandas as gpd
8
- import folium
9
  import streamlit as st
10
- import geemap.colormaps as cm
11
- import geemap.foliumap as geemap
12
- from datetime import date
13
- from shapely.geometry import Polygon
14
-
15
- st.set_page_config(layout="wide")
16
- warnings.filterwarnings("ignore")
17
-
18
-
19
- @st.cache_data
20
- def ee_authenticate(token_name="EARTHENGINE_TOKEN"):
21
- geemap.ee_initialize(token_name=token_name)
22
-
23
-
24
- st.sidebar.info(
25
- """
26
- - Web App URL: <https://streamlit.gishub.org>
27
- - GitHub repository: <https://github.com/giswqs/streamlit-geospatial>
28
- """
29
- )
30
-
31
- st.sidebar.title("Contact")
32
- st.sidebar.info(
33
- """
34
- Qiusheng Wu at [wetlands.io](https://wetlands.io) | [GitHub](https://github.com/giswqs) | [Twitter](https://twitter.com/giswqs) | [YouTube](https://www.youtube.com/c/QiushengWu) | [LinkedIn](https://www.linkedin.com/in/qiushengwu)
35
- """
36
- )
37
-
38
- goes_rois = {
39
- "Creek Fire, CA (2020-09-05)": {
40
- "region": Polygon(
41
- [
42
- [-121.003418, 36.848857],
43
- [-121.003418, 39.049052],
44
- [-117.905273, 39.049052],
45
- [-117.905273, 36.848857],
46
- [-121.003418, 36.848857],
47
- ]
48
- ),
49
- "start_time": "2020-09-05T15:00:00",
50
- "end_time": "2020-09-06T02:00:00",
51
- },
52
- "Bomb Cyclone (2021-10-24)": {
53
- "region": Polygon(
54
- [
55
- [-159.5954, 60.4088],
56
- [-159.5954, 24.5178],
57
- [-114.2438, 24.5178],
58
- [-114.2438, 60.4088],
59
- ]
60
- ),
61
- "start_time": "2021-10-24T14:00:00",
62
- "end_time": "2021-10-25T01:00:00",
63
- },
64
- "Hunga Tonga Volcanic Eruption (2022-01-15)": {
65
- "region": Polygon(
66
- [
67
- [-192.480469, -32.546813],
68
- [-192.480469, -8.754795],
69
- [-157.587891, -8.754795],
70
- [-157.587891, -32.546813],
71
- [-192.480469, -32.546813],
72
- ]
73
- ),
74
- "start_time": "2022-01-15T03:00:00",
75
- "end_time": "2022-01-15T07:00:00",
76
- },
77
- "Hunga Tonga Volcanic Eruption Closer Look (2022-01-15)": {
78
- "region": Polygon(
79
- [
80
- [-178.901367, -22.958393],
81
- [-178.901367, -17.85329],
82
- [-171.452637, -17.85329],
83
- [-171.452637, -22.958393],
84
- [-178.901367, -22.958393],
85
- ]
86
- ),
87
- "start_time": "2022-01-15T03:00:00",
88
- "end_time": "2022-01-15T07:00:00",
89
- },
90
- }
91
-
92
-
93
- landsat_rois = {
94
- "Aral Sea": Polygon(
95
- [
96
- [57.667236, 43.834527],
97
- [57.667236, 45.996962],
98
- [61.12793, 45.996962],
99
- [61.12793, 43.834527],
100
- [57.667236, 43.834527],
101
- ]
102
- ),
103
- "Dubai": Polygon(
104
- [
105
- [54.541626, 24.763044],
106
- [54.541626, 25.427152],
107
- [55.632019, 25.427152],
108
- [55.632019, 24.763044],
109
- [54.541626, 24.763044],
110
- ]
111
- ),
112
- "Hong Kong International Airport": Polygon(
113
- [
114
- [113.825226, 22.198849],
115
- [113.825226, 22.349758],
116
- [114.085121, 22.349758],
117
- [114.085121, 22.198849],
118
- [113.825226, 22.198849],
119
- ]
120
- ),
121
- "Las Vegas, NV": Polygon(
122
- [
123
- [-115.554199, 35.804449],
124
- [-115.554199, 36.558188],
125
- [-113.903503, 36.558188],
126
- [-113.903503, 35.804449],
127
- [-115.554199, 35.804449],
128
- ]
129
- ),
130
- "Pucallpa, Peru": Polygon(
131
- [
132
- [-74.672699, -8.600032],
133
- [-74.672699, -8.254983],
134
- [-74.279938, -8.254983],
135
- [-74.279938, -8.600032],
136
- ]
137
- ),
138
- "Sierra Gorda, Chile": Polygon(
139
- [
140
- [-69.315491, -22.837104],
141
- [-69.315491, -22.751488],
142
- [-69.190006, -22.751488],
143
- [-69.190006, -22.837104],
144
- [-69.315491, -22.837104],
145
- ]
146
- ),
147
- }
148
-
149
- modis_rois = {
150
- "World": Polygon(
151
- [
152
- [-171.210938, -57.136239],
153
- [-171.210938, 79.997168],
154
- [177.539063, 79.997168],
155
- [177.539063, -57.136239],
156
- [-171.210938, -57.136239],
157
- ]
158
- ),
159
- "Africa": Polygon(
160
- [
161
- [-18.6983, 38.1446],
162
- [-18.6983, -36.1630],
163
- [52.2293, -36.1630],
164
- [52.2293, 38.1446],
165
- ]
166
- ),
167
- "USA": Polygon(
168
- [
169
- [-127.177734, 23.725012],
170
- [-127.177734, 50.792047],
171
- [-66.269531, 50.792047],
172
- [-66.269531, 23.725012],
173
- [-127.177734, 23.725012],
174
- ]
175
- ),
176
- }
177
-
178
- ocean_rois = {
179
- "Gulf of Mexico": Polygon(
180
- [
181
- [-101.206055, 15.496032],
182
- [-101.206055, 32.361403],
183
- [-75.673828, 32.361403],
184
- [-75.673828, 15.496032],
185
- [-101.206055, 15.496032],
186
- ]
187
- ),
188
- "North Atlantic Ocean": Polygon(
189
- [
190
- [-85.341797, 24.046464],
191
- [-85.341797, 45.02695],
192
- [-55.810547, 45.02695],
193
- [-55.810547, 24.046464],
194
- [-85.341797, 24.046464],
195
- ]
196
- ),
197
- "World": Polygon(
198
- [
199
- [-171.210938, -57.136239],
200
- [-171.210938, 79.997168],
201
- [177.539063, 79.997168],
202
- [177.539063, -57.136239],
203
- [-171.210938, -57.136239],
204
- ]
205
- ),
206
- }
207
-
208
-
209
- @st.cache_data
210
- def uploaded_file_to_gdf(data):
211
- import tempfile
212
- import os
213
- import uuid
214
-
215
- _, file_extension = os.path.splitext(data.name)
216
- file_id = str(uuid.uuid4())
217
- file_path = os.path.join(tempfile.gettempdir(), f"{file_id}{file_extension}")
218
-
219
- with open(file_path, "wb") as file:
220
- file.write(data.getbuffer())
221
-
222
- if file_path.lower().endswith(".kml"):
223
- fiona.drvsupport.supported_drivers["KML"] = "rw"
224
- gdf = gpd.read_file(file_path, driver="KML")
225
- else:
226
- gdf = gpd.read_file(file_path)
227
-
228
- return gdf
229
-
230
-
231
- def app():
232
-
233
- today = date.today()
234
-
235
- st.title("Create Satellite Timelapse")
236
-
237
- st.markdown(
238
- """
239
- An interactive web app for creating [Landsat](https://developers.google.com/earth-engine/datasets/catalog/landsat)/[GOES](https://jstnbraaten.medium.com/goes-in-earth-engine-53fbc8783c16) timelapse for any location around the globe.
240
- The app was built using [streamlit](https://streamlit.io), [geemap](https://geemap.org), and [Google Earth Engine](https://earthengine.google.com). For more info, check out my streamlit [blog post](https://blog.streamlit.io/creating-satellite-timelapse-with-streamlit-and-earth-engine).
241
- """
242
- )
243
-
244
- row1_col1, row1_col2 = st.columns([2, 1])
245
-
246
- if st.session_state.get("zoom_level") is None:
247
- st.session_state["zoom_level"] = 4
248
-
249
- st.session_state["ee_asset_id"] = None
250
- st.session_state["bands"] = None
251
- st.session_state["palette"] = None
252
- st.session_state["vis_params"] = None
253
-
254
- with row1_col1:
255
- ee_authenticate(token_name="EARTHENGINE_TOKEN")
256
- m = geemap.Map(
257
- basemap="HYBRID",
258
- plugin_Draw=True,
259
- Draw_export=True,
260
- locate_control=True,
261
- plugin_LatLngPopup=False,
262
- )
263
- m.add_basemap("ROADMAP")
264
-
265
- with row1_col2:
266
-
267
- keyword = st.text_input("Search for a location:", "")
268
- if keyword:
269
- locations = geemap.geocode(keyword)
270
- if locations is not None and len(locations) > 0:
271
- str_locations = [str(g)[1:-1] for g in locations]
272
- location = st.selectbox("Select a location:", str_locations)
273
- loc_index = str_locations.index(location)
274
- selected_loc = locations[loc_index]
275
- lat, lng = selected_loc.lat, selected_loc.lng
276
- folium.Marker(location=[lat, lng], popup=location).add_to(m)
277
- m.set_center(lng, lat, 12)
278
- st.session_state["zoom_level"] = 12
279
-
280
- collection = st.selectbox(
281
- "Select a satellite image collection: ",
282
- [
283
- "Any Earth Engine ImageCollection",
284
- "Landsat TM-ETM-OLI Surface Reflectance",
285
- "Sentinel-2 MSI Surface Reflectance",
286
- "Geostationary Operational Environmental Satellites (GOES)",
287
- "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km",
288
- "MODIS Gap filled Land Surface Temperature Daily",
289
- "MODIS Ocean Color SMI",
290
- "USDA National Agriculture Imagery Program (NAIP)",
291
- ],
292
- index=1,
293
- )
294
-
295
- if collection in [
296
- "Landsat TM-ETM-OLI Surface Reflectance",
297
- "Sentinel-2 MSI Surface Reflectance",
298
- ]:
299
- roi_options = ["Uploaded GeoJSON"] + list(landsat_rois.keys())
300
-
301
- elif collection == "Geostationary Operational Environmental Satellites (GOES)":
302
- roi_options = ["Uploaded GeoJSON"] + list(goes_rois.keys())
303
-
304
- elif collection in [
305
- "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km",
306
- "MODIS Gap filled Land Surface Temperature Daily",
307
- ]:
308
- roi_options = ["Uploaded GeoJSON"] + list(modis_rois.keys())
309
- elif collection == "MODIS Ocean Color SMI":
310
- roi_options = ["Uploaded GeoJSON"] + list(ocean_rois.keys())
311
- else:
312
- roi_options = ["Uploaded GeoJSON"]
313
-
314
- if collection == "Any Earth Engine ImageCollection":
315
- keyword = st.text_input("Enter a keyword to search (e.g., MODIS):", "")
316
- if keyword:
317
-
318
- assets = geemap.search_ee_data(keyword)
319
- ee_assets = []
320
- for asset in assets:
321
- if asset["ee_id_snippet"].startswith("ee.ImageCollection"):
322
- ee_assets.append(asset)
323
-
324
- asset_titles = [x["title"] for x in ee_assets]
325
- dataset = st.selectbox("Select a dataset:", asset_titles)
326
- if len(ee_assets) > 0:
327
- st.session_state["ee_assets"] = ee_assets
328
- st.session_state["asset_titles"] = asset_titles
329
- index = asset_titles.index(dataset)
330
- ee_id = ee_assets[index]["id"]
331
- else:
332
- ee_id = ""
333
-
334
- if dataset is not None:
335
- with st.expander("Show dataset details", False):
336
- index = asset_titles.index(dataset)
337
- html = geemap.ee_data_html(st.session_state["ee_assets"][index])
338
- st.markdown(html, True)
339
- # elif collection == "MODIS Gap filled Land Surface Temperature Daily":
340
- # ee_id = ""
341
- else:
342
- ee_id = ""
343
-
344
- asset_id = st.text_input("Enter an ee.ImageCollection asset ID:", ee_id)
345
-
346
- if asset_id:
347
- with st.expander("Customize band combination and color palette", True):
348
- try:
349
- col = ee.ImageCollection.load(asset_id)
350
- st.session_state["ee_asset_id"] = asset_id
351
- except:
352
- st.error("Invalid Earth Engine asset ID.")
353
- st.session_state["ee_asset_id"] = None
354
- return
355
-
356
- img_bands = col.first().bandNames().getInfo()
357
- if len(img_bands) >= 3:
358
- default_bands = img_bands[:3][::-1]
359
- else:
360
- default_bands = img_bands[:]
361
- bands = st.multiselect(
362
- "Select one or three bands (RGB):", img_bands, default_bands
363
- )
364
- st.session_state["bands"] = bands
365
-
366
- if len(bands) == 1:
367
- palette_options = st.selectbox(
368
- "Color palette",
369
- cm.list_colormaps(),
370
- index=2,
371
- )
372
- palette_values = cm.get_palette(palette_options, 15)
373
- palette = st.text_area(
374
- "Enter a custom palette:",
375
- palette_values,
376
- )
377
- st.write(
378
- cm.plot_colormap(cmap=palette_options, return_fig=True)
379
- )
380
- st.session_state["palette"] = json.loads(
381
- palette.replace("'", '"')
382
- )
383
-
384
- if bands:
385
- vis_params = st.text_area(
386
- "Enter visualization parameters",
387
- "{'bands': ["
388
- + ", ".join([f"'{band}'" for band in bands])
389
- + "]}",
390
- )
391
- else:
392
- vis_params = st.text_area(
393
- "Enter visualization parameters",
394
- "{}",
395
- )
396
- try:
397
- st.session_state["vis_params"] = json.loads(
398
- vis_params.replace("'", '"')
399
- )
400
- st.session_state["vis_params"]["palette"] = st.session_state[
401
- "palette"
402
- ]
403
- except Exception as e:
404
- st.session_state["vis_params"] = None
405
- st.error(
406
- f"Invalid visualization parameters. It must be a dictionary."
407
- )
408
-
409
- elif collection == "MODIS Gap filled Land Surface Temperature Daily":
410
- with st.expander("Show dataset details", False):
411
- st.markdown(
412
- """
413
- See the [Awesome GEE Community Datasets](https://samapriya.github.io/awesome-gee-community-datasets/projects/daily_lst/).
414
- """
415
- )
416
-
417
- MODIS_options = ["Daytime (1:30 pm)", "Nighttime (1:30 am)"]
418
- MODIS_option = st.selectbox("Select a MODIS dataset:", MODIS_options)
419
- if MODIS_option == "Daytime (1:30 pm)":
420
- st.session_state["ee_asset_id"] = (
421
- "projects/sat-io/open-datasets/gap-filled-lst/gf_day_1km"
422
- )
423
- else:
424
- st.session_state["ee_asset_id"] = (
425
- "projects/sat-io/open-datasets/gap-filled-lst/gf_night_1km"
426
- )
427
-
428
- palette_options = st.selectbox(
429
- "Color palette",
430
- cm.list_colormaps(),
431
- index=90,
432
- )
433
- palette_values = cm.get_palette(palette_options, 15)
434
- palette = st.text_area(
435
- "Enter a custom palette:",
436
- palette_values,
437
- )
438
- st.write(cm.plot_colormap(cmap=palette_options, return_fig=True))
439
- st.session_state["palette"] = json.loads(palette.replace("'", '"'))
440
- elif collection == "MODIS Ocean Color SMI":
441
- with st.expander("Show dataset details", False):
442
- st.markdown(
443
- """
444
- See the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog/NASA_OCEANDATA_MODIS-Aqua_L3SMI).
445
- """
446
- )
447
-
448
- MODIS_options = ["Aqua", "Terra"]
449
- MODIS_option = st.selectbox("Select a satellite:", MODIS_options)
450
- st.session_state["ee_asset_id"] = MODIS_option
451
- # if MODIS_option == "Daytime (1:30 pm)":
452
- # st.session_state[
453
- # "ee_asset_id"
454
- # ] = "projects/sat-io/open-datasets/gap-filled-lst/gf_day_1km"
455
- # else:
456
- # st.session_state[
457
- # "ee_asset_id"
458
- # ] = "projects/sat-io/open-datasets/gap-filled-lst/gf_night_1km"
459
-
460
- band_dict = {
461
- "Chlorophyll a concentration": "chlor_a",
462
- "Normalized fluorescence line height": "nflh",
463
- "Particulate organic carbon": "poc",
464
- "Sea surface temperature": "sst",
465
- "Remote sensing reflectance at band 412nm": "Rrs_412",
466
- "Remote sensing reflectance at band 443nm": "Rrs_443",
467
- "Remote sensing reflectance at band 469nm": "Rrs_469",
468
- "Remote sensing reflectance at band 488nm": "Rrs_488",
469
- "Remote sensing reflectance at band 531nm": "Rrs_531",
470
- "Remote sensing reflectance at band 547nm": "Rrs_547",
471
- "Remote sensing reflectance at band 555nm": "Rrs_555",
472
- "Remote sensing reflectance at band 645nm": "Rrs_645",
473
- "Remote sensing reflectance at band 667nm": "Rrs_667",
474
- "Remote sensing reflectance at band 678nm": "Rrs_678",
475
- }
476
-
477
- band_options = list(band_dict.keys())
478
- band = st.selectbox(
479
- "Select a band",
480
- band_options,
481
- band_options.index("Sea surface temperature"),
482
- )
483
- st.session_state["band"] = band_dict[band]
484
-
485
- colors = cm.list_colormaps()
486
- palette_options = st.selectbox(
487
- "Color palette",
488
- colors,
489
- index=colors.index("coolwarm"),
490
- )
491
- palette_values = cm.get_palette(palette_options, 15)
492
- palette = st.text_area(
493
- "Enter a custom palette:",
494
- palette_values,
495
- )
496
- st.write(cm.plot_colormap(cmap=palette_options, return_fig=True))
497
- st.session_state["palette"] = json.loads(palette.replace("'", '"'))
498
-
499
- sample_roi = st.selectbox(
500
- "Select a sample ROI or upload a GeoJSON file:",
501
- roi_options,
502
- index=0,
503
- )
504
-
505
- add_outline = st.checkbox(
506
- "Overlay an administrative boundary on timelapse", False
507
- )
508
-
509
- if add_outline:
510
-
511
- with st.expander("Customize administrative boundary", True):
512
-
513
- overlay_options = {
514
- "User-defined": None,
515
- "Continents": "continents",
516
- "Countries": "countries",
517
- "US States": "us_states",
518
- "China": "china",
519
- }
520
-
521
- overlay = st.selectbox(
522
- "Select an administrative boundary:",
523
- list(overlay_options.keys()),
524
- index=2,
525
- )
526
-
527
- overlay_data = overlay_options[overlay]
528
-
529
- if overlay_data is None:
530
- overlay_data = st.text_input(
531
- "Enter an HTTP URL to a GeoJSON file or an ee.FeatureCollection asset id:",
532
- "https://raw.githubusercontent.com/giswqs/geemap/master/examples/data/countries.geojson",
533
- )
534
-
535
- overlay_color = st.color_picker(
536
- "Select a color for the administrative boundary:", "#000000"
537
- )
538
- overlay_width = st.slider(
539
- "Select a line width for the administrative boundary:", 1, 20, 1
540
- )
541
- overlay_opacity = st.slider(
542
- "Select an opacity for the administrative boundary:",
543
- 0.0,
544
- 1.0,
545
- 1.0,
546
- 0.05,
547
- )
548
- else:
549
- overlay_data = None
550
- overlay_color = "black"
551
- overlay_width = 1
552
- overlay_opacity = 1
553
-
554
- with row1_col1:
555
-
556
- with st.expander(
557
- "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 👉"
558
- ):
559
- video_empty = st.empty()
560
-
561
- data = st.file_uploader(
562
- "Upload a GeoJSON file to use as an ROI. Customize timelapse parameters and then click the Submit button 😇👇",
563
- type=["geojson", "kml", "zip"],
564
- )
565
-
566
- crs = "epsg:4326"
567
- if sample_roi == "Uploaded GeoJSON":
568
- if data is None:
569
- # st.info(
570
- # "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"
571
- # )
572
- if collection in [
573
- "Geostationary Operational Environmental Satellites (GOES)",
574
- "USDA National Agriculture Imagery Program (NAIP)",
575
- ] and (not keyword):
576
- m.set_center(-100, 40, 3)
577
- # else:
578
- # m.set_center(4.20, 18.63, zoom=2)
579
- else:
580
- if collection in [
581
- "Landsat TM-ETM-OLI Surface Reflectance",
582
- "Sentinel-2 MSI Surface Reflectance",
583
- ]:
584
- gdf = gpd.GeoDataFrame(
585
- index=[0], crs=crs, geometry=[landsat_rois[sample_roi]]
586
- )
587
- elif (
588
- collection
589
- == "Geostationary Operational Environmental Satellites (GOES)"
590
- ):
591
- gdf = gpd.GeoDataFrame(
592
- index=[0], crs=crs, geometry=[goes_rois[sample_roi]["region"]]
593
- )
594
- elif collection == "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km":
595
- gdf = gpd.GeoDataFrame(
596
- index=[0], crs=crs, geometry=[modis_rois[sample_roi]]
597
- )
598
-
599
- if sample_roi != "Uploaded GeoJSON":
600
-
601
- if collection in [
602
- "Landsat TM-ETM-OLI Surface Reflectance",
603
- "Sentinel-2 MSI Surface Reflectance",
604
- ]:
605
- gdf = gpd.GeoDataFrame(
606
- index=[0], crs=crs, geometry=[landsat_rois[sample_roi]]
607
- )
608
- elif (
609
- collection
610
- == "Geostationary Operational Environmental Satellites (GOES)"
611
- ):
612
- gdf = gpd.GeoDataFrame(
613
- index=[0], crs=crs, geometry=[goes_rois[sample_roi]["region"]]
614
- )
615
- elif collection in [
616
- "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km",
617
- "MODIS Gap filled Land Surface Temperature Daily",
618
- ]:
619
- gdf = gpd.GeoDataFrame(
620
- index=[0], crs=crs, geometry=[modis_rois[sample_roi]]
621
- )
622
- elif collection == "MODIS Ocean Color SMI":
623
- gdf = gpd.GeoDataFrame(
624
- index=[0], crs=crs, geometry=[ocean_rois[sample_roi]]
625
- )
626
- try:
627
- st.session_state["roi"] = geemap.gdf_to_ee(gdf, geodesic=False)
628
- except Exception as e:
629
- st.error(e)
630
- st.error("Please draw another ROI and try again.")
631
- return
632
- m.add_gdf(gdf, "ROI")
633
-
634
- elif data:
635
- gdf = uploaded_file_to_gdf(data)
636
- try:
637
- st.session_state["roi"] = geemap.gdf_to_ee(gdf, geodesic=False)
638
- m.add_gdf(gdf, "ROI")
639
- except Exception as e:
640
- st.error(e)
641
- st.error("Please draw another ROI and try again.")
642
- return
643
-
644
- m.to_streamlit(height=600)
645
-
646
- with row1_col2:
647
-
648
- if collection in [
649
- "Landsat TM-ETM-OLI Surface Reflectance",
650
- "Sentinel-2 MSI Surface Reflectance",
651
- ]:
652
-
653
- if collection == "Landsat TM-ETM-OLI Surface Reflectance":
654
- sensor_start_year = 1984
655
- timelapse_title = "Landsat Timelapse"
656
- timelapse_speed = 5
657
- elif collection == "Sentinel-2 MSI Surface Reflectance":
658
- sensor_start_year = 2015
659
- timelapse_title = "Sentinel-2 Timelapse"
660
- timelapse_speed = 5
661
- video_empty.video("https://youtu.be/VVRK_-dEjR4")
662
-
663
- with st.form("submit_landsat_form"):
664
-
665
- roi = None
666
- if st.session_state.get("roi") is not None:
667
- roi = st.session_state.get("roi")
668
- out_gif = geemap.temp_file_path(".gif")
669
-
670
- title = st.text_input(
671
- "Enter a title to show on the timelapse: ", timelapse_title
672
- )
673
- RGB = st.selectbox(
674
- "Select an RGB band combination:",
675
- [
676
- "Red/Green/Blue",
677
- "NIR/Red/Green",
678
- "SWIR2/SWIR1/NIR",
679
- "NIR/SWIR1/Red",
680
- "SWIR2/NIR/Red",
681
- "SWIR2/SWIR1/Red",
682
- "SWIR1/NIR/Blue",
683
- "NIR/SWIR1/Blue",
684
- "SWIR2/NIR/Green",
685
- "SWIR1/NIR/Red",
686
- "SWIR2/NIR/SWIR1",
687
- "SWIR1/NIR/SWIR2",
688
- ],
689
- index=9,
690
- )
691
-
692
- frequency = st.selectbox(
693
- "Select a temporal frequency:",
694
- ["year", "quarter", "month"],
695
- index=0,
696
- )
697
-
698
- with st.expander("Customize timelapse"):
699
-
700
- speed = st.slider("Frames per second:", 1, 30, timelapse_speed)
701
- dimensions = st.slider(
702
- "Maximum dimensions (Width*Height) in pixels", 768, 2000, 768
703
- )
704
- progress_bar_color = st.color_picker(
705
- "Progress bar color:", "#0000ff"
706
- )
707
- years = st.slider(
708
- "Start and end year:",
709
- sensor_start_year,
710
- today.year,
711
- (sensor_start_year, today.year),
712
- )
713
- months = st.slider("Start and end month:", 1, 12, (1, 12))
714
- font_size = st.slider("Font size:", 10, 50, 30)
715
- font_color = st.color_picker("Font color:", "#ffffff")
716
- apply_fmask = st.checkbox(
717
- "Apply fmask (remove clouds, shadows, snow)", True
718
- )
719
- font_type = st.selectbox(
720
- "Select the font type for the title:",
721
- ["arial.ttf", "alibaba.otf"],
722
- index=0,
723
- )
724
- fading = st.slider(
725
- "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
726
- )
727
- mp4 = st.checkbox("Save timelapse as MP4", True)
728
-
729
- empty_text = st.empty()
730
- empty_image = st.empty()
731
- empty_fire_image = st.empty()
732
- empty_video = st.container()
733
- submitted = st.form_submit_button("Submit")
734
- if submitted:
735
-
736
- if sample_roi == "Uploaded GeoJSON" and data is None:
737
- empty_text.warning(
738
- "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."
739
- )
740
- else:
741
-
742
- empty_text.text("Computing... Please wait...")
743
-
744
- start_year = years[0]
745
- end_year = years[1]
746
- start_date = str(months[0]).zfill(2) + "-01"
747
- end_date = str(months[1]).zfill(2) + "-30"
748
- bands = RGB.split("/")
749
-
750
- try:
751
- if collection == "Landsat TM-ETM-OLI Surface Reflectance":
752
- out_gif = geemap.landsat_timelapse(
753
- roi=roi,
754
- out_gif=out_gif,
755
- start_year=start_year,
756
- end_year=end_year,
757
- start_date=start_date,
758
- end_date=end_date,
759
- bands=bands,
760
- apply_fmask=apply_fmask,
761
- frames_per_second=speed,
762
- # dimensions=dimensions,
763
- dimensions=768,
764
- overlay_data=overlay_data,
765
- overlay_color=overlay_color,
766
- overlay_width=overlay_width,
767
- overlay_opacity=overlay_opacity,
768
- frequency=frequency,
769
- date_format=None,
770
- title=title,
771
- title_xy=("2%", "90%"),
772
- add_text=True,
773
- text_xy=("2%", "2%"),
774
- text_sequence=None,
775
- font_type=font_type,
776
- font_size=font_size,
777
- font_color=font_color,
778
- add_progress_bar=True,
779
- progress_bar_color=progress_bar_color,
780
- progress_bar_height=5,
781
- loop=0,
782
- mp4=mp4,
783
- fading=fading,
784
- )
785
- elif collection == "Sentinel-2 MSI Surface Reflectance":
786
- out_gif = geemap.sentinel2_timelapse(
787
- roi=roi,
788
- out_gif=out_gif,
789
- start_year=start_year,
790
- end_year=end_year,
791
- start_date=start_date,
792
- end_date=end_date,
793
- bands=bands,
794
- apply_fmask=apply_fmask,
795
- frames_per_second=speed,
796
- dimensions=768,
797
- # dimensions=dimensions,
798
- overlay_data=overlay_data,
799
- overlay_color=overlay_color,
800
- overlay_width=overlay_width,
801
- overlay_opacity=overlay_opacity,
802
- frequency=frequency,
803
- date_format=None,
804
- title=title,
805
- title_xy=("2%", "90%"),
806
- add_text=True,
807
- text_xy=("2%", "2%"),
808
- text_sequence=None,
809
- font_type=font_type,
810
- font_size=font_size,
811
- font_color=font_color,
812
- add_progress_bar=True,
813
- progress_bar_color=progress_bar_color,
814
- progress_bar_height=5,
815
- loop=0,
816
- mp4=mp4,
817
- fading=fading,
818
- )
819
- except:
820
- empty_text.error(
821
- "An error occurred while computing the timelapse. Your probably requested too much data. Try reducing the ROI or timespan."
822
- )
823
- st.stop()
824
-
825
- if out_gif is not None and os.path.exists(out_gif):
826
-
827
- empty_text.text(
828
- "Right click the GIF to save it to your computer👇"
829
- )
830
- empty_image.image(out_gif)
831
-
832
- out_mp4 = out_gif.replace(".gif", ".mp4")
833
- if mp4 and os.path.exists(out_mp4):
834
- with empty_video:
835
- st.text(
836
- "Right click the MP4 to save it to your computer👇"
837
- )
838
- st.video(out_gif.replace(".gif", ".mp4"))
839
-
840
- else:
841
- empty_text.error(
842
- "Something went wrong. You probably requested too much data. Try reducing the ROI or timespan."
843
- )
844
-
845
- elif collection == "Geostationary Operational Environmental Satellites (GOES)":
846
-
847
- video_empty.video("https://youtu.be/16fA2QORG4A")
848
-
849
- with st.form("submit_goes_form"):
850
-
851
- roi = None
852
- if st.session_state.get("roi") is not None:
853
- roi = st.session_state.get("roi")
854
- out_gif = geemap.temp_file_path(".gif")
855
-
856
- satellite = st.selectbox("Select a satellite:", ["GOES-17", "GOES-16"])
857
- earliest_date = datetime.date(2017, 7, 10)
858
- latest_date = datetime.date.today()
859
-
860
- if sample_roi == "Uploaded GeoJSON":
861
- roi_start_date = today - datetime.timedelta(days=2)
862
- roi_end_date = today - datetime.timedelta(days=1)
863
- roi_start_time = datetime.time(14, 00)
864
- roi_end_time = datetime.time(1, 00)
865
- else:
866
- roi_start = goes_rois[sample_roi]["start_time"]
867
- roi_end = goes_rois[sample_roi]["end_time"]
868
- roi_start_date = datetime.datetime.strptime(
869
- roi_start[:10], "%Y-%m-%d"
870
- )
871
- roi_end_date = datetime.datetime.strptime(roi_end[:10], "%Y-%m-%d")
872
- roi_start_time = datetime.time(
873
- int(roi_start[11:13]), int(roi_start[14:16])
874
- )
875
- roi_end_time = datetime.time(
876
- int(roi_end[11:13]), int(roi_end[14:16])
877
- )
878
-
879
- start_date = st.date_input("Select the start date:", roi_start_date)
880
- end_date = st.date_input("Select the end date:", roi_end_date)
881
-
882
- with st.expander("Customize timelapse"):
883
-
884
- add_fire = st.checkbox("Add Fire/Hotspot Characterization", False)
885
-
886
- scan_type = st.selectbox(
887
- "Select a scan type:", ["Full Disk", "CONUS", "Mesoscale"]
888
- )
889
-
890
- start_time = st.time_input(
891
- "Select the start time of the start date:", roi_start_time
892
- )
893
-
894
- end_time = st.time_input(
895
- "Select the end time of the end date:", roi_end_time
896
- )
897
-
898
- start = (
899
- start_date.strftime("%Y-%m-%d")
900
- + "T"
901
- + start_time.strftime("%H:%M:%S")
902
- )
903
- end = (
904
- end_date.strftime("%Y-%m-%d")
905
- + "T"
906
- + end_time.strftime("%H:%M:%S")
907
- )
908
-
909
- speed = st.slider("Frames per second:", 1, 30, 5)
910
- add_progress_bar = st.checkbox("Add a progress bar", True)
911
- progress_bar_color = st.color_picker(
912
- "Progress bar color:", "#0000ff"
913
- )
914
- font_size = st.slider("Font size:", 10, 50, 20)
915
- font_color = st.color_picker("Font color:", "#ffffff")
916
- fading = st.slider(
917
- "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
918
- )
919
- mp4 = st.checkbox("Save timelapse as MP4", True)
920
-
921
- empty_text = st.empty()
922
- empty_image = st.empty()
923
- empty_video = st.container()
924
- empty_fire_text = st.empty()
925
- empty_fire_image = st.empty()
926
-
927
- submitted = st.form_submit_button("Submit")
928
- if submitted:
929
- if sample_roi == "Uploaded GeoJSON" and data is None:
930
- empty_text.warning(
931
- "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."
932
- )
933
- else:
934
- empty_text.text("Computing... Please wait...")
935
-
936
- geemap.goes_timelapse(
937
- roi,
938
- out_gif,
939
- start_date=start,
940
- end_date=end,
941
- data=satellite,
942
- scan=scan_type.replace(" ", "_").lower(),
943
- dimensions=768,
944
- framesPerSecond=speed,
945
- date_format="YYYY-MM-dd HH:mm",
946
- xy=("3%", "3%"),
947
- text_sequence=None,
948
- font_type="arial.ttf",
949
- font_size=font_size,
950
- font_color=font_color,
951
- add_progress_bar=add_progress_bar,
952
- progress_bar_color=progress_bar_color,
953
- progress_bar_height=5,
954
- loop=0,
955
- overlay_data=overlay_data,
956
- overlay_color=overlay_color,
957
- overlay_width=overlay_width,
958
- overlay_opacity=overlay_opacity,
959
- mp4=mp4,
960
- fading=fading,
961
- )
962
-
963
- if out_gif is not None and os.path.exists(out_gif):
964
- empty_text.text(
965
- "Right click the GIF to save it to your computer👇"
966
- )
967
- empty_image.image(out_gif)
968
-
969
- out_mp4 = out_gif.replace(".gif", ".mp4")
970
- if mp4 and os.path.exists(out_mp4):
971
- with empty_video:
972
- st.text(
973
- "Right click the MP4 to save it to your computer👇"
974
- )
975
- st.video(out_gif.replace(".gif", ".mp4"))
976
-
977
- if add_fire:
978
- out_fire_gif = geemap.temp_file_path(".gif")
979
- empty_fire_text.text(
980
- "Delineating Fire Hotspot... Please wait..."
981
- )
982
- geemap.goes_fire_timelapse(
983
- out_fire_gif,
984
- start_date=start,
985
- end_date=end,
986
- data=satellite,
987
- scan=scan_type.replace(" ", "_").lower(),
988
- region=roi,
989
- dimensions=768,
990
- framesPerSecond=speed,
991
- date_format="YYYY-MM-dd HH:mm",
992
- xy=("3%", "3%"),
993
- text_sequence=None,
994
- font_type="arial.ttf",
995
- font_size=font_size,
996
- font_color=font_color,
997
- add_progress_bar=add_progress_bar,
998
- progress_bar_color=progress_bar_color,
999
- progress_bar_height=5,
1000
- loop=0,
1001
- )
1002
- if os.path.exists(out_fire_gif):
1003
- empty_fire_image.image(out_fire_gif)
1004
- else:
1005
- empty_text.text(
1006
- "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."
1007
- )
1008
-
1009
- elif collection == "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km":
1010
-
1011
- video_empty.video("https://youtu.be/16fA2QORG4A")
1012
-
1013
- satellite = st.selectbox("Select a satellite:", ["Terra", "Aqua"])
1014
- band = st.selectbox("Select a band:", ["NDVI", "EVI"])
1015
-
1016
- with st.form("submit_modis_form"):
1017
-
1018
- roi = None
1019
- if st.session_state.get("roi") is not None:
1020
- roi = st.session_state.get("roi")
1021
- out_gif = geemap.temp_file_path(".gif")
1022
-
1023
- with st.expander("Customize timelapse"):
1024
-
1025
- start = st.date_input(
1026
- "Select a start date:", datetime.date(2000, 2, 8)
1027
- )
1028
- end = st.date_input("Select an end date:", datetime.date.today())
1029
-
1030
- start_date = start.strftime("%Y-%m-%d")
1031
- end_date = end.strftime("%Y-%m-%d")
1032
-
1033
- speed = st.slider("Frames per second:", 1, 30, 5)
1034
- add_progress_bar = st.checkbox("Add a progress bar", True)
1035
- progress_bar_color = st.color_picker(
1036
- "Progress bar color:", "#0000ff"
1037
- )
1038
- font_size = st.slider("Font size:", 10, 50, 20)
1039
- font_color = st.color_picker("Font color:", "#ffffff")
1040
-
1041
- font_type = st.selectbox(
1042
- "Select the font type for the title:",
1043
- ["arial.ttf", "alibaba.otf"],
1044
- index=0,
1045
- )
1046
- fading = st.slider(
1047
- "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1048
- )
1049
- mp4 = st.checkbox("Save timelapse as MP4", True)
1050
-
1051
- empty_text = st.empty()
1052
- empty_image = st.empty()
1053
- empty_video = st.container()
1054
-
1055
- submitted = st.form_submit_button("Submit")
1056
- if submitted:
1057
- if sample_roi == "Uploaded GeoJSON" and data is None:
1058
- empty_text.warning(
1059
- "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."
1060
- )
1061
- else:
1062
-
1063
- empty_text.text("Computing... Please wait...")
1064
-
1065
- geemap.modis_ndvi_timelapse(
1066
- roi,
1067
- out_gif,
1068
- satellite,
1069
- band,
1070
- start_date,
1071
- end_date,
1072
- 768,
1073
- speed,
1074
- overlay_data=overlay_data,
1075
- overlay_color=overlay_color,
1076
- overlay_width=overlay_width,
1077
- overlay_opacity=overlay_opacity,
1078
- mp4=mp4,
1079
- fading=fading,
1080
- )
1081
-
1082
- geemap.reduce_gif_size(out_gif)
1083
-
1084
- empty_text.text(
1085
- "Right click the GIF to save it to your computer👇"
1086
- )
1087
- empty_image.image(out_gif)
1088
-
1089
- out_mp4 = out_gif.replace(".gif", ".mp4")
1090
- if mp4 and os.path.exists(out_mp4):
1091
- with empty_video:
1092
- st.text(
1093
- "Right click the MP4 to save it to your computer👇"
1094
- )
1095
- st.video(out_gif.replace(".gif", ".mp4"))
1096
-
1097
- elif collection == "Any Earth Engine ImageCollection":
1098
-
1099
- with st.form("submit_ts_form"):
1100
- with st.expander("Customize timelapse"):
1101
-
1102
- title = st.text_input(
1103
- "Enter a title to show on the timelapse: ", "Timelapse"
1104
- )
1105
- start_date = st.date_input(
1106
- "Select the start date:", datetime.date(2020, 1, 1)
1107
- )
1108
- end_date = st.date_input(
1109
- "Select the end date:", datetime.date.today()
1110
- )
1111
- frequency = st.selectbox(
1112
- "Select a temporal frequency:",
1113
- ["year", "quarter", "month", "day", "hour", "minute", "second"],
1114
- index=0,
1115
- )
1116
- reducer = st.selectbox(
1117
- "Select a reducer for aggregating data:",
1118
- ["median", "mean", "min", "max", "sum", "variance", "stdDev"],
1119
- index=0,
1120
- )
1121
- data_format = st.selectbox(
1122
- "Select a date format to show on the timelapse:",
1123
- [
1124
- "YYYY-MM-dd",
1125
- "YYYY",
1126
- "YYMM-MM",
1127
- "YYYY-MM-dd HH:mm",
1128
- "YYYY-MM-dd HH:mm:ss",
1129
- "HH:mm",
1130
- "HH:mm:ss",
1131
- "w",
1132
- "M",
1133
- "d",
1134
- "D",
1135
- ],
1136
- index=0,
1137
- )
1138
-
1139
- speed = st.slider("Frames per second:", 1, 30, 5)
1140
- add_progress_bar = st.checkbox("Add a progress bar", True)
1141
- progress_bar_color = st.color_picker(
1142
- "Progress bar color:", "#0000ff"
1143
- )
1144
- font_size = st.slider("Font size:", 10, 50, 30)
1145
- font_color = st.color_picker("Font color:", "#ffffff")
1146
- font_type = st.selectbox(
1147
- "Select the font type for the title:",
1148
- ["arial.ttf", "alibaba.otf"],
1149
- index=0,
1150
- )
1151
- fading = st.slider(
1152
- "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1153
- )
1154
- mp4 = st.checkbox("Save timelapse as MP4", True)
1155
-
1156
- empty_text = st.empty()
1157
- empty_image = st.empty()
1158
- empty_video = st.container()
1159
- empty_fire_image = st.empty()
1160
-
1161
- roi = None
1162
- if st.session_state.get("roi") is not None:
1163
- roi = st.session_state.get("roi")
1164
- out_gif = geemap.temp_file_path(".gif")
1165
-
1166
- submitted = st.form_submit_button("Submit")
1167
- if submitted:
1168
-
1169
- if sample_roi == "Uploaded GeoJSON" and data is None:
1170
- empty_text.warning(
1171
- "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."
1172
- )
1173
- else:
1174
-
1175
- empty_text.text("Computing... Please wait...")
1176
- try:
1177
- geemap.create_timelapse(
1178
- st.session_state.get("ee_asset_id"),
1179
- start_date=start_date.strftime("%Y-%m-%d"),
1180
- end_date=end_date.strftime("%Y-%m-%d"),
1181
- region=roi,
1182
- frequency=frequency,
1183
- reducer=reducer,
1184
- date_format=data_format,
1185
- out_gif=out_gif,
1186
- bands=st.session_state.get("bands"),
1187
- palette=st.session_state.get("palette"),
1188
- vis_params=st.session_state.get("vis_params"),
1189
- dimensions=768,
1190
- frames_per_second=speed,
1191
- crs="EPSG:3857",
1192
- overlay_data=overlay_data,
1193
- overlay_color=overlay_color,
1194
- overlay_width=overlay_width,
1195
- overlay_opacity=overlay_opacity,
1196
- title=title,
1197
- title_xy=("2%", "90%"),
1198
- add_text=True,
1199
- text_xy=("2%", "2%"),
1200
- text_sequence=None,
1201
- font_type=font_type,
1202
- font_size=font_size,
1203
- font_color=font_color,
1204
- add_progress_bar=add_progress_bar,
1205
- progress_bar_color=progress_bar_color,
1206
- progress_bar_height=5,
1207
- loop=0,
1208
- mp4=mp4,
1209
- fading=fading,
1210
- )
1211
- except:
1212
- empty_text.error(
1213
- "An error occurred while computing the timelapse. You probably requested too much data. Try reducing the ROI or timespan."
1214
- )
1215
-
1216
- empty_text.text(
1217
- "Right click the GIF to save it to your computer👇"
1218
- )
1219
- empty_image.image(out_gif)
1220
-
1221
- out_mp4 = out_gif.replace(".gif", ".mp4")
1222
- if mp4 and os.path.exists(out_mp4):
1223
- with empty_video:
1224
- st.text(
1225
- "Right click the MP4 to save it to your computer👇"
1226
- )
1227
- st.video(out_gif.replace(".gif", ".mp4"))
1228
-
1229
- elif collection in [
1230
- "MODIS Gap filled Land Surface Temperature Daily",
1231
- "MODIS Ocean Color SMI",
1232
- ]:
1233
-
1234
- with st.form("submit_ts_form"):
1235
- with st.expander("Customize timelapse"):
1236
-
1237
- title = st.text_input(
1238
- "Enter a title to show on the timelapse: ",
1239
- "Surface Temperature",
1240
- )
1241
- start_date = st.date_input(
1242
- "Select the start date:", datetime.date(2018, 1, 1)
1243
- )
1244
- end_date = st.date_input(
1245
- "Select the end date:", datetime.date(2020, 12, 31)
1246
- )
1247
- frequency = st.selectbox(
1248
- "Select a temporal frequency:",
1249
- ["year", "quarter", "month", "week", "day"],
1250
- index=2,
1251
- )
1252
- reducer = st.selectbox(
1253
- "Select a reducer for aggregating data:",
1254
- ["median", "mean", "min", "max", "sum", "variance", "stdDev"],
1255
- index=0,
1256
- )
1257
-
1258
- vis_params = st.text_area(
1259
- "Enter visualization parameters",
1260
- "",
1261
- help="Enter a string in the format of a dictionary, such as '{'min': 23, 'max': 32}'",
1262
- )
1263
-
1264
- speed = st.slider("Frames per second:", 1, 30, 5)
1265
- add_progress_bar = st.checkbox("Add a progress bar", True)
1266
- progress_bar_color = st.color_picker(
1267
- "Progress bar color:", "#0000ff"
1268
- )
1269
- font_size = st.slider("Font size:", 10, 50, 30)
1270
- font_color = st.color_picker("Font color:", "#ffffff")
1271
- font_type = st.selectbox(
1272
- "Select the font type for the title:",
1273
- ["arial.ttf", "alibaba.otf"],
1274
- index=0,
1275
- )
1276
- add_colorbar = st.checkbox("Add a colorbar", True)
1277
- colorbar_label = st.text_input(
1278
- "Enter the colorbar label:", "Surface Temperature (°C)"
1279
- )
1280
- fading = st.slider(
1281
- "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1282
- )
1283
- mp4 = st.checkbox("Save timelapse as MP4", True)
1284
-
1285
- empty_text = st.empty()
1286
- empty_image = st.empty()
1287
- empty_video = st.container()
1288
-
1289
- roi = None
1290
- if st.session_state.get("roi") is not None:
1291
- roi = st.session_state.get("roi")
1292
- out_gif = geemap.temp_file_path(".gif")
1293
-
1294
- submitted = st.form_submit_button("Submit")
1295
- if submitted:
1296
-
1297
- if sample_roi == "Uploaded GeoJSON" and data is None:
1298
- empty_text.warning(
1299
- "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."
1300
- )
1301
- else:
1302
-
1303
- empty_text.text("Computing... Please wait...")
1304
- try:
1305
- if (
1306
- collection
1307
- == "MODIS Gap filled Land Surface Temperature Daily"
1308
- ):
1309
- out_gif = geemap.create_timelapse(
1310
- st.session_state.get("ee_asset_id"),
1311
- start_date=start_date.strftime("%Y-%m-%d"),
1312
- end_date=end_date.strftime("%Y-%m-%d"),
1313
- region=roi,
1314
- bands=None,
1315
- frequency=frequency,
1316
- reducer=reducer,
1317
- date_format=None,
1318
- out_gif=out_gif,
1319
- palette=st.session_state.get("palette"),
1320
- vis_params=None,
1321
- dimensions=768,
1322
- frames_per_second=speed,
1323
- crs="EPSG:3857",
1324
- overlay_data=overlay_data,
1325
- overlay_color=overlay_color,
1326
- overlay_width=overlay_width,
1327
- overlay_opacity=overlay_opacity,
1328
- title=title,
1329
- title_xy=("2%", "90%"),
1330
- add_text=True,
1331
- text_xy=("2%", "2%"),
1332
- text_sequence=None,
1333
- font_type=font_type,
1334
- font_size=font_size,
1335
- font_color=font_color,
1336
- add_progress_bar=add_progress_bar,
1337
- progress_bar_color=progress_bar_color,
1338
- progress_bar_height=5,
1339
- add_colorbar=add_colorbar,
1340
- colorbar_label=colorbar_label,
1341
- loop=0,
1342
- mp4=mp4,
1343
- fading=fading,
1344
- )
1345
- elif collection == "MODIS Ocean Color SMI":
1346
- if vis_params.startswith("{") and vis_params.endswith(
1347
- "}"
1348
- ):
1349
- vis_params = json.loads(
1350
- vis_params.replace("'", '"')
1351
- )
1352
- else:
1353
- vis_params = None
1354
- out_gif = geemap.modis_ocean_color_timelapse(
1355
- st.session_state.get("ee_asset_id"),
1356
- start_date=start_date.strftime("%Y-%m-%d"),
1357
- end_date=end_date.strftime("%Y-%m-%d"),
1358
- region=roi,
1359
- bands=st.session_state["band"],
1360
- frequency=frequency,
1361
- reducer=reducer,
1362
- date_format=None,
1363
- out_gif=out_gif,
1364
- palette=st.session_state.get("palette"),
1365
- vis_params=vis_params,
1366
- dimensions=768,
1367
- frames_per_second=speed,
1368
- crs="EPSG:3857",
1369
- overlay_data=overlay_data,
1370
- overlay_color=overlay_color,
1371
- overlay_width=overlay_width,
1372
- overlay_opacity=overlay_opacity,
1373
- title=title,
1374
- title_xy=("2%", "90%"),
1375
- add_text=True,
1376
- text_xy=("2%", "2%"),
1377
- text_sequence=None,
1378
- font_type=font_type,
1379
- font_size=font_size,
1380
- font_color=font_color,
1381
- add_progress_bar=add_progress_bar,
1382
- progress_bar_color=progress_bar_color,
1383
- progress_bar_height=5,
1384
- add_colorbar=add_colorbar,
1385
- colorbar_label=colorbar_label,
1386
- loop=0,
1387
- mp4=mp4,
1388
- fading=fading,
1389
- )
1390
- except:
1391
- empty_text.error(
1392
- "Something went wrong. You probably requested too much data. Try reducing the ROI or timespan."
1393
- )
1394
-
1395
- if out_gif is not None and os.path.exists(out_gif):
1396
-
1397
- geemap.reduce_gif_size(out_gif)
1398
-
1399
- empty_text.text(
1400
- "Right click the GIF to save it to your computer👇"
1401
- )
1402
- empty_image.image(out_gif)
1403
-
1404
- out_mp4 = out_gif.replace(".gif", ".mp4")
1405
- if mp4 and os.path.exists(out_mp4):
1406
- with empty_video:
1407
- st.text(
1408
- "Right click the MP4 to save it to your computer👇"
1409
- )
1410
- st.video(out_gif.replace(".gif", ".mp4"))
1411
-
1412
- else:
1413
- st.error(
1414
- "Something went wrong. You probably requested too much data. Try reducing the ROI or timespan."
1415
- )
1416
-
1417
- elif collection == "USDA National Agriculture Imagery Program (NAIP)":
1418
-
1419
- with st.form("submit_naip_form"):
1420
- with st.expander("Customize timelapse"):
1421
-
1422
- title = st.text_input(
1423
- "Enter a title to show on the timelapse: ", "NAIP Timelapse"
1424
- )
1425
-
1426
- years = st.slider(
1427
- "Start and end year:",
1428
- 2003,
1429
- today.year,
1430
- (2003, today.year),
1431
- )
1432
-
1433
- bands = st.selectbox(
1434
- "Select a band combination:", ["N/R/G", "R/G/B"], index=0
1435
- )
1436
-
1437
- speed = st.slider("Frames per second:", 1, 30, 3)
1438
- add_progress_bar = st.checkbox("Add a progress bar", True)
1439
- progress_bar_color = st.color_picker(
1440
- "Progress bar color:", "#0000ff"
1441
- )
1442
- font_size = st.slider("Font size:", 10, 50, 30)
1443
- font_color = st.color_picker("Font color:", "#ffffff")
1444
- font_type = st.selectbox(
1445
- "Select the font type for the title:",
1446
- ["arial.ttf", "alibaba.otf"],
1447
- index=0,
1448
- )
1449
- fading = st.slider(
1450
- "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1451
- )
1452
- mp4 = st.checkbox("Save timelapse as MP4", True)
1453
-
1454
- empty_text = st.empty()
1455
- empty_image = st.empty()
1456
- empty_video = st.container()
1457
- empty_fire_image = st.empty()
1458
-
1459
- roi = None
1460
- if st.session_state.get("roi") is not None:
1461
- roi = st.session_state.get("roi")
1462
- out_gif = geemap.temp_file_path(".gif")
1463
-
1464
- submitted = st.form_submit_button("Submit")
1465
- if submitted:
1466
-
1467
- if sample_roi == "Uploaded GeoJSON" and data is None:
1468
- empty_text.warning(
1469
- "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."
1470
- )
1471
- else:
1472
-
1473
- empty_text.text("Computing... Please wait...")
1474
- try:
1475
- geemap.naip_timelapse(
1476
- roi,
1477
- years[0],
1478
- years[1],
1479
- out_gif,
1480
- bands=bands.split("/"),
1481
- palette=st.session_state.get("palette"),
1482
- vis_params=None,
1483
- dimensions=768,
1484
- frames_per_second=speed,
1485
- crs="EPSG:3857",
1486
- overlay_data=overlay_data,
1487
- overlay_color=overlay_color,
1488
- overlay_width=overlay_width,
1489
- overlay_opacity=overlay_opacity,
1490
- title=title,
1491
- title_xy=("2%", "90%"),
1492
- add_text=True,
1493
- text_xy=("2%", "2%"),
1494
- text_sequence=None,
1495
- font_type=font_type,
1496
- font_size=font_size,
1497
- font_color=font_color,
1498
- add_progress_bar=add_progress_bar,
1499
- progress_bar_color=progress_bar_color,
1500
- progress_bar_height=5,
1501
- loop=0,
1502
- mp4=mp4,
1503
- fading=fading,
1504
- )
1505
- except:
1506
- empty_text.error(
1507
- "Something went wrong. You either requested too much data or the ROI is outside the U.S."
1508
- )
1509
-
1510
- if out_gif is not None and os.path.exists(out_gif):
1511
-
1512
- empty_text.text(
1513
- "Right click the GIF to save it to your computer👇"
1514
- )
1515
- empty_image.image(out_gif)
1516
-
1517
- out_mp4 = out_gif.replace(".gif", ".mp4")
1518
- if mp4 and os.path.exists(out_mp4):
1519
- with empty_video:
1520
- st.text(
1521
- "Right click the MP4 to save it to your computer👇"
1522
- )
1523
- st.video(out_gif.replace(".gif", ".mp4"))
1524
-
1525
- else:
1526
- st.error(
1527
- "Something went wrong. You either requested too much data or the ROI is outside the U.S."
1528
- )
1529
 
 
 
1530
 
1531
- try:
1532
- app()
1533
- except Exception as e:
1534
- pass
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
+ import ee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
+ # Authenticate and initialize Earth Engine
5
+ ee.Initialize()
6
 
7
+ # Your Streamlit app code here
8
+ st.title("Google Earth Engine in Hugging Face Space")