aassiiyAA123 commited on
Commit
9058afc
·
verified ·
1 Parent(s): 116c1ee

Upload 17 files

Browse files
Files changed (17) hide show
  1. .DS_Store +0 -0
  2. .gitignore +129 -0
  3. Home.py +1874 -0
  4. Interactive_Map.py +224 -0
  5. LICENSE +21 -0
  6. Timelapse.py +1539 -0
  7. custom.js +22 -0
  8. db.sqlite3 +0 -0
  9. index.html +29 -0
  10. jaw.py +20 -0
  11. manage.py +59 -0
  12. ndvi_map.html +72 -0
  13. requirements.txt +14 -0
  14. satellite_image.png +0 -0
  15. style.css +26 -0
  16. test.py +242 -0
  17. test1.py +4 -0
.DS_Store ADDED
Binary file (8.2 kB). View file
 
.gitignore ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ pip-wheel-metadata/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *.cover
50
+ *.py,cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ target/
76
+
77
+ # Jupyter Notebook
78
+ .ipynb_checkpoints
79
+
80
+ # IPython
81
+ profile_default/
82
+ ipython_config.py
83
+
84
+ # pyenv
85
+ .python-version
86
+
87
+ # pipenv
88
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
90
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
91
+ # install all needed dependencies.
92
+ #Pipfile.lock
93
+
94
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95
+ __pypackages__/
96
+
97
+ # Celery stuff
98
+ celerybeat-schedule
99
+ celerybeat.pid
100
+
101
+ # SageMath parsed files
102
+ *.sage.py
103
+
104
+ # Environments
105
+ .env
106
+ .venv
107
+ env/
108
+ venv/
109
+ ENV/
110
+ env.bak/
111
+ venv.bak/
112
+
113
+ # Spyder project settings
114
+ .spyderproject
115
+ .spyproject
116
+
117
+ # Rope project settings
118
+ .ropeproject
119
+
120
+ # mkdocs documentation
121
+ /site
122
+
123
+ # mypy
124
+ .mypy_cache/
125
+ .dmypy.json
126
+ dmypy.json
127
+
128
+ # Pyre type checker
129
+ .pyre/
Home.py ADDED
@@ -0,0 +1,1874 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import folium
3
+ import geopandas as gpd
4
+ import json
5
+ import geemap.foliumap as geemap
6
+ import ee
7
+ import pandas as pd
8
+ import os
9
+ from google.auth.transport.requests import Request
10
+ import google.auth.exceptions
11
+ from streamlit.components.v1 import html
12
+ import ee
13
+ import json
14
+ import os
15
+ import datetime
16
+ import fiona
17
+ import geopandas as gpd
18
+ import folium
19
+ import streamlit as st
20
+ import geemap.colormaps as cm
21
+ import geemap.foliumap as geemap
22
+ from datetime import date
23
+ from shapely.geometry import Polygon
24
+ import leafmap.foliumap as leafmap
25
+
26
+
27
+
28
+ # Define the pages
29
+ def page_home():
30
+ st.title("Home Page")
31
+ st.write("Welcome to the Home Page!")
32
+
33
+ def page_about():
34
+ st.title("About Page")
35
+ st.write("The main purpose is to provide navigation to other pages/maps.")
36
+
37
+
38
+
39
+ # Path to your shapefiles and service account key
40
+ SHAPEFILE_DIR = 'C:/Users/piv/Desktop/y/media/shp'
41
+
42
+
43
+ #<-------------------------------------------------------------------- Google earth engine Authentication code-------------------------------------------------------------------------------->
44
+
45
+ def initialize_gee():
46
+ service = os.getenv('SA')
47
+ file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'gee', 'ee-muzzamil1-37ebc3dece52.json')
48
+ credentials = ee.ServiceAccountCredentials(service, file)
49
+ try:
50
+ ee.Initialize(credentials)
51
+ st.success("Google Earth Engine initialized successfully.")
52
+ except google.auth.exceptions.RefreshError:
53
+ try:
54
+ request = Request()
55
+ credentials.refresh(request)
56
+ ee.Initialize(credentials)
57
+ st.success("Google Earth Engine token refreshed and initialized successfully.")
58
+ except Exception as e:
59
+ st.error(f"Error refreshing Google Earth Engine token: {e}")
60
+ except Exception as e:
61
+ st.error(f"Error initializing Google Earth Engine: {e}")
62
+
63
+ #<---------------------------------------------------------------Interactive map code used to callin home page (Navigation purpose)---------------------------------------------------------------------------------->
64
+
65
+
66
+ def interactive_map_page():
67
+ st.title("Interactive Map")
68
+ submit_control()
69
+
70
+ #<------------------------------------------------------- Interactive map code------------------------------------------------------------------------------------------------------------------->
71
+
72
+
73
+
74
+ # Create two columns: one for the map and one for the controls
75
+ map_col, control_col = st.columns([3, 1]) # Adjust column width ratios as needed
76
+
77
+ # Map column
78
+ with map_col:
79
+ if 'submitted' in st.session_state and st.session_state.submitted:
80
+ st.markdown("### Satellite Data Map")
81
+ st.components.v1.html(st.session_state.folium_map_html, height=600)
82
+
83
+ # Control column
84
+ with control_col:
85
+ st.header("Map Controls")
86
+ selected_dataset = st.selectbox(
87
+ "Select Dataset",
88
+ ["Modis", "dataset_nighttime", 'precipitation', 'GlobalSurfaceWater', 'WorldPop', 'COPERNICUS']
89
+ )
90
+
91
+ selected_date_range_From = st.date_input("From", value=pd.to_datetime("2015-07-01"))
92
+ selected_date_range_To = st.date_input("To", value=pd.to_datetime("2023-09-30"))
93
+
94
+ shape_options = [
95
+ 'District_Boundary', 'hydro_basins', 'karachi',
96
+ 'National_Constituency_with_Projected_2010_Population',
97
+ 'Provincial_Boundary', 'Provincial_Constituency',
98
+ 'Tehsil_Boundary', 'Union_Council'
99
+ ]
100
+
101
+ selected_shape = st.selectbox("Select Shape", shape_options)
102
+
103
+ if st.button("Submit"):
104
+ handle_submit(
105
+ selected_dataset,
106
+ selected_date_range_From,
107
+ selected_date_range_To,
108
+ selected_shape
109
+ )
110
+
111
+
112
+ def create_folium_map(selected_dataset, ee_object, start_date_str, end_date_str):
113
+ folium_map = folium.Map(location=[25.5973518, 65.54495724], zoom_start=7)
114
+
115
+ try:
116
+ if selected_dataset == "Modis":
117
+ dataset = ee.ImageCollection('MODIS/006/MOD13Q1') \
118
+ .filter(ee.Filter.date(start_date_str, end_date_str)) \
119
+ .filterBounds(ee_object)
120
+
121
+ def clip_image(img):
122
+ return img.clip(ee_object).select('NDVI')
123
+
124
+ clipped_collection = dataset.map(clip_image)
125
+ modis_ndvi = clipped_collection.mean()
126
+ vis_params_ndvi = {
127
+ 'min': 0,
128
+ 'max': 9000,
129
+ 'palette': ['FE8374', 'C0E5DE', '3A837C', '034B48']
130
+ }
131
+ modis_ndvi_map_id = modis_ndvi.getMapId(vis_params_ndvi)
132
+ folium.TileLayer(
133
+ tiles=modis_ndvi_map_id['tile_fetcher'].url_format,
134
+ attr='Google Earth Engine',
135
+ name='NDVI',
136
+ overlay=True,
137
+ control=True
138
+ ).add_to(folium_map)
139
+
140
+ elif selected_dataset == "dataset_nighttime":
141
+ dataset_nighttime = ee.ImageCollection('NOAA/VIIRS/DNB/MONTHLY_V1/VCMCFG') \
142
+ .filter(ee.Filter.date(start_date_str, end_date_str))
143
+
144
+ nighttime = dataset_nighttime.select('avg_rad').mosaic()
145
+ nighttime_clipped = nighttime.clip(ee_object)
146
+ nighttime_vis = {
147
+ 'min': 0.0,
148
+ 'max': 60.0,
149
+ 'palette': ['1a3678', '2955bc', '5699ff', '8dbae9', 'acd1ff', 'caebff', 'e5f9ff', 'fdffb4', 'ffe6a2', 'ffc969', 'ffa12d', 'ff7c1f', 'ca531a', 'ff0000', 'ab0000']
150
+ }
151
+ nighttime_map_id = nighttime_clipped.getMapId(nighttime_vis)
152
+ folium.TileLayer(
153
+ tiles=nighttime_map_id['tile_fetcher'].url_format,
154
+ attr='Google Earth Engine',
155
+ name='Nighttime Lights',
156
+ overlay=True,
157
+ control=True
158
+ ).add_to(folium_map)
159
+
160
+ elif selected_dataset == "precipitation":
161
+ dataset_precipitation = ee.ImageCollection('UCSB-CHG/CHIRPS/DAILY') \
162
+ .filter(ee.Filter.date(start_date_str, end_date_str))
163
+
164
+ precipitation = dataset_precipitation.mosaic().clip(ee_object)
165
+ precip_vis = {
166
+ 'min': 0,
167
+ 'max': 300,
168
+ 'palette': ['blue', 'cyan', 'lime', 'yellow', 'red']
169
+ }
170
+ precip_map_id = precipitation.getMapId(precip_vis)
171
+ folium.TileLayer(
172
+ tiles=precip_map_id['tile_fetcher'].url_format,
173
+ attr='Google Earth Engine',
174
+ name='Precipitation',
175
+ overlay=True,
176
+ control=True
177
+ ).add_to(folium_map)
178
+
179
+ elif selected_dataset == "GlobalSurfaceWater":
180
+ st.warning("GlobalSurfaceWater dataset is not configured.")
181
+
182
+ elif selected_dataset == "WorldPop":
183
+ dataset = ee.ImageCollection('WorldPop/GP/100m/pop') \
184
+ .filterBounds(ee_object) \
185
+ .filter(ee.Filter.date(start_date_str, end_date_str))
186
+
187
+ population = dataset.mean().clip(ee_object)
188
+ pop_vis = {
189
+ 'min': 0,
190
+ 'max': 1000,
191
+ 'palette': ['blue', 'green', 'yellow', 'red']
192
+ }
193
+ pop_map_id = population.getMapId(pop_vis)
194
+ folium.TileLayer(
195
+ tiles=pop_map_id['tile_fetcher'].url_format,
196
+ attr='Google Earth Engine',
197
+ name='World Population',
198
+ overlay=True,
199
+ control=True
200
+ ).add_to(folium_map)
201
+
202
+ elif selected_dataset == "COPERNICUS":
203
+ dataset = ee.ImageCollection('COPERNICUS/S2') \
204
+ .filterBounds(ee_object) \
205
+ .filter(ee.Filter.date(start_date_str, end_date_str))
206
+
207
+ sentinel = dataset.median().clip(ee_object)
208
+ vis_params = {
209
+ 'bands': ['B4', 'B3', 'B2'],
210
+ 'min': 0,
211
+ 'max': 3000,
212
+ 'gamma': 1.4
213
+ }
214
+ copernicus_map_id = sentinel.getMapId(vis_params)
215
+ folium.TileLayer(
216
+ tiles=copernicus_map_id['tile_fetcher'].url_format,
217
+ attr='Google Earth Engine',
218
+ name='Copernicus Sentinel-2',
219
+ overlay=True,
220
+ control=True
221
+ ).add_to(folium_map)
222
+
223
+ folium_map.add_child(folium.LayerControl())
224
+ except Exception as e:
225
+ st.error(f"Error processing dataset: {e}")
226
+
227
+ folium_map_html = folium_map._repr_html_()
228
+ return folium_map_html
229
+
230
+ def handle_submit(selected_dataset, selected_date_range_From, selected_date_range_To, selected_shape):
231
+ shapefile_name = f'{selected_shape}.shp'
232
+ shapefile_path = os.path.join(SHAPEFILE_DIR, shapefile_name)
233
+
234
+ if os.path.exists(shapefile_path):
235
+ try:
236
+ roi_gdf = gpd.read_file(shapefile_path)
237
+ roi_geojson = roi_gdf.to_crs("EPSG:4326").to_json()
238
+ except Exception as e:
239
+ st.error(f"Error reading shapefile: {e}")
240
+ return
241
+
242
+ try:
243
+ ee_object = geemap.geojson_to_ee(json.loads(roi_geojson))
244
+ except Exception as e:
245
+ st.error(f"Error converting GeoJSON to Earth Engine object: {e}")
246
+ return
247
+
248
+ st.markdown("### Satellite Data Map")
249
+ folium_map_html = create_folium_map(
250
+ selected_dataset,
251
+ ee_object,
252
+ selected_date_range_From.strftime('%Y-%m-%d'),
253
+ selected_date_range_To.strftime('%Y-%m-%d')
254
+ )
255
+ html(folium_map_html, height=600)
256
+ else:
257
+ st.error("Selected shapefile does not exist.")
258
+
259
+ def submit_control():
260
+ selected_dataset = st.sidebar.selectbox(
261
+ "Select Dataset",
262
+ ["Modis", "dataset_nighttime", 'precipitation', 'GlobalSurfaceWater', 'WorldPop', 'COPERNICUS']
263
+ )
264
+
265
+ selected_date_range_From = st.sidebar.date_input("From", value=pd.to_datetime("2015-07-01"))
266
+ selected_date_range_To = st.sidebar.date_input("To", value=pd.to_datetime("2023-09-30"))
267
+
268
+ shape_options = [
269
+ 'District_Boundary', 'hydro_basins', 'karachi',
270
+ 'National_Constituency_with_Projected_2010_Population',
271
+ 'Provincial_Boundary', 'Provincial_Constituency',
272
+ 'Tehsil_Boundary', 'Union_Council'
273
+ ]
274
+
275
+ selected_shape = st.sidebar.selectbox("Select Shape", shape_options)
276
+
277
+ if st.sidebar.button("Submit"):
278
+ st.session_state.selected_dataset = selected_dataset
279
+ st.session_state.selected_date_range_From = selected_date_range_From
280
+ st.session_state.selected_date_range_To = selected_date_range_To
281
+ st.session_state.selected_shape = selected_shape
282
+ st.session_state.submitted = True
283
+ else:
284
+ st.session_state.submitted = False
285
+
286
+ if 'submitted' in st.session_state and st.session_state.submitted:
287
+ handle_submit(
288
+ st.session_state.selected_dataset,
289
+ st.session_state.selected_date_range_From,
290
+ st.session_state.selected_date_range_To,
291
+ st.session_state.selected_shape
292
+ )
293
+
294
+ def main():
295
+ st.set_page_config(layout="wide")
296
+ st.title("Satellite Data Visualization")
297
+
298
+ initialize_gee()
299
+
300
+
301
+ if __name__ == "__main__":
302
+ main()
303
+
304
+ #<---------------------------------------------------------------------timelapse pagefunction which is calling it in home (Navigation Purpose)----------------------------------------------------------------------------------------------------->
305
+
306
+ def Timelapse_page():
307
+ try:
308
+ app()
309
+ except Exception as e:
310
+ pass
311
+
312
+ #<------------------------------------------------------------------- timelapse code--------------------------------------------------------------------------------------------------------->
313
+ #create timelapse
314
+
315
+ @st.cache_data
316
+ def ee_authenticate(token_name="EARTHENGINE_TOKEN"):
317
+ geemap.ee_initialize(token_name=token_name)
318
+
319
+
320
+ goes_rois = {
321
+ "Creek Fire, CA (2020-09-05)": {
322
+ "region": Polygon(
323
+ [
324
+ [-121.003418, 36.848857],
325
+ [-121.003418, 39.049052],
326
+ [-117.905273, 39.049052],
327
+ [-117.905273, 36.848857],
328
+ [-121.003418, 36.848857],
329
+ ]
330
+ ),
331
+ "start_time": "2020-09-05T15:00:00",
332
+ "end_time": "2020-09-06T02:00:00",
333
+ },
334
+ "Bomb Cyclone (2021-10-24)": {
335
+ "region": Polygon(
336
+ [
337
+ [-159.5954, 60.4088],
338
+ [-159.5954, 24.5178],
339
+ [-114.2438, 24.5178],
340
+ [-114.2438, 60.4088],
341
+ ]
342
+ ),
343
+ "start_time": "2021-10-24T14:00:00",
344
+ "end_time": "2021-10-25T01:00:00",
345
+ },
346
+ "Hunga Tonga Volcanic Eruption (2022-01-15)": {
347
+ "region": Polygon(
348
+ [
349
+ [-192.480469, -32.546813],
350
+ [-192.480469, -8.754795],
351
+ [-157.587891, -8.754795],
352
+ [-157.587891, -32.546813],
353
+ [-192.480469, -32.546813],
354
+ ]
355
+ ),
356
+ "start_time": "2022-01-15T03:00:00",
357
+ "end_time": "2022-01-15T07:00:00",
358
+ },
359
+ "Hunga Tonga Volcanic Eruption Closer Look (2022-01-15)": {
360
+ "region": Polygon(
361
+ [
362
+ [-178.901367, -22.958393],
363
+ [-178.901367, -17.85329],
364
+ [-171.452637, -17.85329],
365
+ [-171.452637, -22.958393],
366
+ [-178.901367, -22.958393],
367
+ ]
368
+ ),
369
+ "start_time": "2022-01-15T03:00:00",
370
+ "end_time": "2022-01-15T07:00:00",
371
+ },
372
+ }
373
+
374
+
375
+ landsat_rois = {
376
+ "Aral Sea": Polygon(
377
+ [
378
+ [57.667236, 43.834527],
379
+ [57.667236, 45.996962],
380
+ [61.12793, 45.996962],
381
+ [61.12793, 43.834527],
382
+ [57.667236, 43.834527],
383
+ ]
384
+ ),
385
+ "Dubai": Polygon(
386
+ [
387
+ [54.541626, 24.763044],
388
+ [54.541626, 25.427152],
389
+ [55.632019, 25.427152],
390
+ [55.632019, 24.763044],
391
+ [54.541626, 24.763044],
392
+ ]
393
+ ),
394
+ "Hong Kong International Airport": Polygon(
395
+ [
396
+ [113.825226, 22.198849],
397
+ [113.825226, 22.349758],
398
+ [114.085121, 22.349758],
399
+ [114.085121, 22.198849],
400
+ [113.825226, 22.198849],
401
+ ]
402
+ ),
403
+ "Las Vegas, NV": Polygon(
404
+ [
405
+ [-115.554199, 35.804449],
406
+ [-115.554199, 36.558188],
407
+ [-113.903503, 36.558188],
408
+ [-113.903503, 35.804449],
409
+ [-115.554199, 35.804449],
410
+ ]
411
+ ),
412
+ "Pucallpa, Peru": Polygon(
413
+ [
414
+ [-74.672699, -8.600032],
415
+ [-74.672699, -8.254983],
416
+ [-74.279938, -8.254983],
417
+ [-74.279938, -8.600032],
418
+ ]
419
+ ),
420
+ "Sierra Gorda, Chile": Polygon(
421
+ [
422
+ [-69.315491, -22.837104],
423
+ [-69.315491, -22.751488],
424
+ [-69.190006, -22.751488],
425
+ [-69.190006, -22.837104],
426
+ [-69.315491, -22.837104],
427
+ ]
428
+ ),
429
+ }
430
+
431
+ modis_rois = {
432
+ "World": Polygon(
433
+ [
434
+ [-171.210938, -57.136239],
435
+ [-171.210938, 79.997168],
436
+ [177.539063, 79.997168],
437
+ [177.539063, -57.136239],
438
+ [-171.210938, -57.136239],
439
+ ]
440
+ ),
441
+ "Africa": Polygon(
442
+ [
443
+ [-18.6983, 38.1446],
444
+ [-18.6983, -36.1630],
445
+ [52.2293, -36.1630],
446
+ [52.2293, 38.1446],
447
+ ]
448
+ ),
449
+ "USA": Polygon(
450
+ [
451
+ [-127.177734, 23.725012],
452
+ [-127.177734, 50.792047],
453
+ [-66.269531, 50.792047],
454
+ [-66.269531, 23.725012],
455
+ [-127.177734, 23.725012],
456
+ ]
457
+ ),
458
+ }
459
+
460
+ ocean_rois = {
461
+ "Gulf of Mexico": Polygon(
462
+ [
463
+ [-101.206055, 15.496032],
464
+ [-101.206055, 32.361403],
465
+ [-75.673828, 32.361403],
466
+ [-75.673828, 15.496032],
467
+ [-101.206055, 15.496032],
468
+ ]
469
+ ),
470
+ "North Atlantic Ocean": Polygon(
471
+ [
472
+ [-85.341797, 24.046464],
473
+ [-85.341797, 45.02695],
474
+ [-55.810547, 45.02695],
475
+ [-55.810547, 24.046464],
476
+ [-85.341797, 24.046464],
477
+ ]
478
+ ),
479
+ "World": Polygon(
480
+ [
481
+ [-171.210938, -57.136239],
482
+ [-171.210938, 79.997168],
483
+ [177.539063, 79.997168],
484
+ [177.539063, -57.136239],
485
+ [-171.210938, -57.136239],
486
+ ]
487
+ ),
488
+ }
489
+
490
+
491
+ @st.cache_data
492
+ def uploaded_file_to_gdf(data):
493
+ import tempfile
494
+ import os
495
+ import uuid
496
+
497
+ _, file_extension = os.path.splitext(data.name)
498
+ file_id = str(uuid.uuid4())
499
+ file_path = os.path.join(tempfile.gettempdir(), f"{file_id}{file_extension}")
500
+
501
+ with open(file_path, "wb") as file:
502
+ file.write(data.getbuffer())
503
+
504
+ if file_path.lower().endswith(".kml"):
505
+ fiona.drvsupport.supported_drivers["KML"] = "rw"
506
+ gdf = gpd.read_file(file_path, driver="KML")
507
+ else:
508
+ gdf = gpd.read_file(file_path)
509
+
510
+ return gdf
511
+
512
+
513
+ def app():
514
+
515
+ today = date.today()
516
+
517
+ st.title("Create Satellite Timelapse")
518
+
519
+ row1_col1, row1_col2 = st.columns([2, 1])
520
+
521
+ if st.session_state.get("zoom_level") is None:
522
+ st.session_state["zoom_level"] = 4
523
+
524
+ st.session_state["ee_asset_id"] = None
525
+ st.session_state["bands"] = None
526
+ st.session_state["palette"] = None
527
+ st.session_state["vis_params"] = None
528
+
529
+ with row1_col1:
530
+ ee_authenticate(token_name="EARTHENGINE_TOKEN")
531
+ m = geemap.Map(
532
+ basemap="HYBRID",
533
+ plugin_Draw=True,
534
+ Draw_export=True,
535
+ locate_control=True,
536
+ plugin_LatLngPopup=False,
537
+ )
538
+ m.add_basemap("ROADMAP")
539
+
540
+ with row1_col2:
541
+
542
+ keyword = st.text_input("Search for a location:", "")
543
+ if keyword:
544
+ locations = geemap.geocode(keyword)
545
+ if locations is not None and len(locations) > 0:
546
+ str_locations = [str(g)[1:-1] for g in locations]
547
+ location = st.selectbox("Select a location:", str_locations)
548
+ loc_index = str_locations.index(location)
549
+ selected_loc = locations[loc_index]
550
+ lat, lng = selected_loc.lat, selected_loc.lng
551
+ folium.Marker(location=[lat, lng], popup=location).add_to(m)
552
+ m.set_center(lng, lat, 12)
553
+ st.session_state["zoom_level"] = 12
554
+
555
+ collection = st.selectbox(
556
+ "Select a satellite image collection: ",
557
+ [
558
+ "Any Earth Engine ImageCollection",
559
+ "Landsat TM-ETM-OLI Surface Reflectance",
560
+ "Sentinel-2 MSI Surface Reflectance",
561
+ "Geostationary Operational Environmental Satellites (GOES)",
562
+ "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km",
563
+ "MODIS Gap filled Land Surface Temperature Daily",
564
+ "MODIS Ocean Color SMI",
565
+ "USDA National Agriculture Imagery Program (NAIP)","Modis",
566
+ "dataset_nighttime", 'precipitation', 'GlobalSurfaceWater', 'WorldPop', 'COPERNICUS'
567
+ ],
568
+ index=1,
569
+ )
570
+
571
+ if collection in [
572
+ "Landsat TM-ETM-OLI Surface Reflectance",
573
+ "Sentinel-2 MSI Surface Reflectance",
574
+ ]:
575
+ roi_options = ["Uploaded GeoJSON"] + list(landsat_rois.keys())
576
+
577
+ elif collection == "Geostationary Operational Environmental Satellites (GOES)":
578
+ roi_options = ["Uploaded GeoJSON"] + list(goes_rois.keys())
579
+
580
+ elif collection in [
581
+ "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km",
582
+ "MODIS Gap filled Land Surface Temperature Daily",
583
+ ]:
584
+ roi_options = ["Uploaded GeoJSON"] + list(modis_rois.keys())
585
+ elif collection == "MODIS Ocean Color SMI":
586
+ roi_options = ["Uploaded GeoJSON"] + list(ocean_rois.keys())
587
+ else:
588
+ roi_options = ["Uploaded GeoJSON"]
589
+
590
+ if collection == "Any Earth Engine ImageCollection":
591
+ keyword = st.text_input("Enter a keyword to search (e.g., MODIS):", "")
592
+ if keyword:
593
+
594
+ assets = geemap.search_ee_data(keyword)
595
+ ee_assets = []
596
+ for asset in assets:
597
+ if asset["ee_id_snippet"].startswith("ee.ImageCollection"):
598
+ ee_assets.append(asset)
599
+
600
+ asset_titles = [x["title"] for x in ee_assets]
601
+ dataset = st.selectbox("Select a dataset:", asset_titles)
602
+ if len(ee_assets) > 0:
603
+ st.session_state["ee_assets"] = ee_assets
604
+ st.session_state["asset_titles"] = asset_titles
605
+ index = asset_titles.index(dataset)
606
+ ee_id = ee_assets[index]["id"]
607
+ else:
608
+ ee_id = ""
609
+
610
+ if dataset is not None:
611
+ with st.expander("Show dataset details", False):
612
+ index = asset_titles.index(dataset)
613
+ html = geemap.ee_data_html(st.session_state["ee_assets"][index])
614
+ st.markdown(html, True)
615
+ # elif collection == "MODIS Gap filled Land Surface Temperature Daily":
616
+ # ee_id = ""
617
+ else:
618
+ ee_id = ""
619
+
620
+ asset_id = st.text_input("Enter an ee.ImageCollection asset ID:", ee_id)
621
+
622
+ if asset_id:
623
+ with st.expander("Customize band combination and color palette", True):
624
+ try:
625
+ col = ee.ImageCollection.load(asset_id)
626
+ st.session_state["ee_asset_id"] = asset_id
627
+ except:
628
+ st.error("Invalid Earth Engine asset ID.")
629
+ st.session_state["ee_asset_id"] = None
630
+ return
631
+
632
+ img_bands = col.first().bandNames().getInfo()
633
+ if len(img_bands) >= 3:
634
+ default_bands = img_bands[:3][::-1]
635
+ else:
636
+ default_bands = img_bands[:]
637
+ bands = st.multiselect(
638
+ "Select one or three bands (RGB):", img_bands, default_bands
639
+ )
640
+ st.session_state["bands"] = bands
641
+
642
+ if len(bands) == 1:
643
+ palette_options = st.selectbox(
644
+ "Color palette",
645
+ cm.list_colormaps(),
646
+ index=2,
647
+ )
648
+ palette_values = cm.get_palette(palette_options, 15)
649
+ palette = st.text_area(
650
+ "Enter a custom palette:",
651
+ palette_values,
652
+ )
653
+ st.write(
654
+ cm.plot_colormap(cmap=palette_options, return_fig=True)
655
+ )
656
+ st.session_state["palette"] = json.loads(
657
+ palette.replace("'", '"')
658
+ )
659
+
660
+ if bands:
661
+ vis_params = st.text_area(
662
+ "Enter visualization parameters",
663
+ "{'bands': ["
664
+ + ", ".join([f"'{band}'" for band in bands])
665
+ + "]}",
666
+ )
667
+ else:
668
+ vis_params = st.text_area(
669
+ "Enter visualization parameters",
670
+ "{}",
671
+ )
672
+ try:
673
+ st.session_state["vis_params"] = json.loads(
674
+ vis_params.replace("'", '"')
675
+ )
676
+ st.session_state["vis_params"]["palette"] = st.session_state[
677
+ "palette"
678
+ ]
679
+ except Exception as e:
680
+ st.session_state["vis_params"] = None
681
+ st.error(
682
+ f"Invalid visualization parameters. It must be a dictionary."
683
+ )
684
+
685
+
686
+ elif collection == "MODIS Gap filled Land Surface Temperature Daily":
687
+ with st.expander("Show dataset details", False):
688
+ st.markdown(
689
+ """
690
+ See the [Awesome GEE Community Datasets](https://samapriya.github.io/awesome-gee-community-datasets/projects/daily_lst/).
691
+ """
692
+ )
693
+
694
+ MODIS_options = ["Daytime (1:30 pm)", "Nighttime (1:30 am)"]
695
+ MODIS_option = st.selectbox("Select a MODIS dataset:", MODIS_options)
696
+ if MODIS_option == "Daytime (1:30 pm)":
697
+ st.session_state["ee_asset_id"] = (
698
+ "projects/sat-io/open-datasets/gap-filled-lst/gf_day_1km"
699
+ )
700
+ else:
701
+ st.session_state["ee_asset_id"] = (
702
+ "projects/sat-io/open-datasets/gap-filled-lst/gf_night_1km"
703
+ )
704
+
705
+ palette_options = st.selectbox(
706
+ "Color palette",
707
+ cm.list_colormaps(),
708
+ index=90,
709
+ )
710
+ palette_values = cm.get_palette(palette_options, 15)
711
+ palette = st.text_area(
712
+ "Enter a custom palette:",
713
+ palette_values,
714
+ )
715
+ st.write(cm.plot_colormap(cmap=palette_options, return_fig=True))
716
+ st.session_state["palette"] = json.loads(palette.replace("'", '"'))
717
+ elif collection == "MODIS Ocean Color SMI":
718
+ with st.expander("Show dataset details", False):
719
+ st.markdown(
720
+ """
721
+ See the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog/NASA_OCEANDATA_MODIS-Aqua_L3SMI).
722
+ """
723
+ )
724
+
725
+ MODIS_options = ["Aqua", "Terra"]
726
+ MODIS_option = st.selectbox("Select a satellite:", MODIS_options)
727
+ st.session_state["ee_asset_id"] = MODIS_option
728
+ # if MODIS_option == "Daytime (1:30 pm)":
729
+ # st.session_state[
730
+ # "ee_asset_id"
731
+ # ] = "projects/sat-io/open-datasets/gap-filled-lst/gf_day_1km"
732
+ # else:
733
+ # st.session_state[
734
+ # "ee_asset_id"
735
+ # ] = "projects/sat-io/open-datasets/gap-filled-lst/gf_night_1km"
736
+
737
+ band_dict = {
738
+ "Chlorophyll a concentration": "chlor_a",
739
+ "Normalized fluorescence line height": "nflh",
740
+ "Particulate organic carbon": "poc",
741
+ "Sea surface temperature": "sst",
742
+ "Remote sensing reflectance at band 412nm": "Rrs_412",
743
+ "Remote sensing reflectance at band 443nm": "Rrs_443",
744
+ "Remote sensing reflectance at band 469nm": "Rrs_469",
745
+ "Remote sensing reflectance at band 488nm": "Rrs_488",
746
+ "Remote sensing reflectance at band 531nm": "Rrs_531",
747
+ "Remote sensing reflectance at band 547nm": "Rrs_547",
748
+ "Remote sensing reflectance at band 555nm": "Rrs_555",
749
+ "Remote sensing reflectance at band 645nm": "Rrs_645",
750
+ "Remote sensing reflectance at band 667nm": "Rrs_667",
751
+ "Remote sensing reflectance at band 678nm": "Rrs_678",
752
+ }
753
+
754
+ band_options = list(band_dict.keys())
755
+ band = st.selectbox(
756
+ "Select a band",
757
+ band_options,
758
+ band_options.index("Sea surface temperature"),
759
+ )
760
+ st.session_state["band"] = band_dict[band]
761
+
762
+ colors = cm.list_colormaps()
763
+ palette_options = st.selectbox(
764
+ "Color palette",
765
+ colors,
766
+ index=colors.index("coolwarm"),
767
+ )
768
+ palette_values = cm.get_palette(palette_options, 15)
769
+ palette = st.text_area(
770
+ "Enter a custom palette:",
771
+ palette_values,
772
+ )
773
+ st.write(cm.plot_colormap(cmap=palette_options, return_fig=True))
774
+ st.session_state["palette"] = json.loads(palette.replace("'", '"'))
775
+
776
+ sample_roi = st.selectbox(
777
+ "Select a sample ROI or upload a GeoJSON file:",
778
+ roi_options,
779
+ index=0,
780
+ )
781
+
782
+ add_outline = st.checkbox(
783
+ "Overlay an administrative boundary on timelapse", False
784
+ )
785
+
786
+ if add_outline:
787
+
788
+ with st.expander("Customize administrative boundary", True):
789
+
790
+ overlay_options = {
791
+ "User-defined": None,
792
+ "Continents": "continents",
793
+ "Countries": "countries",
794
+ "US States": "us_states",
795
+ "China": "china",
796
+ }
797
+
798
+ overlay = st.selectbox(
799
+ "Select an administrative boundary:",
800
+ list(overlay_options.keys()),
801
+ index=2,
802
+ )
803
+
804
+ overlay_data = overlay_options[overlay]
805
+
806
+ if overlay_data is None:
807
+ overlay_data = st.text_input(
808
+ "Enter an HTTP URL to a GeoJSON file or an ee.FeatureCollection asset id:",
809
+ "https://raw.githubusercontent.com/giswqs/geemap/master/examples/data/countries.geojson",
810
+ )
811
+
812
+ overlay_color = st.color_picker(
813
+ "Select a color for the administrative boundary:", "#000000"
814
+ )
815
+ overlay_width = st.slider(
816
+ "Select a line width for the administrative boundary:", 1, 20, 1
817
+ )
818
+ overlay_opacity = st.slider(
819
+ "Select an opacity for the administrative boundary:",
820
+ 0.0,
821
+ 1.0,
822
+ 1.0,
823
+ 0.05,
824
+ )
825
+ else:
826
+ overlay_data = None
827
+ overlay_color = "black"
828
+ overlay_width = 1
829
+ overlay_opacity = 1
830
+
831
+ with row1_col1:
832
+
833
+ with st.expander(
834
+ "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 👉"
835
+ ):
836
+ video_empty = st.empty()
837
+
838
+ data = st.file_uploader(
839
+ "Upload a GeoJSON file to use as an ROI. Customize timelapse parameters and then click the Submit button 😇👇",
840
+ type=["geojson", "kml", "zip"],
841
+ )
842
+
843
+ crs = "epsg:4326"
844
+ if sample_roi == "Uploaded GeoJSON":
845
+ if data is None:
846
+ # st.info(
847
+ # "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"
848
+ # )
849
+ if collection in [
850
+ "Geostationary Operational Environmental Satellites (GOES)",
851
+ "USDA National Agriculture Imagery Program (NAIP)",
852
+ ] and (not keyword):
853
+ m.set_center(-100, 40, 3)
854
+ # else:
855
+ # m.set_center(4.20, 18.63, zoom=2)
856
+ else:
857
+ if collection in [
858
+ "Landsat TM-ETM-OLI Surface Reflectance",
859
+ "Sentinel-2 MSI Surface Reflectance",
860
+ ]:
861
+ gdf = gpd.GeoDataFrame(
862
+ index=[0], crs=crs, geometry=[landsat_rois[sample_roi]]
863
+ )
864
+ elif (
865
+ collection
866
+ == "Geostationary Operational Environmental Satellites (GOES)"
867
+ ):
868
+ gdf = gpd.GeoDataFrame(
869
+ index=[0], crs=crs, geometry=[goes_rois[sample_roi]["region"]]
870
+ )
871
+ elif collection == "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km":
872
+ gdf = gpd.GeoDataFrame(
873
+ index=[0], crs=crs, geometry=[modis_rois[sample_roi]]
874
+ )
875
+
876
+ if sample_roi != "Uploaded GeoJSON":
877
+
878
+ if collection in [
879
+ "Landsat TM-ETM-OLI Surface Reflectance",
880
+ "Sentinel-2 MSI Surface Reflectance",
881
+ ]:
882
+ gdf = gpd.GeoDataFrame(
883
+ index=[0], crs=crs, geometry=[landsat_rois[sample_roi]]
884
+ )
885
+ elif (
886
+ collection
887
+ == "Geostationary Operational Environmental Satellites (GOES)"
888
+ ):
889
+ gdf = gpd.GeoDataFrame(
890
+ index=[0], crs=crs, geometry=[goes_rois[sample_roi]["region"]]
891
+ )
892
+ elif collection in [
893
+ "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km",
894
+ "MODIS Gap filled Land Surface Temperature Daily",
895
+ ]:
896
+ gdf = gpd.GeoDataFrame(
897
+ index=[0], crs=crs, geometry=[modis_rois[sample_roi]]
898
+ )
899
+ elif collection == "MODIS Ocean Color SMI":
900
+ gdf = gpd.GeoDataFrame(
901
+ index=[0], crs=crs, geometry=[ocean_rois[sample_roi]]
902
+ )
903
+ try:
904
+ st.session_state["roi"] = geemap.gdf_to_ee(gdf, geodesic=False)
905
+ except Exception as e:
906
+ st.error(e)
907
+ st.error("Please draw another ROI and try again.")
908
+ return
909
+ m.add_gdf(gdf, "ROI")
910
+
911
+ elif data:
912
+ gdf = uploaded_file_to_gdf(data)
913
+ try:
914
+ st.session_state["roi"] = geemap.gdf_to_ee(gdf, geodesic=False)
915
+ m.add_gdf(gdf, "ROI")
916
+ except Exception as e:
917
+ st.error(e)
918
+ st.error("Please draw another ROI and try again.")
919
+ return
920
+
921
+ m.to_streamlit(height=600)
922
+
923
+ with row1_col2:
924
+
925
+ if collection in [
926
+ "Landsat TM-ETM-OLI Surface Reflectance",
927
+ "Sentinel-2 MSI Surface Reflectance",
928
+ ]:
929
+
930
+ if collection == "Landsat TM-ETM-OLI Surface Reflectance":
931
+ sensor_start_year = 1984
932
+ timelapse_title = "Landsat Timelapse"
933
+ timelapse_speed = 5
934
+ elif collection == "Sentinel-2 MSI Surface Reflectance":
935
+ sensor_start_year = 2015
936
+ timelapse_title = "Sentinel-2 Timelapse"
937
+ timelapse_speed = 5
938
+ video_empty.video("https://youtu.be/VVRK_-dEjR4")
939
+
940
+ with st.form("submit_landsat_form"):
941
+
942
+ roi = None
943
+ if st.session_state.get("roi") is not None:
944
+ roi = st.session_state.get("roi")
945
+ out_gif = geemap.temp_file_path(".gif")
946
+
947
+ title = st.text_input(
948
+ "Enter a title to show on the timelapse: ", timelapse_title
949
+ )
950
+ RGB = st.selectbox(
951
+ "Select an RGB band combination:",
952
+ [
953
+ "Red/Green/Blue",
954
+ "NIR/Red/Green",
955
+ "SWIR2/SWIR1/NIR",
956
+ "NIR/SWIR1/Red",
957
+ "SWIR2/NIR/Red",
958
+ "SWIR2/SWIR1/Red",
959
+ "SWIR1/NIR/Blue",
960
+ "NIR/SWIR1/Blue",
961
+ "SWIR2/NIR/Green",
962
+ "SWIR1/NIR/Red",
963
+ "SWIR2/NIR/SWIR1",
964
+ "SWIR1/NIR/SWIR2",
965
+ ],
966
+ index=9,
967
+ )
968
+
969
+ frequency = st.selectbox(
970
+ "Select a temporal frequency:",
971
+ ["year", "quarter", "month"],
972
+ index=0,
973
+ )
974
+
975
+ with st.expander("Customize timelapse"):
976
+
977
+ speed = st.slider("Frames per second:", 1, 30, timelapse_speed)
978
+ dimensions = st.slider(
979
+ "Maximum dimensions (Width*Height) in pixels", 768, 2000, 768
980
+ )
981
+ progress_bar_color = st.color_picker(
982
+ "Progress bar color:", "#0000ff"
983
+ )
984
+ years = st.slider(
985
+ "Start and end year:",
986
+ sensor_start_year,
987
+ today.year,
988
+ (sensor_start_year, today.year),
989
+ )
990
+ months = st.slider("Start and end month:", 1, 12, (1, 12))
991
+ font_size = st.slider("Font size:", 10, 50, 30)
992
+ font_color = st.color_picker("Font color:", "#ffffff")
993
+ apply_fmask = st.checkbox(
994
+ "Apply fmask (remove clouds, shadows, snow)", True
995
+ )
996
+ font_type = st.selectbox(
997
+ "Select the font type for the title:",
998
+ ["arial.ttf", "alibaba.otf"],
999
+ index=0,
1000
+ )
1001
+ fading = st.slider(
1002
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1003
+ )
1004
+ mp4 = st.checkbox("Save timelapse as MP4", True)
1005
+
1006
+ empty_text = st.empty()
1007
+ empty_image = st.empty()
1008
+ empty_fire_image = st.empty()
1009
+ empty_video = st.container()
1010
+ submitted = st.form_submit_button("Submit")
1011
+ if submitted:
1012
+
1013
+ if sample_roi == "Uploaded GeoJSON" and data is None:
1014
+ empty_text.warning(
1015
+ "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."
1016
+ )
1017
+ else:
1018
+
1019
+ empty_text.text("Computing... Please wait...")
1020
+
1021
+ start_year = years[0]
1022
+ end_year = years[1]
1023
+ start_date = str(months[0]).zfill(2) + "-01"
1024
+ end_date = str(months[1]).zfill(2) + "-30"
1025
+ bands = RGB.split("/")
1026
+
1027
+ try:
1028
+ if collection == "Landsat TM-ETM-OLI Surface Reflectance":
1029
+ out_gif = geemap.landsat_timelapse(
1030
+ roi=roi,
1031
+ out_gif=out_gif,
1032
+ start_year=start_year,
1033
+ end_year=end_year,
1034
+ start_date=start_date,
1035
+ end_date=end_date,
1036
+ bands=bands,
1037
+ apply_fmask=apply_fmask,
1038
+ frames_per_second=speed,
1039
+ # dimensions=dimensions,
1040
+ dimensions=768,
1041
+ overlay_data=overlay_data,
1042
+ overlay_color=overlay_color,
1043
+ overlay_width=overlay_width,
1044
+ overlay_opacity=overlay_opacity,
1045
+ frequency=frequency,
1046
+ date_format=None,
1047
+ title=title,
1048
+ title_xy=("2%", "90%"),
1049
+ add_text=True,
1050
+ text_xy=("2%", "2%"),
1051
+ text_sequence=None,
1052
+ font_type=font_type,
1053
+ font_size=font_size,
1054
+ font_color=font_color,
1055
+ add_progress_bar=True,
1056
+ progress_bar_color=progress_bar_color,
1057
+ progress_bar_height=5,
1058
+ loop=0,
1059
+ mp4=mp4,
1060
+ fading=fading,
1061
+ )
1062
+ elif collection == "Sentinel-2 MSI Surface Reflectance":
1063
+ out_gif = geemap.sentinel2_timelapse(
1064
+ roi=roi,
1065
+ out_gif=out_gif,
1066
+ start_year=start_year,
1067
+ end_year=end_year,
1068
+ start_date=start_date,
1069
+ end_date=end_date,
1070
+ bands=bands,
1071
+ apply_fmask=apply_fmask,
1072
+ frames_per_second=speed,
1073
+ dimensions=768,
1074
+ # dimensions=dimensions,
1075
+ overlay_data=overlay_data,
1076
+ overlay_color=overlay_color,
1077
+ overlay_width=overlay_width,
1078
+ overlay_opacity=overlay_opacity,
1079
+ frequency=frequency,
1080
+ date_format=None,
1081
+ title=title,
1082
+ title_xy=("2%", "90%"),
1083
+ add_text=True,
1084
+ text_xy=("2%", "2%"),
1085
+ text_sequence=None,
1086
+ font_type=font_type,
1087
+ font_size=font_size,
1088
+ font_color=font_color,
1089
+ add_progress_bar=True,
1090
+ progress_bar_color=progress_bar_color,
1091
+ progress_bar_height=5,
1092
+ loop=0,
1093
+ mp4=mp4,
1094
+ fading=fading,
1095
+ )
1096
+ except:
1097
+ empty_text.error(
1098
+ "An error occurred while computing the timelapse. Your probably requested too much data. Try reducing the ROI or timespan."
1099
+ )
1100
+ st.stop()
1101
+
1102
+ if out_gif is not None and os.path.exists(out_gif):
1103
+
1104
+ empty_text.text(
1105
+ "Right click the GIF to save it to your computer👇"
1106
+ )
1107
+ empty_image.image(out_gif)
1108
+
1109
+ out_mp4 = out_gif.replace(".gif", ".mp4")
1110
+ if mp4 and os.path.exists(out_mp4):
1111
+ with empty_video:
1112
+ st.text(
1113
+ "Right click the MP4 to save it to your computer👇"
1114
+ )
1115
+ st.video(out_gif.replace(".gif", ".mp4"))
1116
+
1117
+ else:
1118
+ empty_text.error(
1119
+ "Something went wrong. You probably requested too much data. Try reducing the ROI or timespan."
1120
+ )
1121
+
1122
+ elif collection == "Geostationary Operational Environmental Satellites (GOES)":
1123
+
1124
+ video_empty.video("https://youtu.be/16fA2QORG4A")
1125
+
1126
+ with st.form("submit_goes_form"):
1127
+
1128
+ roi = None
1129
+ if st.session_state.get("roi") is not None:
1130
+ roi = st.session_state.get("roi")
1131
+ out_gif = geemap.temp_file_path(".gif")
1132
+
1133
+ satellite = st.selectbox("Select a satellite:", ["GOES-17", "GOES-16"])
1134
+ earliest_date = datetime.date(2017, 7, 10)
1135
+ latest_date = datetime.date.today()
1136
+
1137
+ if sample_roi == "Uploaded GeoJSON":
1138
+ roi_start_date = today - datetime.timedelta(days=2)
1139
+ roi_end_date = today - datetime.timedelta(days=1)
1140
+ roi_start_time = datetime.time(14, 00)
1141
+ roi_end_time = datetime.time(1, 00)
1142
+ else:
1143
+ roi_start = goes_rois[sample_roi]["start_time"]
1144
+ roi_end = goes_rois[sample_roi]["end_time"]
1145
+ roi_start_date = datetime.datetime.strptime(
1146
+ roi_start[:10], "%Y-%m-%d"
1147
+ )
1148
+ roi_end_date = datetime.datetime.strptime(roi_end[:10], "%Y-%m-%d")
1149
+ roi_start_time = datetime.time(
1150
+ int(roi_start[11:13]), int(roi_start[14:16])
1151
+ )
1152
+ roi_end_time = datetime.time(
1153
+ int(roi_end[11:13]), int(roi_end[14:16])
1154
+ )
1155
+
1156
+ start_date = st.date_input("Select the start date:", roi_start_date)
1157
+ end_date = st.date_input("Select the end date:", roi_end_date)
1158
+
1159
+ with st.expander("Customize timelapse"):
1160
+
1161
+ add_fire = st.checkbox("Add Fire/Hotspot Characterization", False)
1162
+
1163
+ scan_type = st.selectbox(
1164
+ "Select a scan type:", ["Full Disk", "CONUS", "Mesoscale"]
1165
+ )
1166
+
1167
+ start_time = st.time_input(
1168
+ "Select the start time of the start date:", roi_start_time
1169
+ )
1170
+
1171
+ end_time = st.time_input(
1172
+ "Select the end time of the end date:", roi_end_time
1173
+ )
1174
+
1175
+ start = (
1176
+ start_date.strftime("%Y-%m-%d")
1177
+ + "T"
1178
+ + start_time.strftime("%H:%M:%S")
1179
+ )
1180
+ end = (
1181
+ end_date.strftime("%Y-%m-%d")
1182
+ + "T"
1183
+ + end_time.strftime("%H:%M:%S")
1184
+ )
1185
+
1186
+ speed = st.slider("Frames per second:", 1, 30, 5)
1187
+ add_progress_bar = st.checkbox("Add a progress bar", True)
1188
+ progress_bar_color = st.color_picker(
1189
+ "Progress bar color:", "#0000ff"
1190
+ )
1191
+ font_size = st.slider("Font size:", 10, 50, 20)
1192
+ font_color = st.color_picker("Font color:", "#ffffff")
1193
+ fading = st.slider(
1194
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1195
+ )
1196
+ mp4 = st.checkbox("Save timelapse as MP4", True)
1197
+
1198
+ empty_text = st.empty()
1199
+ empty_image = st.empty()
1200
+ empty_video = st.container()
1201
+ empty_fire_text = st.empty()
1202
+ empty_fire_image = st.empty()
1203
+
1204
+ submitted = st.form_submit_button("Submit")
1205
+ if submitted:
1206
+ if sample_roi == "Uploaded GeoJSON" and data is None:
1207
+ empty_text.warning(
1208
+ "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."
1209
+ )
1210
+ else:
1211
+ empty_text.text("Computing... Please wait...")
1212
+
1213
+ geemap.goes_timelapse(
1214
+ roi,
1215
+ out_gif,
1216
+ start_date=start,
1217
+ end_date=end,
1218
+ data=satellite,
1219
+ scan=scan_type.replace(" ", "_").lower(),
1220
+ dimensions=768,
1221
+ framesPerSecond=speed,
1222
+ date_format="YYYY-MM-dd HH:mm",
1223
+ xy=("3%", "3%"),
1224
+ text_sequence=None,
1225
+ font_type="arial.ttf",
1226
+ font_size=font_size,
1227
+ font_color=font_color,
1228
+ add_progress_bar=add_progress_bar,
1229
+ progress_bar_color=progress_bar_color,
1230
+ progress_bar_height=5,
1231
+ loop=0,
1232
+ overlay_data=overlay_data,
1233
+ overlay_color=overlay_color,
1234
+ overlay_width=overlay_width,
1235
+ overlay_opacity=overlay_opacity,
1236
+ mp4=mp4,
1237
+ fading=fading,
1238
+ )
1239
+
1240
+ if out_gif is not None and os.path.exists(out_gif):
1241
+ empty_text.text(
1242
+ "Right click the GIF to save it to your computer👇"
1243
+ )
1244
+ empty_image.image(out_gif)
1245
+
1246
+ out_mp4 = out_gif.replace(".gif", ".mp4")
1247
+ if mp4 and os.path.exists(out_mp4):
1248
+ with empty_video:
1249
+ st.text(
1250
+ "Right click the MP4 to save it to your computer👇"
1251
+ )
1252
+ st.video(out_gif.replace(".gif", ".mp4"))
1253
+
1254
+ if add_fire:
1255
+ out_fire_gif = geemap.temp_file_path(".gif")
1256
+ empty_fire_text.text(
1257
+ "Delineating Fire Hotspot... Please wait..."
1258
+ )
1259
+ geemap.goes_fire_timelapse(
1260
+ out_fire_gif,
1261
+ start_date=start,
1262
+ end_date=end,
1263
+ data=satellite,
1264
+ scan=scan_type.replace(" ", "_").lower(),
1265
+ region=roi,
1266
+ dimensions=768,
1267
+ framesPerSecond=speed,
1268
+ date_format="YYYY-MM-dd HH:mm",
1269
+ xy=("3%", "3%"),
1270
+ text_sequence=None,
1271
+ font_type="arial.ttf",
1272
+ font_size=font_size,
1273
+ font_color=font_color,
1274
+ add_progress_bar=add_progress_bar,
1275
+ progress_bar_color=progress_bar_color,
1276
+ progress_bar_height=5,
1277
+ loop=0,
1278
+ )
1279
+ if os.path.exists(out_fire_gif):
1280
+ empty_fire_image.image(out_fire_gif)
1281
+ else:
1282
+ empty_text.text(
1283
+ "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."
1284
+ )
1285
+
1286
+ elif collection == "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km":
1287
+
1288
+ video_empty.video("https://youtu.be/16fA2QORG4A")
1289
+
1290
+ satellite = st.selectbox("Select a satellite:", ["Terra", "Aqua"])
1291
+ band = st.selectbox("Select a band:", ["NDVI", "EVI"])
1292
+
1293
+ with st.form("submit_modis_form"):
1294
+
1295
+ roi = None
1296
+ if st.session_state.get("roi") is not None:
1297
+ roi = st.session_state.get("roi")
1298
+ out_gif = geemap.temp_file_path(".gif")
1299
+
1300
+ with st.expander("Customize timelapse"):
1301
+
1302
+ start = st.date_input(
1303
+ "Select a start date:", datetime.date(2000, 2, 8)
1304
+ )
1305
+ end = st.date_input("Select an end date:", datetime.date.today())
1306
+
1307
+ start_date = start.strftime("%Y-%m-%d")
1308
+ end_date = end.strftime("%Y-%m-%d")
1309
+
1310
+ speed = st.slider("Frames per second:", 1, 30, 5)
1311
+ add_progress_bar = st.checkbox("Add a progress bar", True)
1312
+ progress_bar_color = st.color_picker(
1313
+ "Progress bar color:", "#0000ff"
1314
+ )
1315
+ font_size = st.slider("Font size:", 10, 50, 20)
1316
+ font_color = st.color_picker("Font color:", "#ffffff")
1317
+
1318
+ font_type = st.selectbox(
1319
+ "Select the font type for the title:",
1320
+ ["arial.ttf", "alibaba.otf"],
1321
+ index=0,
1322
+ )
1323
+ fading = st.slider(
1324
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1325
+ )
1326
+ mp4 = st.checkbox("Save timelapse as MP4", True)
1327
+
1328
+ empty_text = st.empty()
1329
+ empty_image = st.empty()
1330
+ empty_video = st.container()
1331
+
1332
+ submitted = st.form_submit_button("Submit")
1333
+ if submitted:
1334
+ if sample_roi == "Uploaded GeoJSON" and data is None:
1335
+ empty_text.warning(
1336
+ "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."
1337
+ )
1338
+ else:
1339
+
1340
+ empty_text.text("Computing... Please wait...")
1341
+
1342
+ geemap.modis_ndvi_timelapse(
1343
+ roi,
1344
+ out_gif,
1345
+ satellite,
1346
+ band,
1347
+ start_date,
1348
+ end_date,
1349
+ 768,
1350
+ speed,
1351
+ overlay_data=overlay_data,
1352
+ overlay_color=overlay_color,
1353
+ overlay_width=overlay_width,
1354
+ overlay_opacity=overlay_opacity,
1355
+ mp4=mp4,
1356
+ fading=fading,
1357
+ )
1358
+
1359
+ geemap.reduce_gif_size(out_gif)
1360
+
1361
+ empty_text.text(
1362
+ "Right click the GIF to save it to your computer👇"
1363
+ )
1364
+ empty_image.image(out_gif)
1365
+
1366
+ out_mp4 = out_gif.replace(".gif", ".mp4")
1367
+ if mp4 and os.path.exists(out_mp4):
1368
+ with empty_video:
1369
+ st.text(
1370
+ "Right click the MP4 to save it to your computer👇"
1371
+ )
1372
+ st.video(out_gif.replace(".gif", ".mp4"))
1373
+
1374
+ elif collection == "Any Earth Engine ImageCollection":
1375
+
1376
+ with st.form("submit_ts_form"):
1377
+ with st.expander("Customize timelapse"):
1378
+
1379
+ title = st.text_input(
1380
+ "Enter a title to show on the timelapse: ", "Timelapse"
1381
+ )
1382
+ start_date = st.date_input(
1383
+ "Select the start date:", datetime.date(2020, 1, 1)
1384
+ )
1385
+ end_date = st.date_input(
1386
+ "Select the end date:", datetime.date.today()
1387
+ )
1388
+ frequency = st.selectbox(
1389
+ "Select a temporal frequency:",
1390
+ ["year", "quarter", "month", "day", "hour", "minute", "second"],
1391
+ index=0,
1392
+ )
1393
+ reducer = st.selectbox(
1394
+ "Select a reducer for aggregating data:",
1395
+ ["median", "mean", "min", "max", "sum", "variance", "stdDev"],
1396
+ index=0,
1397
+ )
1398
+ data_format = st.selectbox(
1399
+ "Select a date format to show on the timelapse:",
1400
+ [
1401
+ "YYYY-MM-dd",
1402
+ "YYYY",
1403
+ "YYMM-MM",
1404
+ "YYYY-MM-dd HH:mm",
1405
+ "YYYY-MM-dd HH:mm:ss",
1406
+ "HH:mm",
1407
+ "HH:mm:ss",
1408
+ "w",
1409
+ "M",
1410
+ "d",
1411
+ "D",
1412
+ ],
1413
+ index=0,
1414
+ )
1415
+
1416
+ speed = st.slider("Frames per second:", 1, 30, 5)
1417
+ add_progress_bar = st.checkbox("Add a progress bar", True)
1418
+ progress_bar_color = st.color_picker(
1419
+ "Progress bar color:", "#0000ff"
1420
+ )
1421
+ font_size = st.slider("Font size:", 10, 50, 30)
1422
+ font_color = st.color_picker("Font color:", "#ffffff")
1423
+ font_type = st.selectbox(
1424
+ "Select the font type for the title:",
1425
+ ["arial.ttf", "alibaba.otf"],
1426
+ index=0,
1427
+ )
1428
+ fading = st.slider(
1429
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1430
+ )
1431
+ mp4 = st.checkbox("Save timelapse as MP4", True)
1432
+
1433
+ empty_text = st.empty()
1434
+ empty_image = st.empty()
1435
+ empty_video = st.container()
1436
+ empty_fire_image = st.empty()
1437
+
1438
+ roi = None
1439
+ if st.session_state.get("roi") is not None:
1440
+ roi = st.session_state.get("roi")
1441
+ out_gif = geemap.temp_file_path(".gif")
1442
+
1443
+ submitted = st.form_submit_button("Submit")
1444
+ if submitted:
1445
+
1446
+ if sample_roi == "Uploaded GeoJSON" and data is None:
1447
+ empty_text.warning(
1448
+ "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."
1449
+ )
1450
+ else:
1451
+
1452
+ empty_text.text("Computing... Please wait...")
1453
+ try:
1454
+ geemap.create_timelapse(
1455
+ st.session_state.get("ee_asset_id"),
1456
+ start_date=start_date.strftime("%Y-%m-%d"),
1457
+ end_date=end_date.strftime("%Y-%m-%d"),
1458
+ region=roi,
1459
+ frequency=frequency,
1460
+ reducer=reducer,
1461
+ date_format=data_format,
1462
+ out_gif=out_gif,
1463
+ bands=st.session_state.get("bands"),
1464
+ palette=st.session_state.get("palette"),
1465
+ vis_params=st.session_state.get("vis_params"),
1466
+ dimensions=768,
1467
+ frames_per_second=speed,
1468
+ crs="EPSG:3857",
1469
+ overlay_data=overlay_data,
1470
+ overlay_color=overlay_color,
1471
+ overlay_width=overlay_width,
1472
+ overlay_opacity=overlay_opacity,
1473
+ title=title,
1474
+ title_xy=("2%", "90%"),
1475
+ add_text=True,
1476
+ text_xy=("2%", "2%"),
1477
+ text_sequence=None,
1478
+ font_type=font_type,
1479
+ font_size=font_size,
1480
+ font_color=font_color,
1481
+ add_progress_bar=add_progress_bar,
1482
+ progress_bar_color=progress_bar_color,
1483
+ progress_bar_height=5,
1484
+ loop=0,
1485
+ mp4=mp4,
1486
+ fading=fading,
1487
+ )
1488
+ except:
1489
+ empty_text.error(
1490
+ "An error occurred while computing the timelapse. You probably requested too much data. Try reducing the ROI or timespan."
1491
+ )
1492
+
1493
+ empty_text.text(
1494
+ "Right click the GIF to save it to your computer👇"
1495
+ )
1496
+ empty_image.image(out_gif)
1497
+
1498
+ out_mp4 = out_gif.replace(".gif", ".mp4")
1499
+ if mp4 and os.path.exists(out_mp4):
1500
+ with empty_video:
1501
+ st.text(
1502
+ "Right click the MP4 to save it to your computer👇"
1503
+ )
1504
+ st.video(out_gif.replace(".gif", ".mp4"))
1505
+
1506
+ elif collection in [
1507
+ "MODIS Gap filled Land Surface Temperature Daily",
1508
+ "MODIS Ocean Color SMI",
1509
+ ]:
1510
+
1511
+ with st.form("submit_ts_form"):
1512
+ with st.expander("Customize timelapse"):
1513
+
1514
+ title = st.text_input(
1515
+ "Enter a title to show on the timelapse: ",
1516
+ "Surface Temperature",
1517
+ )
1518
+ start_date = st.date_input(
1519
+ "Select the start date:", datetime.date(2018, 1, 1)
1520
+ )
1521
+ end_date = st.date_input(
1522
+ "Select the end date:", datetime.date(2020, 12, 31)
1523
+ )
1524
+ frequency = st.selectbox(
1525
+ "Select a temporal frequency:",
1526
+ ["year", "quarter", "month", "week", "day"],
1527
+ index=2,
1528
+ )
1529
+ reducer = st.selectbox(
1530
+ "Select a reducer for aggregating data:",
1531
+ ["median", "mean", "min", "max", "sum", "variance", "stdDev"],
1532
+ index=0,
1533
+ )
1534
+
1535
+ vis_params = st.text_area(
1536
+ "Enter visualization parameters",
1537
+ "",
1538
+ help="Enter a string in the format of a dictionary, such as '{'min': 23, 'max': 32}'",
1539
+ )
1540
+
1541
+ speed = st.slider("Frames per second:", 1, 30, 5)
1542
+ add_progress_bar = st.checkbox("Add a progress bar", True)
1543
+ progress_bar_color = st.color_picker(
1544
+ "Progress bar color:", "#0000ff"
1545
+ )
1546
+ font_size = st.slider("Font size:", 10, 50, 30)
1547
+ font_color = st.color_picker("Font color:", "#ffffff")
1548
+ font_type = st.selectbox(
1549
+ "Select the font type for the title:",
1550
+ ["arial.ttf", "alibaba.otf"],
1551
+ index=0,
1552
+ )
1553
+ add_colorbar = st.checkbox("Add a colorbar", True)
1554
+ colorbar_label = st.text_input(
1555
+ "Enter the colorbar label:", "Surface Temperature (°C)"
1556
+ )
1557
+ fading = st.slider(
1558
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1559
+ )
1560
+ mp4 = st.checkbox("Save timelapse as MP4", True)
1561
+
1562
+ empty_text = st.empty()
1563
+ empty_image = st.empty()
1564
+ empty_video = st.container()
1565
+
1566
+ roi = None
1567
+ if st.session_state.get("roi") is not None:
1568
+ roi = st.session_state.get("roi")
1569
+ out_gif = geemap.temp_file_path(".gif")
1570
+
1571
+ submitted = st.form_submit_button("Submit")
1572
+ if submitted:
1573
+
1574
+ if sample_roi == "Uploaded GeoJSON" and data is None:
1575
+ empty_text.warning(
1576
+ "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."
1577
+ )
1578
+ else:
1579
+
1580
+ empty_text.text("Computing... Please wait...")
1581
+ try:
1582
+ if (
1583
+ collection
1584
+ == "MODIS Gap filled Land Surface Temperature Daily"
1585
+ ):
1586
+ out_gif = geemap.create_timelapse(
1587
+ st.session_state.get("ee_asset_id"),
1588
+ start_date=start_date.strftime("%Y-%m-%d"),
1589
+ end_date=end_date.strftime("%Y-%m-%d"),
1590
+ region=roi,
1591
+ bands=None,
1592
+ frequency=frequency,
1593
+ reducer=reducer,
1594
+ date_format=None,
1595
+ out_gif=out_gif,
1596
+ palette=st.session_state.get("palette"),
1597
+ vis_params=None,
1598
+ dimensions=768,
1599
+ frames_per_second=speed,
1600
+ crs="EPSG:3857",
1601
+ overlay_data=overlay_data,
1602
+ overlay_color=overlay_color,
1603
+ overlay_width=overlay_width,
1604
+ overlay_opacity=overlay_opacity,
1605
+ title=title,
1606
+ title_xy=("2%", "90%"),
1607
+ add_text=True,
1608
+ text_xy=("2%", "2%"),
1609
+ text_sequence=None,
1610
+ font_type=font_type,
1611
+ font_size=font_size,
1612
+ font_color=font_color,
1613
+ add_progress_bar=add_progress_bar,
1614
+ progress_bar_color=progress_bar_color,
1615
+ progress_bar_height=5,
1616
+ add_colorbar=add_colorbar,
1617
+ colorbar_label=colorbar_label,
1618
+ loop=0,
1619
+ mp4=mp4,
1620
+ fading=fading,
1621
+ )
1622
+ elif collection == "MODIS Ocean Color SMI":
1623
+ if vis_params.startswith("{") and vis_params.endswith(
1624
+ "}"
1625
+ ):
1626
+ vis_params = json.loads(
1627
+ vis_params.replace("'", '"')
1628
+ )
1629
+ else:
1630
+ vis_params = None
1631
+ out_gif = geemap.modis_ocean_color_timelapse(
1632
+ st.session_state.get("ee_asset_id"),
1633
+ start_date=start_date.strftime("%Y-%m-%d"),
1634
+ end_date=end_date.strftime("%Y-%m-%d"),
1635
+ region=roi,
1636
+ bands=st.session_state["band"],
1637
+ frequency=frequency,
1638
+ reducer=reducer,
1639
+ date_format=None,
1640
+ out_gif=out_gif,
1641
+ palette=st.session_state.get("palette"),
1642
+ vis_params=vis_params,
1643
+ dimensions=768,
1644
+ frames_per_second=speed,
1645
+ crs="EPSG:3857",
1646
+ overlay_data=overlay_data,
1647
+ overlay_color=overlay_color,
1648
+ overlay_width=overlay_width,
1649
+ overlay_opacity=overlay_opacity,
1650
+ title=title,
1651
+ title_xy=("2%", "90%"),
1652
+ add_text=True,
1653
+ text_xy=("2%", "2%"),
1654
+ text_sequence=None,
1655
+ font_type=font_type,
1656
+ font_size=font_size,
1657
+ font_color=font_color,
1658
+ add_progress_bar=add_progress_bar,
1659
+ progress_bar_color=progress_bar_color,
1660
+ progress_bar_height=5,
1661
+ add_colorbar=add_colorbar,
1662
+ colorbar_label=colorbar_label,
1663
+ loop=0,
1664
+ mp4=mp4,
1665
+ fading=fading,
1666
+ )
1667
+ except:
1668
+ empty_text.error(
1669
+ "Something went wrong. You probably requested too much data. Try reducing the ROI or timespan."
1670
+ )
1671
+
1672
+ if out_gif is not None and os.path.exists(out_gif):
1673
+
1674
+ geemap.reduce_gif_size(out_gif)
1675
+
1676
+ empty_text.text(
1677
+ "Right click the GIF to save it to your computer👇"
1678
+ )
1679
+ empty_image.image(out_gif)
1680
+
1681
+ out_mp4 = out_gif.replace(".gif", ".mp4")
1682
+ if mp4 and os.path.exists(out_mp4):
1683
+ with empty_video:
1684
+ st.text(
1685
+ "Right click the MP4 to save it to your computer👇"
1686
+ )
1687
+ st.video(out_gif.replace(".gif", ".mp4"))
1688
+
1689
+ else:
1690
+ st.error(
1691
+ "Something went wrong. You probably requested too much data. Try reducing the ROI or timespan."
1692
+ )
1693
+
1694
+ elif collection == "USDA National Agriculture Imagery Program (NAIP)":
1695
+
1696
+ with st.form("submit_naip_form"):
1697
+ with st.expander("Customize timelapse"):
1698
+
1699
+ title = st.text_input(
1700
+ "Enter a title to show on the timelapse: ", "NAIP Timelapse"
1701
+ )
1702
+
1703
+ years = st.slider(
1704
+ "Start and end year:",
1705
+ 2003,
1706
+ today.year,
1707
+ (2003, today.year),
1708
+ )
1709
+
1710
+ bands = st.selectbox(
1711
+ "Select a band combination:", ["N/R/G", "R/G/B"], index=0
1712
+ )
1713
+
1714
+ speed = st.slider("Frames per second:", 1, 30, 3)
1715
+ add_progress_bar = st.checkbox("Add a progress bar", True)
1716
+ progress_bar_color = st.color_picker(
1717
+ "Progress bar color:", "#0000ff"
1718
+ )
1719
+ font_size = st.slider("Font size:", 10, 50, 30)
1720
+ font_color = st.color_picker("Font color:", "#ffffff")
1721
+ font_type = st.selectbox(
1722
+ "Select the font type for the title:",
1723
+ ["arial.ttf", "alibaba.otf"],
1724
+ index=0,
1725
+ )
1726
+ fading = st.slider(
1727
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1728
+ )
1729
+ mp4 = st.checkbox("Save timelapse as MP4", True)
1730
+
1731
+ empty_text = st.empty()
1732
+ empty_image = st.empty()
1733
+ empty_video = st.container()
1734
+ empty_fire_image = st.empty()
1735
+
1736
+ roi = None
1737
+ if st.session_state.get("roi") is not None:
1738
+ roi = st.session_state.get("roi")
1739
+ out_gif = geemap.temp_file_path(".gif")
1740
+
1741
+ submitted = st.form_submit_button("Submit")
1742
+ if submitted:
1743
+
1744
+ if sample_roi == "Uploaded GeoJSON" and data is None:
1745
+ empty_text.warning(
1746
+ "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."
1747
+ )
1748
+ else:
1749
+
1750
+ empty_text.text("Computing... Please wait...")
1751
+ try:
1752
+ geemap.naip_timelapse(
1753
+ roi,
1754
+ years[0],
1755
+ years[1],
1756
+ out_gif,
1757
+ bands=bands.split("/"),
1758
+ palette=st.session_state.get("palette"),
1759
+ vis_params=None,
1760
+ dimensions=768,
1761
+ frames_per_second=speed,
1762
+ crs="EPSG:3857",
1763
+ overlay_data=overlay_data,
1764
+ overlay_color=overlay_color,
1765
+ overlay_width=overlay_width,
1766
+ overlay_opacity=overlay_opacity,
1767
+ title=title,
1768
+ title_xy=("2%", "90%"),
1769
+ add_text=True,
1770
+ text_xy=("2%", "2%"),
1771
+ text_sequence=None,
1772
+ font_type=font_type,
1773
+ font_size=font_size,
1774
+ font_color=font_color,
1775
+ add_progress_bar=add_progress_bar,
1776
+ progress_bar_color=progress_bar_color,
1777
+ progress_bar_height=5,
1778
+ loop=0,
1779
+ mp4=mp4,
1780
+ fading=fading,
1781
+ )
1782
+ except:
1783
+ empty_text.error(
1784
+ "Something went wrong. You either requested too much data or the ROI is outside the U.S."
1785
+ )
1786
+
1787
+ if out_gif is not None and os.path.exists(out_gif):
1788
+
1789
+ empty_text.text(
1790
+ "Right click the GIF to save it to your computer👇"
1791
+ )
1792
+ empty_image.image(out_gif)
1793
+
1794
+ out_mp4 = out_gif.replace(".gif", ".mp4")
1795
+ if mp4 and os.path.exists(out_mp4):
1796
+ with empty_video:
1797
+ st.text(
1798
+ "Right click the MP4 to save it to your computer👇"
1799
+ )
1800
+ st.video(out_gif.replace(".gif", ".mp4"))
1801
+
1802
+ else:
1803
+ st.error(
1804
+ "Something went wrong. You either requested too much data or the ROI is outside the U.S."
1805
+ )
1806
+
1807
+ #<----------------------------------------------------------------base map code for calling in home page(Navigation purpose)---------------------------------------------------------------->
1808
+
1809
+ def basemap_page():
1810
+ st.title("Search Basemaps")
1811
+ base_map()
1812
+
1813
+
1814
+ #<----------------------------------------------------------------basemap code------------------------------------------------------------------------------------------------------>
1815
+
1816
+ def base_map():
1817
+ st.markdown(
1818
+ """
1819
+ This app is a demonstration of searching and loading basemaps from [xyzservices](https://github.com/geopandas/xyzservices) and [Quick Map Services (QMS)](https://github.com/nextgis/quickmapservices). Selecting from 1000+ basemaps with a few clicks.
1820
+ """
1821
+ )
1822
+
1823
+ with st.expander("See demo"):
1824
+ st.image("https://i.imgur.com/0SkUhZh.gif")
1825
+
1826
+ row1_col1, row1_col2 = st.columns([3, 1])
1827
+ width = 800
1828
+ height = 600
1829
+ tiles = None
1830
+
1831
+ with row1_col2:
1832
+
1833
+ checkbox = st.checkbox("Search Quick Map Services (QMS)")
1834
+ keyword = st.text_input("Enter a keyword to search and press Enter:")
1835
+ empty = st.empty()
1836
+
1837
+ if keyword:
1838
+ options = leafmap.search_xyz_services(keyword=keyword)
1839
+ if checkbox:
1840
+ qms = leafmap.search_qms(keyword=keyword)
1841
+ if qms is not None:
1842
+ options = options + qms
1843
+
1844
+ tiles = empty.multiselect("Select XYZ tiles to add to the map:", options)
1845
+
1846
+ with row1_col1:
1847
+ m = leafmap.Map()
1848
+
1849
+ if tiles is not None:
1850
+ for tile in tiles:
1851
+ m.add_xyz_service(tile)
1852
+
1853
+ m.to_streamlit(height=height)
1854
+
1855
+
1856
+ #<-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->
1857
+
1858
+
1859
+ # Create a dictionary of pages
1860
+ pages = {
1861
+ "Home": page_home,
1862
+ "About": page_about,
1863
+ "Interactive Map": interactive_map_page,
1864
+ "Timelapse": Timelapse_page, # Placeholder for Timelapse page function
1865
+ "Basemap": basemap_page,
1866
+ }
1867
+
1868
+ # Add a sidebar for navigation
1869
+ st.sidebar.title("Navigation")
1870
+ selection = st.sidebar.radio("Go to", list(pages.keys()))
1871
+
1872
+ # Call the function of the selected page
1873
+ page = pages[selection]
1874
+ page()
Interactive_Map.py ADDED
@@ -0,0 +1,224 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import folium
3
+ import geopandas as gpd
4
+ import json
5
+ import geemap.foliumap as geemap
6
+ import ee
7
+ import pandas as pd
8
+ import os
9
+ from google.auth.transport.requests import Request
10
+ import google.auth.exceptions
11
+ from streamlit.components.v1 import html
12
+
13
+ # Path to your shapefiles and service account key
14
+ SHAPEFILE_DIR = 'C:/Users/piv/Desktop/y/media/shp'
15
+
16
+ def initialize_gee():
17
+ service = os.getenv('SA')
18
+ file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'gee', 'ee-muzzamil1-37ebc3dece52.json')
19
+ credentials = ee.ServiceAccountCredentials(service, file)
20
+ try:
21
+ ee.Initialize(credentials)
22
+ st.success("Google Earth Engine initialized successfully.")
23
+ except google.auth.exceptions.RefreshError:
24
+ try:
25
+ request = Request()
26
+ credentials.refresh(request)
27
+ ee.Initialize(credentials)
28
+ st.success("Google Earth Engine token refreshed and initialized successfully.")
29
+ except Exception as e:
30
+ st.error(f"Error refreshing Google Earth Engine token: {e}")
31
+ except Exception as e:
32
+ st.error(f"Error initializing Google Earth Engine: {e}")
33
+
34
+ def create_folium_map(selected_dataset, ee_object, start_date_str, end_date_str):
35
+ folium_map = folium.Map(location=[25.5973518, 65.54495724], zoom_start=7)
36
+
37
+ try:
38
+ if selected_dataset == "Modis":
39
+ dataset = ee.ImageCollection('MODIS/006/MOD13Q1') \
40
+ .filter(ee.Filter.date(start_date_str, end_date_str)) \
41
+ .filterBounds(ee_object)
42
+
43
+ def clip_image(img):
44
+ return img.clip(ee_object).select('NDVI')
45
+
46
+ clipped_collection = dataset.map(clip_image)
47
+ modis_ndvi = clipped_collection.mean()
48
+ vis_params_ndvi = {
49
+ 'min': 0,
50
+ 'max': 9000,
51
+ 'palette': ['FE8374', 'C0E5DE', '3A837C', '034B48']
52
+ }
53
+ modis_ndvi_map_id = modis_ndvi.getMapId(vis_params_ndvi)
54
+ folium.TileLayer(
55
+ tiles=modis_ndvi_map_id['tile_fetcher'].url_format,
56
+ attr='Google Earth Engine',
57
+ name='NDVI',
58
+ overlay=True,
59
+ control=True
60
+ ).add_to(folium_map)
61
+
62
+ elif selected_dataset == "dataset_nighttime":
63
+ dataset_nighttime = ee.ImageCollection('NOAA/VIIRS/DNB/MONTHLY_V1/VCMCFG') \
64
+ .filter(ee.Filter.date(start_date_str, end_date_str))
65
+
66
+ nighttime = dataset_nighttime.select('avg_rad').mosaic()
67
+ nighttime_clipped = nighttime.clip(ee_object)
68
+ nighttime_vis = {
69
+ 'min': 0.0,
70
+ 'max': 60.0,
71
+ 'palette': ['1a3678', '2955bc', '5699ff', '8dbae9', 'acd1ff', 'caebff', 'e5f9ff', 'fdffb4', 'ffe6a2', 'ffc969', 'ffa12d', 'ff7c1f', 'ca531a', 'ff0000', 'ab0000']
72
+ }
73
+ nighttime_map_id = nighttime_clipped.getMapId(nighttime_vis)
74
+ folium.TileLayer(
75
+ tiles=nighttime_map_id['tile_fetcher'].url_format,
76
+ attr='Google Earth Engine',
77
+ name='Nighttime Lights',
78
+ overlay=True,
79
+ control=True
80
+ ).add_to(folium_map)
81
+
82
+ elif selected_dataset == "precipitation":
83
+ dataset_precipitation = ee.ImageCollection('UCSB-CHG/CHIRPS/DAILY') \
84
+ .filter(ee.Filter.date(start_date_str, end_date_str))
85
+
86
+ precipitation = dataset_precipitation.mosaic().clip(ee_object)
87
+ precip_vis = {
88
+ 'min': 0,
89
+ 'max': 300,
90
+ 'palette': ['blue', 'cyan', 'lime', 'yellow', 'red']
91
+ }
92
+ precip_map_id = precipitation.getMapId(precip_vis)
93
+ folium.TileLayer(
94
+ tiles=precip_map_id['tile_fetcher'].url_format,
95
+ attr='Google Earth Engine',
96
+ name='Precipitation',
97
+ overlay=True,
98
+ control=True
99
+ ).add_to(folium_map)
100
+
101
+ elif selected_dataset == "GlobalSurfaceWater":
102
+ st.warning("GlobalSurfaceWater dataset is not configured.")
103
+
104
+ elif selected_dataset == "WorldPop":
105
+ dataset = ee.ImageCollection('WorldPop/GP/100m/pop') \
106
+ .filterBounds(ee_object) \
107
+ .filter(ee.Filter.date(start_date_str, end_date_str))
108
+
109
+ population = dataset.mean().clip(ee_object)
110
+ pop_vis = {
111
+ 'min': 0,
112
+ 'max': 1000,
113
+ 'palette': ['blue', 'green', 'yellow', 'red']
114
+ }
115
+ pop_map_id = population.getMapId(pop_vis)
116
+ folium.TileLayer(
117
+ tiles=pop_map_id['tile_fetcher'].url_format,
118
+ attr='Google Earth Engine',
119
+ name='World Population',
120
+ overlay=True,
121
+ control=True
122
+ ).add_to(folium_map)
123
+
124
+ elif selected_dataset == "COPERNICUS":
125
+ dataset = ee.ImageCollection('COPERNICUS/S2') \
126
+ .filterBounds(ee_object) \
127
+ .filter(ee.Filter.date(start_date_str, end_date_str))
128
+
129
+ sentinel = dataset.median().clip(ee_object)
130
+ vis_params = {
131
+ 'bands': ['B4', 'B3', 'B2'],
132
+ 'min': 0,
133
+ 'max': 3000,
134
+ 'gamma': 1.4
135
+ }
136
+ copernicus_map_id = sentinel.getMapId(vis_params)
137
+ folium.TileLayer(
138
+ tiles=copernicus_map_id['tile_fetcher'].url_format,
139
+ attr='Google Earth Engine',
140
+ name='Copernicus Sentinel-2',
141
+ overlay=True,
142
+ control=True
143
+ ).add_to(folium_map)
144
+
145
+ folium_map.add_child(folium.LayerControl())
146
+ except Exception as e:
147
+ st.error(f"Error processing dataset: {e}")
148
+
149
+ folium_map_html = folium_map._repr_html_()
150
+ return folium_map_html
151
+
152
+ def handle_submit(selected_dataset, selected_date_range_From, selected_date_range_To, selected_shape):
153
+ shapefile_name = f'{selected_shape}.shp'
154
+ shapefile_path = os.path.join(SHAPEFILE_DIR, shapefile_name)
155
+
156
+ if os.path.exists(shapefile_path):
157
+ try:
158
+ roi_gdf = gpd.read_file(shapefile_path)
159
+ roi_geojson = roi_gdf.to_crs("EPSG:4326").to_json()
160
+ except Exception as e:
161
+ st.error(f"Error reading shapefile: {e}")
162
+ return
163
+
164
+ try:
165
+ ee_object = geemap.geojson_to_ee(json.loads(roi_geojson))
166
+ except Exception as e:
167
+ st.error(f"Error converting GeoJSON to Earth Engine object: {e}")
168
+ return
169
+
170
+ st.markdown("### Satellite Data Map")
171
+ folium_map_html = create_folium_map(
172
+ selected_dataset,
173
+ ee_object,
174
+ selected_date_range_From.strftime('%Y-%m-%d'),
175
+ selected_date_range_To.strftime('%Y-%m-%d')
176
+ )
177
+ html(folium_map_html, height=600)
178
+ else:
179
+ st.error("Selected shapefile does not exist.")
180
+
181
+ def submit_control():
182
+ selected_dataset = st.sidebar.selectbox(
183
+ "Select Dataset",
184
+ ["Modis", "dataset_nighttime", 'precipitation', 'GlobalSurfaceWater', 'WorldPop', 'COPERNICUS']
185
+ )
186
+
187
+ selected_date_range_From = st.sidebar.date_input("From", value=pd.to_datetime("2015-07-01"))
188
+ selected_date_range_To = st.sidebar.date_input("To", value=pd.to_datetime("2023-09-30"))
189
+
190
+ shape_options = [
191
+ 'District_Boundary', 'hydro_basins', 'karachi',
192
+ 'National_Constituency_with_Projected_2010_Population',
193
+ 'Provincial_Boundary', 'Provincial_Constituency',
194
+ 'Tehsil_Boundary', 'Union_Council'
195
+ ]
196
+
197
+ selected_shape = st.sidebar.selectbox("Select Shape", shape_options)
198
+
199
+ if st.sidebar.button("Submit"):
200
+ st.session_state.selected_dataset = selected_dataset
201
+ st.session_state.selected_date_range_From = selected_date_range_From
202
+ st.session_state.selected_date_range_To = selected_date_range_To
203
+ st.session_state.selected_shape = selected_shape
204
+ st.session_state.submitted = True
205
+ else:
206
+ st.session_state.submitted = False
207
+
208
+ if 'submitted' in st.session_state and st.session_state.submitted:
209
+ handle_submit(
210
+ st.session_state.selected_dataset,
211
+ st.session_state.selected_date_range_From,
212
+ st.session_state.selected_date_range_To,
213
+ st.session_state.selected_shape
214
+ )
215
+
216
+ def main():
217
+ st.set_page_config(layout="wide")
218
+ st.title("Satellite Data Visualization, Interactive Map")
219
+
220
+ initialize_gee()
221
+ submit_control()
222
+
223
+ if __name__ == "__main__":
224
+ main()
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2020 bikesh bade
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
Timelapse.py ADDED
@@ -0,0 +1,1539 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ def Timelapse_map():
16
+ st.title("Timelapse Page")
17
+ st.write("Content of the Timelapse Page.")
18
+ # Additional code for the Timelapse functionality
19
+
20
+ st.set_page_config(layout="wide")
21
+ warnings.filterwarnings("ignore")
22
+
23
+
24
+ @st.cache_data
25
+ def ee_authenticate(token_name="EARTHENGINE_TOKEN"):
26
+ geemap.ee_initialize(token_name=token_name)
27
+
28
+
29
+ st.sidebar.info(
30
+ """
31
+ - Web App URL: <https://streamlit.gishub.org>
32
+ - GitHub repository: <https://github.com/giswqs/streamlit-geospatial>
33
+ """
34
+ )
35
+
36
+ st.sidebar.title("Contact")
37
+ st.sidebar.info(
38
+ """
39
+ 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)
40
+ """
41
+ )
42
+
43
+ goes_rois = {
44
+ "Creek Fire, CA (2020-09-05)": {
45
+ "region": Polygon(
46
+ [
47
+ [-121.003418, 36.848857],
48
+ [-121.003418, 39.049052],
49
+ [-117.905273, 39.049052],
50
+ [-117.905273, 36.848857],
51
+ [-121.003418, 36.848857],
52
+ ]
53
+ ),
54
+ "start_time": "2020-09-05T15:00:00",
55
+ "end_time": "2020-09-06T02:00:00",
56
+ },
57
+ "Bomb Cyclone (2021-10-24)": {
58
+ "region": Polygon(
59
+ [
60
+ [-159.5954, 60.4088],
61
+ [-159.5954, 24.5178],
62
+ [-114.2438, 24.5178],
63
+ [-114.2438, 60.4088],
64
+ ]
65
+ ),
66
+ "start_time": "2021-10-24T14:00:00",
67
+ "end_time": "2021-10-25T01:00:00",
68
+ },
69
+ "Hunga Tonga Volcanic Eruption (2022-01-15)": {
70
+ "region": Polygon(
71
+ [
72
+ [-192.480469, -32.546813],
73
+ [-192.480469, -8.754795],
74
+ [-157.587891, -8.754795],
75
+ [-157.587891, -32.546813],
76
+ [-192.480469, -32.546813],
77
+ ]
78
+ ),
79
+ "start_time": "2022-01-15T03:00:00",
80
+ "end_time": "2022-01-15T07:00:00",
81
+ },
82
+ "Hunga Tonga Volcanic Eruption Closer Look (2022-01-15)": {
83
+ "region": Polygon(
84
+ [
85
+ [-178.901367, -22.958393],
86
+ [-178.901367, -17.85329],
87
+ [-171.452637, -17.85329],
88
+ [-171.452637, -22.958393],
89
+ [-178.901367, -22.958393],
90
+ ]
91
+ ),
92
+ "start_time": "2022-01-15T03:00:00",
93
+ "end_time": "2022-01-15T07:00:00",
94
+ },
95
+ }
96
+
97
+
98
+ landsat_rois = {
99
+ "Aral Sea": Polygon(
100
+ [
101
+ [57.667236, 43.834527],
102
+ [57.667236, 45.996962],
103
+ [61.12793, 45.996962],
104
+ [61.12793, 43.834527],
105
+ [57.667236, 43.834527],
106
+ ]
107
+ ),
108
+ "Dubai": Polygon(
109
+ [
110
+ [54.541626, 24.763044],
111
+ [54.541626, 25.427152],
112
+ [55.632019, 25.427152],
113
+ [55.632019, 24.763044],
114
+ [54.541626, 24.763044],
115
+ ]
116
+ ),
117
+ "Hong Kong International Airport": Polygon(
118
+ [
119
+ [113.825226, 22.198849],
120
+ [113.825226, 22.349758],
121
+ [114.085121, 22.349758],
122
+ [114.085121, 22.198849],
123
+ [113.825226, 22.198849],
124
+ ]
125
+ ),
126
+ "Las Vegas, NV": Polygon(
127
+ [
128
+ [-115.554199, 35.804449],
129
+ [-115.554199, 36.558188],
130
+ [-113.903503, 36.558188],
131
+ [-113.903503, 35.804449],
132
+ [-115.554199, 35.804449],
133
+ ]
134
+ ),
135
+ "Pucallpa, Peru": Polygon(
136
+ [
137
+ [-74.672699, -8.600032],
138
+ [-74.672699, -8.254983],
139
+ [-74.279938, -8.254983],
140
+ [-74.279938, -8.600032],
141
+ ]
142
+ ),
143
+ "Sierra Gorda, Chile": Polygon(
144
+ [
145
+ [-69.315491, -22.837104],
146
+ [-69.315491, -22.751488],
147
+ [-69.190006, -22.751488],
148
+ [-69.190006, -22.837104],
149
+ [-69.315491, -22.837104],
150
+ ]
151
+ ),
152
+ }
153
+
154
+ modis_rois = {
155
+ "World": Polygon(
156
+ [
157
+ [-171.210938, -57.136239],
158
+ [-171.210938, 79.997168],
159
+ [177.539063, 79.997168],
160
+ [177.539063, -57.136239],
161
+ [-171.210938, -57.136239],
162
+ ]
163
+ ),
164
+ "Africa": Polygon(
165
+ [
166
+ [-18.6983, 38.1446],
167
+ [-18.6983, -36.1630],
168
+ [52.2293, -36.1630],
169
+ [52.2293, 38.1446],
170
+ ]
171
+ ),
172
+ "USA": Polygon(
173
+ [
174
+ [-127.177734, 23.725012],
175
+ [-127.177734, 50.792047],
176
+ [-66.269531, 50.792047],
177
+ [-66.269531, 23.725012],
178
+ [-127.177734, 23.725012],
179
+ ]
180
+ ),
181
+ }
182
+
183
+ ocean_rois = {
184
+ "Gulf of Mexico": Polygon(
185
+ [
186
+ [-101.206055, 15.496032],
187
+ [-101.206055, 32.361403],
188
+ [-75.673828, 32.361403],
189
+ [-75.673828, 15.496032],
190
+ [-101.206055, 15.496032],
191
+ ]
192
+ ),
193
+ "North Atlantic Ocean": Polygon(
194
+ [
195
+ [-85.341797, 24.046464],
196
+ [-85.341797, 45.02695],
197
+ [-55.810547, 45.02695],
198
+ [-55.810547, 24.046464],
199
+ [-85.341797, 24.046464],
200
+ ]
201
+ ),
202
+ "World": Polygon(
203
+ [
204
+ [-171.210938, -57.136239],
205
+ [-171.210938, 79.997168],
206
+ [177.539063, 79.997168],
207
+ [177.539063, -57.136239],
208
+ [-171.210938, -57.136239],
209
+ ]
210
+ ),
211
+ }
212
+
213
+
214
+ @st.cache_data
215
+ def uploaded_file_to_gdf(data):
216
+ import tempfile
217
+ import os
218
+ import uuid
219
+
220
+ _, file_extension = os.path.splitext(data.name)
221
+ file_id = str(uuid.uuid4())
222
+ file_path = os.path.join(tempfile.gettempdir(), f"{file_id}{file_extension}")
223
+
224
+ with open(file_path, "wb") as file:
225
+ file.write(data.getbuffer())
226
+
227
+ if file_path.lower().endswith(".kml"):
228
+ fiona.drvsupport.supported_drivers["KML"] = "rw"
229
+ gdf = gpd.read_file(file_path, driver="KML")
230
+ else:
231
+ gdf = gpd.read_file(file_path)
232
+
233
+ return gdf
234
+
235
+
236
+ def app():
237
+
238
+ today = date.today()
239
+
240
+ st.title("Create Satellite Timelapse")
241
+
242
+ st.markdown(
243
+ """
244
+ 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.
245
+ 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).
246
+ """
247
+ )
248
+
249
+ row1_col1, row1_col2 = st.columns([2, 1])
250
+
251
+ if st.session_state.get("zoom_level") is None:
252
+ st.session_state["zoom_level"] = 4
253
+
254
+ st.session_state["ee_asset_id"] = None
255
+ st.session_state["bands"] = None
256
+ st.session_state["palette"] = None
257
+ st.session_state["vis_params"] = None
258
+
259
+ with row1_col1:
260
+ ee_authenticate(token_name="EARTHENGINE_TOKEN")
261
+ m = geemap.Map(
262
+ basemap="HYBRID",
263
+ plugin_Draw=True,
264
+ Draw_export=True,
265
+ locate_control=True,
266
+ plugin_LatLngPopup=False,
267
+ )
268
+ m.add_basemap("ROADMAP")
269
+
270
+ with row1_col2:
271
+
272
+ keyword = st.text_input("Search for a location:", "")
273
+ if keyword:
274
+ locations = geemap.geocode(keyword)
275
+ if locations is not None and len(locations) > 0:
276
+ str_locations = [str(g)[1:-1] for g in locations]
277
+ location = st.selectbox("Select a location:", str_locations)
278
+ loc_index = str_locations.index(location)
279
+ selected_loc = locations[loc_index]
280
+ lat, lng = selected_loc.lat, selected_loc.lng
281
+ folium.Marker(location=[lat, lng], popup=location).add_to(m)
282
+ m.set_center(lng, lat, 12)
283
+ st.session_state["zoom_level"] = 12
284
+
285
+ collection = st.selectbox(
286
+ "Select a satellite image collection: ",
287
+ [
288
+ "Any Earth Engine ImageCollection",
289
+ "Landsat TM-ETM-OLI Surface Reflectance",
290
+ "Sentinel-2 MSI Surface Reflectance",
291
+ "Geostationary Operational Environmental Satellites (GOES)",
292
+ "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km",
293
+ "MODIS Gap filled Land Surface Temperature Daily",
294
+ "MODIS Ocean Color SMI",
295
+ "USDA National Agriculture Imagery Program (NAIP)",
296
+ ],
297
+ index=1,
298
+ )
299
+
300
+ if collection in [
301
+ "Landsat TM-ETM-OLI Surface Reflectance",
302
+ "Sentinel-2 MSI Surface Reflectance",
303
+ ]:
304
+ roi_options = ["Uploaded GeoJSON"] + list(landsat_rois.keys())
305
+
306
+ elif collection == "Geostationary Operational Environmental Satellites (GOES)":
307
+ roi_options = ["Uploaded GeoJSON"] + list(goes_rois.keys())
308
+
309
+ elif collection in [
310
+ "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km",
311
+ "MODIS Gap filled Land Surface Temperature Daily",
312
+ ]:
313
+ roi_options = ["Uploaded GeoJSON"] + list(modis_rois.keys())
314
+ elif collection == "MODIS Ocean Color SMI":
315
+ roi_options = ["Uploaded GeoJSON"] + list(ocean_rois.keys())
316
+ else:
317
+ roi_options = ["Uploaded GeoJSON"]
318
+
319
+ if collection == "Any Earth Engine ImageCollection":
320
+ keyword = st.text_input("Enter a keyword to search (e.g., MODIS):", "")
321
+ if keyword:
322
+
323
+ assets = geemap.search_ee_data(keyword)
324
+ ee_assets = []
325
+ for asset in assets:
326
+ if asset["ee_id_snippet"].startswith("ee.ImageCollection"):
327
+ ee_assets.append(asset)
328
+
329
+ asset_titles = [x["title"] for x in ee_assets]
330
+ dataset = st.selectbox("Select a dataset:", asset_titles)
331
+ if len(ee_assets) > 0:
332
+ st.session_state["ee_assets"] = ee_assets
333
+ st.session_state["asset_titles"] = asset_titles
334
+ index = asset_titles.index(dataset)
335
+ ee_id = ee_assets[index]["id"]
336
+ else:
337
+ ee_id = ""
338
+
339
+ if dataset is not None:
340
+ with st.expander("Show dataset details", False):
341
+ index = asset_titles.index(dataset)
342
+ html = geemap.ee_data_html(st.session_state["ee_assets"][index])
343
+ st.markdown(html, True)
344
+ # elif collection == "MODIS Gap filled Land Surface Temperature Daily":
345
+ # ee_id = ""
346
+ else:
347
+ ee_id = ""
348
+
349
+ asset_id = st.text_input("Enter an ee.ImageCollection asset ID:", ee_id)
350
+
351
+ if asset_id:
352
+ with st.expander("Customize band combination and color palette", True):
353
+ try:
354
+ col = ee.ImageCollection.load(asset_id)
355
+ st.session_state["ee_asset_id"] = asset_id
356
+ except:
357
+ st.error("Invalid Earth Engine asset ID.")
358
+ st.session_state["ee_asset_id"] = None
359
+ return
360
+
361
+ img_bands = col.first().bandNames().getInfo()
362
+ if len(img_bands) >= 3:
363
+ default_bands = img_bands[:3][::-1]
364
+ else:
365
+ default_bands = img_bands[:]
366
+ bands = st.multiselect(
367
+ "Select one or three bands (RGB):", img_bands, default_bands
368
+ )
369
+ st.session_state["bands"] = bands
370
+
371
+ if len(bands) == 1:
372
+ palette_options = st.selectbox(
373
+ "Color palette",
374
+ cm.list_colormaps(),
375
+ index=2,
376
+ )
377
+ palette_values = cm.get_palette(palette_options, 15)
378
+ palette = st.text_area(
379
+ "Enter a custom palette:",
380
+ palette_values,
381
+ )
382
+ st.write(
383
+ cm.plot_colormap(cmap=palette_options, return_fig=True)
384
+ )
385
+ st.session_state["palette"] = json.loads(
386
+ palette.replace("'", '"')
387
+ )
388
+
389
+ if bands:
390
+ vis_params = st.text_area(
391
+ "Enter visualization parameters",
392
+ "{'bands': ["
393
+ + ", ".join([f"'{band}'" for band in bands])
394
+ + "]}",
395
+ )
396
+ else:
397
+ vis_params = st.text_area(
398
+ "Enter visualization parameters",
399
+ "{}",
400
+ )
401
+ try:
402
+ st.session_state["vis_params"] = json.loads(
403
+ vis_params.replace("'", '"')
404
+ )
405
+ st.session_state["vis_params"]["palette"] = st.session_state[
406
+ "palette"
407
+ ]
408
+ except Exception as e:
409
+ st.session_state["vis_params"] = None
410
+ st.error(
411
+ f"Invalid visualization parameters. It must be a dictionary."
412
+ )
413
+
414
+ elif collection == "MODIS Gap filled Land Surface Temperature Daily":
415
+ with st.expander("Show dataset details", False):
416
+ st.markdown(
417
+ """
418
+ See the [Awesome GEE Community Datasets](https://samapriya.github.io/awesome-gee-community-datasets/projects/daily_lst/).
419
+ """
420
+ )
421
+
422
+ MODIS_options = ["Daytime (1:30 pm)", "Nighttime (1:30 am)"]
423
+ MODIS_option = st.selectbox("Select a MODIS dataset:", MODIS_options)
424
+ if MODIS_option == "Daytime (1:30 pm)":
425
+ st.session_state["ee_asset_id"] = (
426
+ "projects/sat-io/open-datasets/gap-filled-lst/gf_day_1km"
427
+ )
428
+ else:
429
+ st.session_state["ee_asset_id"] = (
430
+ "projects/sat-io/open-datasets/gap-filled-lst/gf_night_1km"
431
+ )
432
+
433
+ palette_options = st.selectbox(
434
+ "Color palette",
435
+ cm.list_colormaps(),
436
+ index=90,
437
+ )
438
+ palette_values = cm.get_palette(palette_options, 15)
439
+ palette = st.text_area(
440
+ "Enter a custom palette:",
441
+ palette_values,
442
+ )
443
+ st.write(cm.plot_colormap(cmap=palette_options, return_fig=True))
444
+ st.session_state["palette"] = json.loads(palette.replace("'", '"'))
445
+ elif collection == "MODIS Ocean Color SMI":
446
+ with st.expander("Show dataset details", False):
447
+ st.markdown(
448
+ """
449
+ See the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog/NASA_OCEANDATA_MODIS-Aqua_L3SMI).
450
+ """
451
+ )
452
+
453
+ MODIS_options = ["Aqua", "Terra"]
454
+ MODIS_option = st.selectbox("Select a satellite:", MODIS_options)
455
+ st.session_state["ee_asset_id"] = MODIS_option
456
+ # if MODIS_option == "Daytime (1:30 pm)":
457
+ # st.session_state[
458
+ # "ee_asset_id"
459
+ # ] = "projects/sat-io/open-datasets/gap-filled-lst/gf_day_1km"
460
+ # else:
461
+ # st.session_state[
462
+ # "ee_asset_id"
463
+ # ] = "projects/sat-io/open-datasets/gap-filled-lst/gf_night_1km"
464
+
465
+ band_dict = {
466
+ "Chlorophyll a concentration": "chlor_a",
467
+ "Normalized fluorescence line height": "nflh",
468
+ "Particulate organic carbon": "poc",
469
+ "Sea surface temperature": "sst",
470
+ "Remote sensing reflectance at band 412nm": "Rrs_412",
471
+ "Remote sensing reflectance at band 443nm": "Rrs_443",
472
+ "Remote sensing reflectance at band 469nm": "Rrs_469",
473
+ "Remote sensing reflectance at band 488nm": "Rrs_488",
474
+ "Remote sensing reflectance at band 531nm": "Rrs_531",
475
+ "Remote sensing reflectance at band 547nm": "Rrs_547",
476
+ "Remote sensing reflectance at band 555nm": "Rrs_555",
477
+ "Remote sensing reflectance at band 645nm": "Rrs_645",
478
+ "Remote sensing reflectance at band 667nm": "Rrs_667",
479
+ "Remote sensing reflectance at band 678nm": "Rrs_678",
480
+ }
481
+
482
+ band_options = list(band_dict.keys())
483
+ band = st.selectbox(
484
+ "Select a band",
485
+ band_options,
486
+ band_options.index("Sea surface temperature"),
487
+ )
488
+ st.session_state["band"] = band_dict[band]
489
+
490
+ colors = cm.list_colormaps()
491
+ palette_options = st.selectbox(
492
+ "Color palette",
493
+ colors,
494
+ index=colors.index("coolwarm"),
495
+ )
496
+ palette_values = cm.get_palette(palette_options, 15)
497
+ palette = st.text_area(
498
+ "Enter a custom palette:",
499
+ palette_values,
500
+ )
501
+ st.write(cm.plot_colormap(cmap=palette_options, return_fig=True))
502
+ st.session_state["palette"] = json.loads(palette.replace("'", '"'))
503
+
504
+ sample_roi = st.selectbox(
505
+ "Select a sample ROI or upload a GeoJSON file:",
506
+ roi_options,
507
+ index=0,
508
+ )
509
+
510
+ add_outline = st.checkbox(
511
+ "Overlay an administrative boundary on timelapse", False
512
+ )
513
+
514
+ if add_outline:
515
+
516
+ with st.expander("Customize administrative boundary", True):
517
+
518
+ overlay_options = {
519
+ "User-defined": None,
520
+ "Continents": "continents",
521
+ "Countries": "countries",
522
+ "US States": "us_states",
523
+ "China": "china",
524
+ }
525
+
526
+ overlay = st.selectbox(
527
+ "Select an administrative boundary:",
528
+ list(overlay_options.keys()),
529
+ index=2,
530
+ )
531
+
532
+ overlay_data = overlay_options[overlay]
533
+
534
+ if overlay_data is None:
535
+ overlay_data = st.text_input(
536
+ "Enter an HTTP URL to a GeoJSON file or an ee.FeatureCollection asset id:",
537
+ "https://raw.githubusercontent.com/giswqs/geemap/master/examples/data/countries.geojson",
538
+ )
539
+
540
+ overlay_color = st.color_picker(
541
+ "Select a color for the administrative boundary:", "#000000"
542
+ )
543
+ overlay_width = st.slider(
544
+ "Select a line width for the administrative boundary:", 1, 20, 1
545
+ )
546
+ overlay_opacity = st.slider(
547
+ "Select an opacity for the administrative boundary:",
548
+ 0.0,
549
+ 1.0,
550
+ 1.0,
551
+ 0.05,
552
+ )
553
+ else:
554
+ overlay_data = None
555
+ overlay_color = "black"
556
+ overlay_width = 1
557
+ overlay_opacity = 1
558
+
559
+ with row1_col1:
560
+
561
+ with st.expander(
562
+ "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 👉"
563
+ ):
564
+ video_empty = st.empty()
565
+
566
+ data = st.file_uploader(
567
+ "Upload a GeoJSON file to use as an ROI. Customize timelapse parameters and then click the Submit button 😇👇",
568
+ type=["geojson", "kml", "zip"],
569
+ )
570
+
571
+ crs = "epsg:4326"
572
+ if sample_roi == "Uploaded GeoJSON":
573
+ if data is None:
574
+ # st.info(
575
+ # "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"
576
+ # )
577
+ if collection in [
578
+ "Geostationary Operational Environmental Satellites (GOES)",
579
+ "USDA National Agriculture Imagery Program (NAIP)",
580
+ ] and (not keyword):
581
+ m.set_center(-100, 40, 3)
582
+ # else:
583
+ # m.set_center(4.20, 18.63, zoom=2)
584
+ else:
585
+ if collection in [
586
+ "Landsat TM-ETM-OLI Surface Reflectance",
587
+ "Sentinel-2 MSI Surface Reflectance",
588
+ ]:
589
+ gdf = gpd.GeoDataFrame(
590
+ index=[0], crs=crs, geometry=[landsat_rois[sample_roi]]
591
+ )
592
+ elif (
593
+ collection
594
+ == "Geostationary Operational Environmental Satellites (GOES)"
595
+ ):
596
+ gdf = gpd.GeoDataFrame(
597
+ index=[0], crs=crs, geometry=[goes_rois[sample_roi]["region"]]
598
+ )
599
+ elif collection == "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km":
600
+ gdf = gpd.GeoDataFrame(
601
+ index=[0], crs=crs, geometry=[modis_rois[sample_roi]]
602
+ )
603
+
604
+ if sample_roi != "Uploaded GeoJSON":
605
+
606
+ if collection in [
607
+ "Landsat TM-ETM-OLI Surface Reflectance",
608
+ "Sentinel-2 MSI Surface Reflectance",
609
+ ]:
610
+ gdf = gpd.GeoDataFrame(
611
+ index=[0], crs=crs, geometry=[landsat_rois[sample_roi]]
612
+ )
613
+ elif (
614
+ collection
615
+ == "Geostationary Operational Environmental Satellites (GOES)"
616
+ ):
617
+ gdf = gpd.GeoDataFrame(
618
+ index=[0], crs=crs, geometry=[goes_rois[sample_roi]["region"]]
619
+ )
620
+ elif collection in [
621
+ "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km",
622
+ "MODIS Gap filled Land Surface Temperature Daily",
623
+ ]:
624
+ gdf = gpd.GeoDataFrame(
625
+ index=[0], crs=crs, geometry=[modis_rois[sample_roi]]
626
+ )
627
+ elif collection == "MODIS Ocean Color SMI":
628
+ gdf = gpd.GeoDataFrame(
629
+ index=[0], crs=crs, geometry=[ocean_rois[sample_roi]]
630
+ )
631
+ try:
632
+ st.session_state["roi"] = geemap.gdf_to_ee(gdf, geodesic=False)
633
+ except Exception as e:
634
+ st.error(e)
635
+ st.error("Please draw another ROI and try again.")
636
+ return
637
+ m.add_gdf(gdf, "ROI")
638
+
639
+ elif data:
640
+ gdf = uploaded_file_to_gdf(data)
641
+ try:
642
+ st.session_state["roi"] = geemap.gdf_to_ee(gdf, geodesic=False)
643
+ m.add_gdf(gdf, "ROI")
644
+ except Exception as e:
645
+ st.error(e)
646
+ st.error("Please draw another ROI and try again.")
647
+ return
648
+
649
+ m.to_streamlit(height=600)
650
+
651
+ with row1_col2:
652
+
653
+ if collection in [
654
+ "Landsat TM-ETM-OLI Surface Reflectance",
655
+ "Sentinel-2 MSI Surface Reflectance",
656
+ ]:
657
+
658
+ if collection == "Landsat TM-ETM-OLI Surface Reflectance":
659
+ sensor_start_year = 1984
660
+ timelapse_title = "Landsat Timelapse"
661
+ timelapse_speed = 5
662
+ elif collection == "Sentinel-2 MSI Surface Reflectance":
663
+ sensor_start_year = 2015
664
+ timelapse_title = "Sentinel-2 Timelapse"
665
+ timelapse_speed = 5
666
+ video_empty.video("https://youtu.be/VVRK_-dEjR4")
667
+
668
+ with st.form("submit_landsat_form"):
669
+
670
+ roi = None
671
+ if st.session_state.get("roi") is not None:
672
+ roi = st.session_state.get("roi")
673
+ out_gif = geemap.temp_file_path(".gif")
674
+
675
+ title = st.text_input(
676
+ "Enter a title to show on the timelapse: ", timelapse_title
677
+ )
678
+ RGB = st.selectbox(
679
+ "Select an RGB band combination:",
680
+ [
681
+ "Red/Green/Blue",
682
+ "NIR/Red/Green",
683
+ "SWIR2/SWIR1/NIR",
684
+ "NIR/SWIR1/Red",
685
+ "SWIR2/NIR/Red",
686
+ "SWIR2/SWIR1/Red",
687
+ "SWIR1/NIR/Blue",
688
+ "NIR/SWIR1/Blue",
689
+ "SWIR2/NIR/Green",
690
+ "SWIR1/NIR/Red",
691
+ "SWIR2/NIR/SWIR1",
692
+ "SWIR1/NIR/SWIR2",
693
+ ],
694
+ index=9,
695
+ )
696
+
697
+ frequency = st.selectbox(
698
+ "Select a temporal frequency:",
699
+ ["year", "quarter", "month"],
700
+ index=0,
701
+ )
702
+
703
+ with st.expander("Customize timelapse"):
704
+
705
+ speed = st.slider("Frames per second:", 1, 30, timelapse_speed)
706
+ dimensions = st.slider(
707
+ "Maximum dimensions (Width*Height) in pixels", 768, 2000, 768
708
+ )
709
+ progress_bar_color = st.color_picker(
710
+ "Progress bar color:", "#0000ff"
711
+ )
712
+ years = st.slider(
713
+ "Start and end year:",
714
+ sensor_start_year,
715
+ today.year,
716
+ (sensor_start_year, today.year),
717
+ )
718
+ months = st.slider("Start and end month:", 1, 12, (1, 12))
719
+ font_size = st.slider("Font size:", 10, 50, 30)
720
+ font_color = st.color_picker("Font color:", "#ffffff")
721
+ apply_fmask = st.checkbox(
722
+ "Apply fmask (remove clouds, shadows, snow)", True
723
+ )
724
+ font_type = st.selectbox(
725
+ "Select the font type for the title:",
726
+ ["arial.ttf", "alibaba.otf"],
727
+ index=0,
728
+ )
729
+ fading = st.slider(
730
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
731
+ )
732
+ mp4 = st.checkbox("Save timelapse as MP4", True)
733
+
734
+ empty_text = st.empty()
735
+ empty_image = st.empty()
736
+ empty_fire_image = st.empty()
737
+ empty_video = st.container()
738
+ submitted = st.form_submit_button("Submit")
739
+ if submitted:
740
+
741
+ if sample_roi == "Uploaded GeoJSON" and data is None:
742
+ empty_text.warning(
743
+ "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."
744
+ )
745
+ else:
746
+
747
+ empty_text.text("Computing... Please wait...")
748
+
749
+ start_year = years[0]
750
+ end_year = years[1]
751
+ start_date = str(months[0]).zfill(2) + "-01"
752
+ end_date = str(months[1]).zfill(2) + "-30"
753
+ bands = RGB.split("/")
754
+
755
+ try:
756
+ if collection == "Landsat TM-ETM-OLI Surface Reflectance":
757
+ out_gif = geemap.landsat_timelapse(
758
+ roi=roi,
759
+ out_gif=out_gif,
760
+ start_year=start_year,
761
+ end_year=end_year,
762
+ start_date=start_date,
763
+ end_date=end_date,
764
+ bands=bands,
765
+ apply_fmask=apply_fmask,
766
+ frames_per_second=speed,
767
+ # dimensions=dimensions,
768
+ dimensions=768,
769
+ overlay_data=overlay_data,
770
+ overlay_color=overlay_color,
771
+ overlay_width=overlay_width,
772
+ overlay_opacity=overlay_opacity,
773
+ frequency=frequency,
774
+ date_format=None,
775
+ title=title,
776
+ title_xy=("2%", "90%"),
777
+ add_text=True,
778
+ text_xy=("2%", "2%"),
779
+ text_sequence=None,
780
+ font_type=font_type,
781
+ font_size=font_size,
782
+ font_color=font_color,
783
+ add_progress_bar=True,
784
+ progress_bar_color=progress_bar_color,
785
+ progress_bar_height=5,
786
+ loop=0,
787
+ mp4=mp4,
788
+ fading=fading,
789
+ )
790
+ elif collection == "Sentinel-2 MSI Surface Reflectance":
791
+ out_gif = geemap.sentinel2_timelapse(
792
+ roi=roi,
793
+ out_gif=out_gif,
794
+ start_year=start_year,
795
+ end_year=end_year,
796
+ start_date=start_date,
797
+ end_date=end_date,
798
+ bands=bands,
799
+ apply_fmask=apply_fmask,
800
+ frames_per_second=speed,
801
+ dimensions=768,
802
+ # dimensions=dimensions,
803
+ overlay_data=overlay_data,
804
+ overlay_color=overlay_color,
805
+ overlay_width=overlay_width,
806
+ overlay_opacity=overlay_opacity,
807
+ frequency=frequency,
808
+ date_format=None,
809
+ title=title,
810
+ title_xy=("2%", "90%"),
811
+ add_text=True,
812
+ text_xy=("2%", "2%"),
813
+ text_sequence=None,
814
+ font_type=font_type,
815
+ font_size=font_size,
816
+ font_color=font_color,
817
+ add_progress_bar=True,
818
+ progress_bar_color=progress_bar_color,
819
+ progress_bar_height=5,
820
+ loop=0,
821
+ mp4=mp4,
822
+ fading=fading,
823
+ )
824
+ except:
825
+ empty_text.error(
826
+ "An error occurred while computing the timelapse. Your probably requested too much data. Try reducing the ROI or timespan."
827
+ )
828
+ st.stop()
829
+
830
+ if out_gif is not None and os.path.exists(out_gif):
831
+
832
+ empty_text.text(
833
+ "Right click the GIF to save it to your computer👇"
834
+ )
835
+ empty_image.image(out_gif)
836
+
837
+ out_mp4 = out_gif.replace(".gif", ".mp4")
838
+ if mp4 and os.path.exists(out_mp4):
839
+ with empty_video:
840
+ st.text(
841
+ "Right click the MP4 to save it to your computer👇"
842
+ )
843
+ st.video(out_gif.replace(".gif", ".mp4"))
844
+
845
+ else:
846
+ empty_text.error(
847
+ "Something went wrong. You probably requested too much data. Try reducing the ROI or timespan."
848
+ )
849
+
850
+ elif collection == "Geostationary Operational Environmental Satellites (GOES)":
851
+
852
+ video_empty.video("https://youtu.be/16fA2QORG4A")
853
+
854
+ with st.form("submit_goes_form"):
855
+
856
+ roi = None
857
+ if st.session_state.get("roi") is not None:
858
+ roi = st.session_state.get("roi")
859
+ out_gif = geemap.temp_file_path(".gif")
860
+
861
+ satellite = st.selectbox("Select a satellite:", ["GOES-17", "GOES-16"])
862
+ earliest_date = datetime.date(2017, 7, 10)
863
+ latest_date = datetime.date.today()
864
+
865
+ if sample_roi == "Uploaded GeoJSON":
866
+ roi_start_date = today - datetime.timedelta(days=2)
867
+ roi_end_date = today - datetime.timedelta(days=1)
868
+ roi_start_time = datetime.time(14, 00)
869
+ roi_end_time = datetime.time(1, 00)
870
+ else:
871
+ roi_start = goes_rois[sample_roi]["start_time"]
872
+ roi_end = goes_rois[sample_roi]["end_time"]
873
+ roi_start_date = datetime.datetime.strptime(
874
+ roi_start[:10], "%Y-%m-%d"
875
+ )
876
+ roi_end_date = datetime.datetime.strptime(roi_end[:10], "%Y-%m-%d")
877
+ roi_start_time = datetime.time(
878
+ int(roi_start[11:13]), int(roi_start[14:16])
879
+ )
880
+ roi_end_time = datetime.time(
881
+ int(roi_end[11:13]), int(roi_end[14:16])
882
+ )
883
+
884
+ start_date = st.date_input("Select the start date:", roi_start_date)
885
+ end_date = st.date_input("Select the end date:", roi_end_date)
886
+
887
+ with st.expander("Customize timelapse"):
888
+
889
+ add_fire = st.checkbox("Add Fire/Hotspot Characterization", False)
890
+
891
+ scan_type = st.selectbox(
892
+ "Select a scan type:", ["Full Disk", "CONUS", "Mesoscale"]
893
+ )
894
+
895
+ start_time = st.time_input(
896
+ "Select the start time of the start date:", roi_start_time
897
+ )
898
+
899
+ end_time = st.time_input(
900
+ "Select the end time of the end date:", roi_end_time
901
+ )
902
+
903
+ start = (
904
+ start_date.strftime("%Y-%m-%d")
905
+ + "T"
906
+ + start_time.strftime("%H:%M:%S")
907
+ )
908
+ end = (
909
+ end_date.strftime("%Y-%m-%d")
910
+ + "T"
911
+ + end_time.strftime("%H:%M:%S")
912
+ )
913
+
914
+ speed = st.slider("Frames per second:", 1, 30, 5)
915
+ add_progress_bar = st.checkbox("Add a progress bar", True)
916
+ progress_bar_color = st.color_picker(
917
+ "Progress bar color:", "#0000ff"
918
+ )
919
+ font_size = st.slider("Font size:", 10, 50, 20)
920
+ font_color = st.color_picker("Font color:", "#ffffff")
921
+ fading = st.slider(
922
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
923
+ )
924
+ mp4 = st.checkbox("Save timelapse as MP4", True)
925
+
926
+ empty_text = st.empty()
927
+ empty_image = st.empty()
928
+ empty_video = st.container()
929
+ empty_fire_text = st.empty()
930
+ empty_fire_image = st.empty()
931
+
932
+ submitted = st.form_submit_button("Submit")
933
+ if submitted:
934
+ if sample_roi == "Uploaded GeoJSON" and data is None:
935
+ empty_text.warning(
936
+ "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."
937
+ )
938
+ else:
939
+ empty_text.text("Computing... Please wait...")
940
+
941
+ geemap.goes_timelapse(
942
+ roi,
943
+ out_gif,
944
+ start_date=start,
945
+ end_date=end,
946
+ data=satellite,
947
+ scan=scan_type.replace(" ", "_").lower(),
948
+ dimensions=768,
949
+ framesPerSecond=speed,
950
+ date_format="YYYY-MM-dd HH:mm",
951
+ xy=("3%", "3%"),
952
+ text_sequence=None,
953
+ font_type="arial.ttf",
954
+ font_size=font_size,
955
+ font_color=font_color,
956
+ add_progress_bar=add_progress_bar,
957
+ progress_bar_color=progress_bar_color,
958
+ progress_bar_height=5,
959
+ loop=0,
960
+ overlay_data=overlay_data,
961
+ overlay_color=overlay_color,
962
+ overlay_width=overlay_width,
963
+ overlay_opacity=overlay_opacity,
964
+ mp4=mp4,
965
+ fading=fading,
966
+ )
967
+
968
+ if out_gif is not None and os.path.exists(out_gif):
969
+ empty_text.text(
970
+ "Right click the GIF to save it to your computer👇"
971
+ )
972
+ empty_image.image(out_gif)
973
+
974
+ out_mp4 = out_gif.replace(".gif", ".mp4")
975
+ if mp4 and os.path.exists(out_mp4):
976
+ with empty_video:
977
+ st.text(
978
+ "Right click the MP4 to save it to your computer👇"
979
+ )
980
+ st.video(out_gif.replace(".gif", ".mp4"))
981
+
982
+ if add_fire:
983
+ out_fire_gif = geemap.temp_file_path(".gif")
984
+ empty_fire_text.text(
985
+ "Delineating Fire Hotspot... Please wait..."
986
+ )
987
+ geemap.goes_fire_timelapse(
988
+ out_fire_gif,
989
+ start_date=start,
990
+ end_date=end,
991
+ data=satellite,
992
+ scan=scan_type.replace(" ", "_").lower(),
993
+ region=roi,
994
+ dimensions=768,
995
+ framesPerSecond=speed,
996
+ date_format="YYYY-MM-dd HH:mm",
997
+ xy=("3%", "3%"),
998
+ text_sequence=None,
999
+ font_type="arial.ttf",
1000
+ font_size=font_size,
1001
+ font_color=font_color,
1002
+ add_progress_bar=add_progress_bar,
1003
+ progress_bar_color=progress_bar_color,
1004
+ progress_bar_height=5,
1005
+ loop=0,
1006
+ )
1007
+ if os.path.exists(out_fire_gif):
1008
+ empty_fire_image.image(out_fire_gif)
1009
+ else:
1010
+ empty_text.text(
1011
+ "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."
1012
+ )
1013
+
1014
+ elif collection == "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km":
1015
+
1016
+ video_empty.video("https://youtu.be/16fA2QORG4A")
1017
+
1018
+ satellite = st.selectbox("Select a satellite:", ["Terra", "Aqua"])
1019
+ band = st.selectbox("Select a band:", ["NDVI", "EVI"])
1020
+
1021
+ with st.form("submit_modis_form"):
1022
+
1023
+ roi = None
1024
+ if st.session_state.get("roi") is not None:
1025
+ roi = st.session_state.get("roi")
1026
+ out_gif = geemap.temp_file_path(".gif")
1027
+
1028
+ with st.expander("Customize timelapse"):
1029
+
1030
+ start = st.date_input(
1031
+ "Select a start date:", datetime.date(2000, 2, 8)
1032
+ )
1033
+ end = st.date_input("Select an end date:", datetime.date.today())
1034
+
1035
+ start_date = start.strftime("%Y-%m-%d")
1036
+ end_date = end.strftime("%Y-%m-%d")
1037
+
1038
+ speed = st.slider("Frames per second:", 1, 30, 5)
1039
+ add_progress_bar = st.checkbox("Add a progress bar", True)
1040
+ progress_bar_color = st.color_picker(
1041
+ "Progress bar color:", "#0000ff"
1042
+ )
1043
+ font_size = st.slider("Font size:", 10, 50, 20)
1044
+ font_color = st.color_picker("Font color:", "#ffffff")
1045
+
1046
+ font_type = st.selectbox(
1047
+ "Select the font type for the title:",
1048
+ ["arial.ttf", "alibaba.otf"],
1049
+ index=0,
1050
+ )
1051
+ fading = st.slider(
1052
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1053
+ )
1054
+ mp4 = st.checkbox("Save timelapse as MP4", True)
1055
+
1056
+ empty_text = st.empty()
1057
+ empty_image = st.empty()
1058
+ empty_video = st.container()
1059
+
1060
+ submitted = st.form_submit_button("Submit")
1061
+ if submitted:
1062
+ if sample_roi == "Uploaded GeoJSON" and data is None:
1063
+ empty_text.warning(
1064
+ "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."
1065
+ )
1066
+ else:
1067
+
1068
+ empty_text.text("Computing... Please wait...")
1069
+
1070
+ geemap.modis_ndvi_timelapse(
1071
+ roi,
1072
+ out_gif,
1073
+ satellite,
1074
+ band,
1075
+ start_date,
1076
+ end_date,
1077
+ 768,
1078
+ speed,
1079
+ overlay_data=overlay_data,
1080
+ overlay_color=overlay_color,
1081
+ overlay_width=overlay_width,
1082
+ overlay_opacity=overlay_opacity,
1083
+ mp4=mp4,
1084
+ fading=fading,
1085
+ )
1086
+
1087
+ geemap.reduce_gif_size(out_gif)
1088
+
1089
+ empty_text.text(
1090
+ "Right click the GIF to save it to your computer👇"
1091
+ )
1092
+ empty_image.image(out_gif)
1093
+
1094
+ out_mp4 = out_gif.replace(".gif", ".mp4")
1095
+ if mp4 and os.path.exists(out_mp4):
1096
+ with empty_video:
1097
+ st.text(
1098
+ "Right click the MP4 to save it to your computer👇"
1099
+ )
1100
+ st.video(out_gif.replace(".gif", ".mp4"))
1101
+
1102
+ elif collection == "Any Earth Engine ImageCollection":
1103
+
1104
+ with st.form("submit_ts_form"):
1105
+ with st.expander("Customize timelapse"):
1106
+
1107
+ title = st.text_input(
1108
+ "Enter a title to show on the timelapse: ", "Timelapse"
1109
+ )
1110
+ start_date = st.date_input(
1111
+ "Select the start date:", datetime.date(2020, 1, 1)
1112
+ )
1113
+ end_date = st.date_input(
1114
+ "Select the end date:", datetime.date.today()
1115
+ )
1116
+ frequency = st.selectbox(
1117
+ "Select a temporal frequency:",
1118
+ ["year", "quarter", "month", "day", "hour", "minute", "second"],
1119
+ index=0,
1120
+ )
1121
+ reducer = st.selectbox(
1122
+ "Select a reducer for aggregating data:",
1123
+ ["median", "mean", "min", "max", "sum", "variance", "stdDev"],
1124
+ index=0,
1125
+ )
1126
+ data_format = st.selectbox(
1127
+ "Select a date format to show on the timelapse:",
1128
+ [
1129
+ "YYYY-MM-dd",
1130
+ "YYYY",
1131
+ "YYMM-MM",
1132
+ "YYYY-MM-dd HH:mm",
1133
+ "YYYY-MM-dd HH:mm:ss",
1134
+ "HH:mm",
1135
+ "HH:mm:ss",
1136
+ "w",
1137
+ "M",
1138
+ "d",
1139
+ "D",
1140
+ ],
1141
+ index=0,
1142
+ )
1143
+
1144
+ speed = st.slider("Frames per second:", 1, 30, 5)
1145
+ add_progress_bar = st.checkbox("Add a progress bar", True)
1146
+ progress_bar_color = st.color_picker(
1147
+ "Progress bar color:", "#0000ff"
1148
+ )
1149
+ font_size = st.slider("Font size:", 10, 50, 30)
1150
+ font_color = st.color_picker("Font color:", "#ffffff")
1151
+ font_type = st.selectbox(
1152
+ "Select the font type for the title:",
1153
+ ["arial.ttf", "alibaba.otf"],
1154
+ index=0,
1155
+ )
1156
+ fading = st.slider(
1157
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1158
+ )
1159
+ mp4 = st.checkbox("Save timelapse as MP4", True)
1160
+
1161
+ empty_text = st.empty()
1162
+ empty_image = st.empty()
1163
+ empty_video = st.container()
1164
+ empty_fire_image = st.empty()
1165
+
1166
+ roi = None
1167
+ if st.session_state.get("roi") is not None:
1168
+ roi = st.session_state.get("roi")
1169
+ out_gif = geemap.temp_file_path(".gif")
1170
+
1171
+ submitted = st.form_submit_button("Submit")
1172
+ if submitted:
1173
+
1174
+ if sample_roi == "Uploaded GeoJSON" and data is None:
1175
+ empty_text.warning(
1176
+ "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."
1177
+ )
1178
+ else:
1179
+
1180
+ empty_text.text("Computing... Please wait...")
1181
+ try:
1182
+ geemap.create_timelapse(
1183
+ st.session_state.get("ee_asset_id"),
1184
+ start_date=start_date.strftime("%Y-%m-%d"),
1185
+ end_date=end_date.strftime("%Y-%m-%d"),
1186
+ region=roi,
1187
+ frequency=frequency,
1188
+ reducer=reducer,
1189
+ date_format=data_format,
1190
+ out_gif=out_gif,
1191
+ bands=st.session_state.get("bands"),
1192
+ palette=st.session_state.get("palette"),
1193
+ vis_params=st.session_state.get("vis_params"),
1194
+ dimensions=768,
1195
+ frames_per_second=speed,
1196
+ crs="EPSG:3857",
1197
+ overlay_data=overlay_data,
1198
+ overlay_color=overlay_color,
1199
+ overlay_width=overlay_width,
1200
+ overlay_opacity=overlay_opacity,
1201
+ title=title,
1202
+ title_xy=("2%", "90%"),
1203
+ add_text=True,
1204
+ text_xy=("2%", "2%"),
1205
+ text_sequence=None,
1206
+ font_type=font_type,
1207
+ font_size=font_size,
1208
+ font_color=font_color,
1209
+ add_progress_bar=add_progress_bar,
1210
+ progress_bar_color=progress_bar_color,
1211
+ progress_bar_height=5,
1212
+ loop=0,
1213
+ mp4=mp4,
1214
+ fading=fading,
1215
+ )
1216
+ except:
1217
+ empty_text.error(
1218
+ "An error occurred while computing the timelapse. You probably requested too much data. Try reducing the ROI or timespan."
1219
+ )
1220
+
1221
+ empty_text.text(
1222
+ "Right click the GIF to save it to your computer👇"
1223
+ )
1224
+ empty_image.image(out_gif)
1225
+
1226
+ out_mp4 = out_gif.replace(".gif", ".mp4")
1227
+ if mp4 and os.path.exists(out_mp4):
1228
+ with empty_video:
1229
+ st.text(
1230
+ "Right click the MP4 to save it to your computer👇"
1231
+ )
1232
+ st.video(out_gif.replace(".gif", ".mp4"))
1233
+
1234
+ elif collection in [
1235
+ "MODIS Gap filled Land Surface Temperature Daily",
1236
+ "MODIS Ocean Color SMI",
1237
+ ]:
1238
+
1239
+ with st.form("submit_ts_form"):
1240
+ with st.expander("Customize timelapse"):
1241
+
1242
+ title = st.text_input(
1243
+ "Enter a title to show on the timelapse: ",
1244
+ "Surface Temperature",
1245
+ )
1246
+ start_date = st.date_input(
1247
+ "Select the start date:", datetime.date(2018, 1, 1)
1248
+ )
1249
+ end_date = st.date_input(
1250
+ "Select the end date:", datetime.date(2020, 12, 31)
1251
+ )
1252
+ frequency = st.selectbox(
1253
+ "Select a temporal frequency:",
1254
+ ["year", "quarter", "month", "week", "day"],
1255
+ index=2,
1256
+ )
1257
+ reducer = st.selectbox(
1258
+ "Select a reducer for aggregating data:",
1259
+ ["median", "mean", "min", "max", "sum", "variance", "stdDev"],
1260
+ index=0,
1261
+ )
1262
+
1263
+ vis_params = st.text_area(
1264
+ "Enter visualization parameters",
1265
+ "",
1266
+ help="Enter a string in the format of a dictionary, such as '{'min': 23, 'max': 32}'",
1267
+ )
1268
+
1269
+ speed = st.slider("Frames per second:", 1, 30, 5)
1270
+ add_progress_bar = st.checkbox("Add a progress bar", True)
1271
+ progress_bar_color = st.color_picker(
1272
+ "Progress bar color:", "#0000ff"
1273
+ )
1274
+ font_size = st.slider("Font size:", 10, 50, 30)
1275
+ font_color = st.color_picker("Font color:", "#ffffff")
1276
+ font_type = st.selectbox(
1277
+ "Select the font type for the title:",
1278
+ ["arial.ttf", "alibaba.otf"],
1279
+ index=0,
1280
+ )
1281
+ add_colorbar = st.checkbox("Add a colorbar", True)
1282
+ colorbar_label = st.text_input(
1283
+ "Enter the colorbar label:", "Surface Temperature (°C)"
1284
+ )
1285
+ fading = st.slider(
1286
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1287
+ )
1288
+ mp4 = st.checkbox("Save timelapse as MP4", True)
1289
+
1290
+ empty_text = st.empty()
1291
+ empty_image = st.empty()
1292
+ empty_video = st.container()
1293
+
1294
+ roi = None
1295
+ if st.session_state.get("roi") is not None:
1296
+ roi = st.session_state.get("roi")
1297
+ out_gif = geemap.temp_file_path(".gif")
1298
+
1299
+ submitted = st.form_submit_button("Submit")
1300
+ if submitted:
1301
+
1302
+ if sample_roi == "Uploaded GeoJSON" and data is None:
1303
+ empty_text.warning(
1304
+ "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."
1305
+ )
1306
+ else:
1307
+
1308
+ empty_text.text("Computing... Please wait...")
1309
+ try:
1310
+ if (
1311
+ collection
1312
+ == "MODIS Gap filled Land Surface Temperature Daily"
1313
+ ):
1314
+ out_gif = geemap.create_timelapse(
1315
+ st.session_state.get("ee_asset_id"),
1316
+ start_date=start_date.strftime("%Y-%m-%d"),
1317
+ end_date=end_date.strftime("%Y-%m-%d"),
1318
+ region=roi,
1319
+ bands=None,
1320
+ frequency=frequency,
1321
+ reducer=reducer,
1322
+ date_format=None,
1323
+ out_gif=out_gif,
1324
+ palette=st.session_state.get("palette"),
1325
+ vis_params=None,
1326
+ dimensions=768,
1327
+ frames_per_second=speed,
1328
+ crs="EPSG:3857",
1329
+ overlay_data=overlay_data,
1330
+ overlay_color=overlay_color,
1331
+ overlay_width=overlay_width,
1332
+ overlay_opacity=overlay_opacity,
1333
+ title=title,
1334
+ title_xy=("2%", "90%"),
1335
+ add_text=True,
1336
+ text_xy=("2%", "2%"),
1337
+ text_sequence=None,
1338
+ font_type=font_type,
1339
+ font_size=font_size,
1340
+ font_color=font_color,
1341
+ add_progress_bar=add_progress_bar,
1342
+ progress_bar_color=progress_bar_color,
1343
+ progress_bar_height=5,
1344
+ add_colorbar=add_colorbar,
1345
+ colorbar_label=colorbar_label,
1346
+ loop=0,
1347
+ mp4=mp4,
1348
+ fading=fading,
1349
+ )
1350
+ elif collection == "MODIS Ocean Color SMI":
1351
+ if vis_params.startswith("{") and vis_params.endswith(
1352
+ "}"
1353
+ ):
1354
+ vis_params = json.loads(
1355
+ vis_params.replace("'", '"')
1356
+ )
1357
+ else:
1358
+ vis_params = None
1359
+ out_gif = geemap.modis_ocean_color_timelapse(
1360
+ st.session_state.get("ee_asset_id"),
1361
+ start_date=start_date.strftime("%Y-%m-%d"),
1362
+ end_date=end_date.strftime("%Y-%m-%d"),
1363
+ region=roi,
1364
+ bands=st.session_state["band"],
1365
+ frequency=frequency,
1366
+ reducer=reducer,
1367
+ date_format=None,
1368
+ out_gif=out_gif,
1369
+ palette=st.session_state.get("palette"),
1370
+ vis_params=vis_params,
1371
+ dimensions=768,
1372
+ frames_per_second=speed,
1373
+ crs="EPSG:3857",
1374
+ overlay_data=overlay_data,
1375
+ overlay_color=overlay_color,
1376
+ overlay_width=overlay_width,
1377
+ overlay_opacity=overlay_opacity,
1378
+ title=title,
1379
+ title_xy=("2%", "90%"),
1380
+ add_text=True,
1381
+ text_xy=("2%", "2%"),
1382
+ text_sequence=None,
1383
+ font_type=font_type,
1384
+ font_size=font_size,
1385
+ font_color=font_color,
1386
+ add_progress_bar=add_progress_bar,
1387
+ progress_bar_color=progress_bar_color,
1388
+ progress_bar_height=5,
1389
+ add_colorbar=add_colorbar,
1390
+ colorbar_label=colorbar_label,
1391
+ loop=0,
1392
+ mp4=mp4,
1393
+ fading=fading,
1394
+ )
1395
+ except:
1396
+ empty_text.error(
1397
+ "Something went wrong. You probably requested too much data. Try reducing the ROI or timespan."
1398
+ )
1399
+
1400
+ if out_gif is not None and os.path.exists(out_gif):
1401
+
1402
+ geemap.reduce_gif_size(out_gif)
1403
+
1404
+ empty_text.text(
1405
+ "Right click the GIF to save it to your computer👇"
1406
+ )
1407
+ empty_image.image(out_gif)
1408
+
1409
+ out_mp4 = out_gif.replace(".gif", ".mp4")
1410
+ if mp4 and os.path.exists(out_mp4):
1411
+ with empty_video:
1412
+ st.text(
1413
+ "Right click the MP4 to save it to your computer👇"
1414
+ )
1415
+ st.video(out_gif.replace(".gif", ".mp4"))
1416
+
1417
+ else:
1418
+ st.error(
1419
+ "Something went wrong. You probably requested too much data. Try reducing the ROI or timespan."
1420
+ )
1421
+
1422
+ elif collection == "USDA National Agriculture Imagery Program (NAIP)":
1423
+
1424
+ with st.form("submit_naip_form"):
1425
+ with st.expander("Customize timelapse"):
1426
+
1427
+ title = st.text_input(
1428
+ "Enter a title to show on the timelapse: ", "NAIP Timelapse"
1429
+ )
1430
+
1431
+ years = st.slider(
1432
+ "Start and end year:",
1433
+ 2003,
1434
+ today.year,
1435
+ (2003, today.year),
1436
+ )
1437
+
1438
+ bands = st.selectbox(
1439
+ "Select a band combination:", ["N/R/G", "R/G/B"], index=0
1440
+ )
1441
+
1442
+ speed = st.slider("Frames per second:", 1, 30, 3)
1443
+ add_progress_bar = st.checkbox("Add a progress bar", True)
1444
+ progress_bar_color = st.color_picker(
1445
+ "Progress bar color:", "#0000ff"
1446
+ )
1447
+ font_size = st.slider("Font size:", 10, 50, 30)
1448
+ font_color = st.color_picker("Font color:", "#ffffff")
1449
+ font_type = st.selectbox(
1450
+ "Select the font type for the title:",
1451
+ ["arial.ttf", "alibaba.otf"],
1452
+ index=0,
1453
+ )
1454
+ fading = st.slider(
1455
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1456
+ )
1457
+ mp4 = st.checkbox("Save timelapse as MP4", True)
1458
+
1459
+ empty_text = st.empty()
1460
+ empty_image = st.empty()
1461
+ empty_video = st.container()
1462
+ empty_fire_image = st.empty()
1463
+
1464
+ roi = None
1465
+ if st.session_state.get("roi") is not None:
1466
+ roi = st.session_state.get("roi")
1467
+ out_gif = geemap.temp_file_path(".gif")
1468
+
1469
+ submitted = st.form_submit_button("Submit")
1470
+ if submitted:
1471
+
1472
+ if sample_roi == "Uploaded GeoJSON" and data is None:
1473
+ empty_text.warning(
1474
+ "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."
1475
+ )
1476
+ else:
1477
+
1478
+ empty_text.text("Computing... Please wait...")
1479
+ try:
1480
+ geemap.naip_timelapse(
1481
+ roi,
1482
+ years[0],
1483
+ years[1],
1484
+ out_gif,
1485
+ bands=bands.split("/"),
1486
+ palette=st.session_state.get("palette"),
1487
+ vis_params=None,
1488
+ dimensions=768,
1489
+ frames_per_second=speed,
1490
+ crs="EPSG:3857",
1491
+ overlay_data=overlay_data,
1492
+ overlay_color=overlay_color,
1493
+ overlay_width=overlay_width,
1494
+ overlay_opacity=overlay_opacity,
1495
+ title=title,
1496
+ title_xy=("2%", "90%"),
1497
+ add_text=True,
1498
+ text_xy=("2%", "2%"),
1499
+ text_sequence=None,
1500
+ font_type=font_type,
1501
+ font_size=font_size,
1502
+ font_color=font_color,
1503
+ add_progress_bar=add_progress_bar,
1504
+ progress_bar_color=progress_bar_color,
1505
+ progress_bar_height=5,
1506
+ loop=0,
1507
+ mp4=mp4,
1508
+ fading=fading,
1509
+ )
1510
+ except:
1511
+ empty_text.error(
1512
+ "Something went wrong. You either requested too much data or the ROI is outside the U.S."
1513
+ )
1514
+
1515
+ if out_gif is not None and os.path.exists(out_gif):
1516
+
1517
+ empty_text.text(
1518
+ "Right click the GIF to save it to your computer👇"
1519
+ )
1520
+ empty_image.image(out_gif)
1521
+
1522
+ out_mp4 = out_gif.replace(".gif", ".mp4")
1523
+ if mp4 and os.path.exists(out_mp4):
1524
+ with empty_video:
1525
+ st.text(
1526
+ "Right click the MP4 to save it to your computer👇"
1527
+ )
1528
+ st.video(out_gif.replace(".gif", ".mp4"))
1529
+
1530
+ else:
1531
+ st.error(
1532
+ "Something went wrong. You either requested too much data or the ROI is outside the U.S."
1533
+ )
1534
+
1535
+
1536
+ try:
1537
+ app()
1538
+ except Exception as e:
1539
+ pass
custom.js ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ document.addEventListener("DOMContentLoaded", function () {
2
+ // Add a fade-in effect to elements with class "fade-in"
3
+ const elements = document.querySelectorAll(".fade-in");
4
+ elements.forEach(function (element) {
5
+ element.classList.add("fade");
6
+ element.style.opacity = 0;
7
+ element.addEventListener("transitionend", function () {
8
+ element.style.opacity = 1;
9
+ });
10
+ });
11
+
12
+ // Handle form submission when the "Submit" button is clicked
13
+ const submitButton = document.getElementById("submitButton");
14
+ submitButton.addEventListener("click", function (event) {
15
+ // Prevent the default form submission
16
+ event.preventDefault();
17
+
18
+ // Trigger the form submission
19
+ const form = document.getElementById("dataForm");
20
+ form.submit();
21
+ });
22
+ });
db.sqlite3 ADDED
Binary file (131 kB). View file
 
index.html ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Run Command</title>
5
+ </head>
6
+ <body>
7
+ <h1>Run Command</h1>
8
+ <button id="runCommand">Run Server Command</button>
9
+ <pre id="result"></pre>
10
+
11
+ <script>
12
+ document.getElementById('runCommand').addEventListener('click', () => {
13
+ fetch('https://your-backend-url.com/run-command/', {
14
+ method: 'POST',
15
+ headers: {
16
+ 'Content-Type': 'application/json',
17
+ },
18
+ })
19
+ .then(response => response.json())
20
+ .then(data => {
21
+ document.getElementById('result').textContent = JSON.stringify(data, null, 2);
22
+ })
23
+ .catch(error => {
24
+ document.getElementById('result').textContent = 'Error: ' + error;
25
+ });
26
+ });
27
+ </script>
28
+ </body>
29
+ </html>
jaw.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+
3
+ st.title("HOME PAGE")
4
+
5
+ st.title("Streamlit for Geospatial Applications")
6
+
7
+
8
+ PAGES = {
9
+ "Home": "jaw.py",
10
+ "Folium Map": "folium_Map.py",
11
+
12
+ }
13
+
14
+ # Sidebar for navigation
15
+ st.sidebar.title("Navigation")
16
+ selection = st.sidebar.radio("Go to", list(PAGES.keys()))
17
+
18
+ # Load the selected page
19
+ page = PAGES[selection]
20
+ exec(open(page).read())
manage.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ #!/usr/bin/env python
3
+ import os
4
+ import sys
5
+ import ee
6
+ import google.auth.exceptions
7
+
8
+
9
+ # Function to initialize GEE
10
+ # def initialize_gee():
11
+ # service = os.getenv('SA')
12
+ # file = r"D:\Desktop\Django_app_12_sep-2023\gee\ee-muzzamil.json"
13
+ # credentials = ee.ServiceAccountCredentials(service, file)
14
+ # ee.Initialize(credentials)
15
+
16
+
17
+ # Function to refresh GEE token
18
+ # def refresh_gee_token():
19
+ # if not ee.data.getAssetRoots():
20
+ # initialize_gee()
21
+ from google.auth.transport.requests import Request
22
+
23
+
24
+
25
+
26
+ def inv():
27
+ service = os.getenv('SA')
28
+ file = os.path.join(os.path.dirname(os.path.abspath(__file__)),'gee','ee-muzzamil1-37ebc3dece52.json')
29
+ print(file)
30
+ credentials = ee.ServiceAccountCredentials(service, file)
31
+ try:
32
+ ee.Initialize(credentials)
33
+ except google.auth.exceptions.RefreshError as e:
34
+ # If the token has expired, refresh it
35
+ request = Request()
36
+ credentials.refresh(request)
37
+ ee.Initialize(credentials)
38
+
39
+
40
+
41
+ if __name__ == "__main__":
42
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djangoGEE.settings")
43
+ # initialize_gee()
44
+ # refresh_gee_token()
45
+ inv()
46
+
47
+ try:
48
+ from django.core.management import execute_from_command_line
49
+ except ImportError as exc:
50
+ raise ImportError(
51
+ "Couldn't import Django. Are you sure it's installed and "
52
+ "available on your PYTHONPATH environment variable? Did you "
53
+ "forget to activate a virtual environment?"
54
+ ) from exc
55
+
56
+ # Add a call to refresh_gee_token() before executing Django commands
57
+ # refresh_gee_token()
58
+
59
+ execute_from_command_line(sys.argv)
ndvi_map.html ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+
5
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
6
+
7
+ <script>
8
+ L_NO_TOUCH = false;
9
+ L_DISABLE_3D = false;
10
+ </script>
11
+
12
+ <style>html, body {width: 100%;height: 100%;margin: 0;padding: 0;}</style>
13
+ <style>#map {position:absolute;top:0;bottom:0;right:0;left:0;}</style>
14
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/leaflet.js"></script>
15
+ <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
16
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
17
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.js"></script>
18
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/leaflet.css"/>
19
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"/>
20
+ <link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css"/>
21
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/[email protected]/css/all.min.css"/>
22
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css"/>
23
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/python-visualization/folium/folium/templates/leaflet.awesome.rotate.min.css"/>
24
+
25
+ <meta name="viewport" content="width=device-width,
26
+ initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
27
+ <style>
28
+ #map_fcd37a053ddc8939363703c5aef5a9a7 {
29
+ position: relative;
30
+ width: 100.0%;
31
+ height: 100.0%;
32
+ left: 0.0%;
33
+ top: 0.0%;
34
+ }
35
+ .leaflet-container { font-size: 1rem; }
36
+ </style>
37
+
38
+ </head>
39
+ <body>
40
+
41
+
42
+ <div class="folium-map" id="map_fcd37a053ddc8939363703c5aef5a9a7" ></div>
43
+
44
+ </body>
45
+ <script>
46
+
47
+
48
+ var map_fcd37a053ddc8939363703c5aef5a9a7 = L.map(
49
+ "map_fcd37a053ddc8939363703c5aef5a9a7",
50
+ {
51
+ center: [25.5973518, 65.54495724],
52
+ crs: L.CRS.EPSG3857,
53
+ zoom: 7,
54
+ zoomControl: true,
55
+ preferCanvas: false,
56
+ }
57
+ );
58
+
59
+
60
+
61
+
62
+
63
+ var tile_layer_38d271509d035dba40f2746a329fd4e2 = L.tileLayer(
64
+ "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
65
+ {"attribution": "\u0026copy; \u003ca href=\"https://www.openstreetmap.org/copyright\"\u003eOpenStreetMap\u003c/a\u003e contributors", "detectRetina": false, "maxNativeZoom": 19, "maxZoom": 19, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abc", "tms": false}
66
+ );
67
+
68
+
69
+ tile_layer_38d271509d035dba40f2746a329fd4e2.addTo(map_fcd37a053ddc8939363703c5aef5a9a7);
70
+
71
+ </script>
72
+ </html>
requirements.txt ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ streamlit==1.15.2
2
+ folium==0.12.1.post1
3
+ geopandas==0.12.2
4
+ geemap==0.11.3
5
+ earthengine-api==0.1.328
6
+ pandas==1.5.3
7
+ google-auth==2.17.3
8
+ shapely==2.0.1
9
+ fiona==1.8.22
10
+ streamlit
11
+ folium
12
+ earthengine-api
13
+ pandas
14
+ numpy
satellite_image.png ADDED
style.css ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* styles.css */
2
+
3
+ /* Header styles */
4
+ header {
5
+ background-color: #333;
6
+ color: #fff;
7
+ text-align: center;
8
+ padding: 20px 0;
9
+ }
10
+
11
+ nav ul {
12
+ list-style: none;
13
+ padding: 0;
14
+ }
15
+
16
+ nav li {
17
+ display: inline;
18
+ margin-right: 20px;
19
+ }
20
+
21
+ nav a {
22
+ color: #fff;
23
+ text-decoration: none;
24
+ }
25
+
26
+ /* Add more CSS styles as needed */
test.py ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import folium
3
+ import geopandas as gpd
4
+ import json
5
+ import geemap.foliumap as geemap
6
+ import ee
7
+ import pandas as pd
8
+ import os
9
+ from google.auth.transport.requests import Request
10
+ import google.auth.exceptions
11
+ from streamlit.components.v1 import html
12
+
13
+ # Path to your shapefiles and service account key
14
+ SHAPEFILE_DIR = 'C:\\Users\\piv\\Desktop\\y\\media\\shp' # Fixed path separator
15
+
16
+ # Function to initialize GEE
17
+ def initialize_gee():
18
+ service = os.getenv('SA')
19
+ file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'gee', 'ee-muzzamil1-37ebc3dece52.json')
20
+ credentials = ee.ServiceAccountCredentials(service, file)
21
+ try:
22
+ ee.Initialize(credentials)
23
+ st.success("Google Earth Engine initialized successfully.")
24
+ except google.auth.exceptions.RefreshError:
25
+ try:
26
+ request = Request()
27
+ credentials.refresh(request)
28
+ ee.Initialize(credentials)
29
+ st.success("Google Earth Engine token refreshed and initialized successfully.")
30
+ except Exception as e:
31
+ st.error(f"Error refreshing Google Earth Engine token: {e}")
32
+ except Exception as e:
33
+ st.error(f"Error initializing Google Earth Engine: {e}")
34
+
35
+ # Function to create Folium map with selected dataset
36
+ def create_folium_map(selected_dataset, ee_object, start_date_str, end_date_str):
37
+ folium_map = folium.Map(location=[25.5973518, 65.54495724], zoom_start=7)
38
+
39
+ try:
40
+ if selected_dataset == "Modis":
41
+ dataset = ee.ImageCollection('MODIS/006/MOD13Q1') \
42
+ .filter(ee.Filter.date(start_date_str, end_date_str)) \
43
+ .filterBounds(ee_object)
44
+ def clip_image(img):
45
+ return img.clip(ee_object).select('NDVI')
46
+ clipped_collection = dataset.map(clip_image)
47
+ modis_ndvi = clipped_collection.mean()
48
+ vis_params_ndvi = {
49
+ 'min': 0,
50
+ 'max': 9000,
51
+ 'palette': ['FE8374', 'C0E5DE', '3A837C', '034B48']
52
+ }
53
+ modis_ndvi_map_id = modis_ndvi.getMapId(vis_params_ndvi)
54
+ folium.TileLayer(
55
+ tiles=modis_ndvi_map_id['tile_fetcher'].url_format,
56
+ attr='Google Earth Engine',
57
+ name='NDVI',
58
+ overlay=True,
59
+ control=True
60
+ ).add_to(folium_map)
61
+
62
+ elif selected_dataset == "dataset_nighttime":
63
+ dataset_nighttime = ee.ImageCollection('NOAA/VIIRS/DNB/MONTHLY_V1/VCMCFG') \
64
+ .filter(ee.Filter.date(start_date_str, end_date_str))
65
+ nighttime = dataset_nighttime.select('avg_rad').mosaic()
66
+ nighttime_clipped = nighttime.clip(ee_object)
67
+ nighttime_vis = {
68
+ 'min': 0.0,
69
+ 'max': 60.0,
70
+ 'palette': ['1a3678', '2955bc', '5699ff', '8dbae9', 'acd1ff', 'caebff', 'e5f9ff', 'fdffb4', 'ffe6a2', 'ffc969', 'ffa12d', 'ff7c1f', 'ca531a', 'ff0000', 'ab0000']
71
+ }
72
+ nighttime_map_id = nighttime_clipped.getMapId(nighttime_vis)
73
+ folium.TileLayer(
74
+ tiles=nighttime_map_id['tile_fetcher'].url_format,
75
+ attr='Google Earth Engine',
76
+ name='Nighttime Lights',
77
+ overlay=True,
78
+ control=True
79
+ ).add_to(folium_map)
80
+
81
+ elif selected_dataset == "precipitation":
82
+ dataset_precipitation = ee.ImageCollection('UCSB-CHG/CHIRPS/DAILY') \
83
+ .filter(ee.Filter.date(start_date_str, end_date_str))
84
+ precipitation = dataset_precipitation.mosaic().clip(ee_object)
85
+ precip_vis = {
86
+ 'min': 0,
87
+ 'max': 300,
88
+ 'palette': ['blue', 'cyan', 'lime', 'yellow', 'red']
89
+ }
90
+ precip_map_id = precipitation.getMapId(precip_vis)
91
+ folium.TileLayer(
92
+ tiles=precip_map_id['tile_fetcher'].url_format,
93
+ attr='Google Earth Engine',
94
+ name='Precipitation',
95
+ overlay=True,
96
+ control=True
97
+ ).add_to(folium_map)
98
+
99
+ elif selected_dataset == "GlobalSurfaceWater":
100
+ st.warning("GlobalSurfaceWater dataset is not configured.")
101
+
102
+ elif selected_dataset == "WorldPop":
103
+ dataset = ee.ImageCollection('WorldPop/GP/100m/pop') \
104
+ .filterBounds(ee_object) \
105
+ .filter(ee.Filter.date(start_date_str, end_date_str))
106
+ population = dataset.mean().clip(ee_object)
107
+ pop_vis = {
108
+ 'min': 0,
109
+ 'max': 1000,
110
+ 'palette': ['blue', 'green', 'yellow', 'red']
111
+ }
112
+ pop_map_id = population.getMapId(pop_vis)
113
+ folium.TileLayer(
114
+ tiles=pop_map_id['tile_fetcher'].url_format,
115
+ attr='Google Earth Engine',
116
+ name='World Population',
117
+ overlay=True,
118
+ control=True
119
+ ).add_to(folium_map)
120
+
121
+ elif selected_dataset == "COPERNICUS":
122
+ dataset = ee.ImageCollection('COPERNICUS/S2') \
123
+ .filterBounds(ee_object) \
124
+ .filter(ee.Filter.date(start_date_str, end_date_str))
125
+ sentinel = dataset.median().clip(ee_object)
126
+ vis_params = {
127
+ 'bands': ['B4', 'B3', 'B2'], # RGB bands for visualization
128
+ 'min': 0,
129
+ 'max': 3000,
130
+ 'gamma': 1.4
131
+ }
132
+ copernicus_map_id = sentinel.getMapId(vis_params)
133
+ folium.TileLayer(
134
+ tiles=copernicus_map_id['tile_fetcher'].url_format,
135
+ attr='Google Earth Engine',
136
+ name='Copernicus Sentinel-2',
137
+ overlay=True,
138
+ control=True
139
+ ).add_to(folium_map)
140
+
141
+ folium_map.add_child(folium.LayerControl())
142
+ except Exception as e:
143
+ st.error(f"Error processing dataset: {e}")
144
+ st.write(f"Exception: {e}")
145
+
146
+ # Convert Folium map to HTML
147
+ folium_map_html = folium_map._repr_html_()
148
+ st.write(folium_map_html) # Debug line
149
+ return folium_map_html
150
+
151
+ # Function to handle submit button logic
152
+ def handle_submit(selected_dataset, selected_date_range_From, selected_date_range_To, selected_shape):
153
+ # Construct shapefile path based on selected shape
154
+ shapefile_name = f'{selected_shape}.shp'
155
+ shapefile_path = os.path.join(SHAPEFILE_DIR, shapefile_name)
156
+
157
+ if os.path.exists(shapefile_path):
158
+ try:
159
+ # Read shapefile
160
+ roi_gdf = gpd.read_file(shapefile_path)
161
+ roi_geojson = roi_gdf.to_crs("EPSG:4326").to_json()
162
+ except Exception as e:
163
+ st.error(f"Error reading shapefile: {e}")
164
+ return
165
+
166
+ # Convert GeoJSON to Earth Engine object
167
+ try:
168
+ ee_object = geemap.geojson_to_ee(json.loads(roi_geojson))
169
+ except Exception as e:
170
+ st.error(f"Error converting GeoJSON to Earth Engine object: {e}")
171
+ return
172
+
173
+ # Create and display Folium map for satellite data
174
+ st.markdown("### Satellite Data Map")
175
+ folium_map_html = create_folium_map(
176
+ selected_dataset,
177
+ ee_object,
178
+ selected_date_range_From.strftime('%Y-%m-%d'),
179
+ selected_date_range_To.strftime('%Y-%m-%d')
180
+ )
181
+ # Use Streamlit to render the HTML
182
+ html(folium_map_html, height=600)
183
+ else:
184
+ st.error("Selected shapefile does not exist.")
185
+
186
+ # Streamlit application
187
+ def main():
188
+ st.set_page_config(layout="wide")
189
+ st.title("Satellite Data Visualization, Interactive Map")
190
+
191
+ # Initialize GEE when the app starts
192
+ initialize_gee()
193
+
194
+ # Sidebar with general information
195
+ st.sidebar.title("Controls")
196
+
197
+ submit_control()
198
+
199
+ # Dataset selection
200
+
201
+ def submit_control():
202
+ selected_dataset = st.sidebar.selectbox(
203
+ "Select Dataset",
204
+ ["Modis", "dataset_nighttime", 'precipitation', 'GlobalSurfaceWater', 'WorldPop', 'COPERNICUS']
205
+ )
206
+
207
+ # Date range selection
208
+ selected_date_range_From = st.sidebar.date_input("From", value=pd.to_datetime("2015-07-01"))
209
+ selected_date_range_To = st.sidebar.date_input("To", value=pd.to_datetime("2023-09-30"))
210
+
211
+ # Shape options
212
+ shape_options = [
213
+ 'District_Boundary', 'hydro_basins', 'karachi',
214
+ 'National_Constituency_with_Projected_2010_Population',
215
+ 'Provincial_Boundary', 'Provincial_Constituency',
216
+ 'Tehsil_Boundary', 'Union_Council'
217
+ ]
218
+
219
+ # Shape selection
220
+ selected_shape = st.sidebar.selectbox("Select Shape", shape_options)
221
+
222
+ # Add a submit button
223
+ if st.sidebar.button("Submit"):
224
+ # Store the current inputs in session state
225
+ st.session_state.selected_dataset = selected_dataset
226
+ st.session_state.selected_date_range_From = selected_date_range_From
227
+ st.session_state.selected_date_range_To = selected_date_range_To
228
+ st.session_state.selected_shape = selected_shape
229
+
230
+ # Check if the form has been submitted
231
+ if 'selected_dataset' in st.session_state:
232
+ handle_submit(
233
+ st.session_state.selected_dataset,
234
+ st.session_state.selected_date_range_From,
235
+ st.session_state.selected_date_range_To,
236
+ st.session_state.selected_shape
237
+ )
238
+
239
+
240
+ if __name__ == "__main__":
241
+ main()
242
+
test1.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ import streamlit as st
2
+
3
+ x = st.slider('Select a value')
4
+ st.write(x, 'squared is', x * x)