aassiiyAA123 commited on
Commit
7890d7a
·
verified ·
1 Parent(s): 2854df2

Upload 17 files

Browse files
Files changed (4) hide show
  1. Home.py +2079 -0
  2. Timelapse.py +0 -5
  3. requirements.txt +14 -14
  4. test.py +242 -0
Home.py ADDED
@@ -0,0 +1,2079 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ def interactive_map_page():
66
+ st.title("Interactive Map")
67
+ create_sidebar_controls()
68
+
69
+ map_col, control_col = st.columns([3, 1]) # Adjust column width ratios as needed
70
+
71
+ with map_col:
72
+ if 'submitted' in st.session_state and st.session_state.submitted:
73
+ st.markdown("### Satellite Data Map")
74
+ st.components.v1.html(st.session_state.folium_map_html, height=600)
75
+
76
+ with control_col:
77
+ st.header("Map Controls")
78
+
79
+ def create_folium_map(selected_dataset, ee_object, start_date_str, end_date_str):
80
+ folium_map = folium.Map(location=[25.5973518, 65.54495724], zoom_start=7)
81
+
82
+ try:
83
+ if selected_dataset == "Modis":
84
+ dataset = ee.ImageCollection('MODIS/006/MOD13Q1') \
85
+ .filter(ee.Filter.date(start_date_str, end_date_str)) \
86
+ .filterBounds(ee_object)
87
+
88
+ def clip_image(img):
89
+ return img.clip(ee_object).select('NDVI')
90
+
91
+ clipped_collection = dataset.map(clip_image)
92
+ modis_ndvi = clipped_collection.mean()
93
+ vis_params_ndvi = {
94
+ 'min': 0,
95
+ 'max': 9000,
96
+ 'palette': ['FE8374', 'C0E5DE', '3A837C', '034B48']
97
+ }
98
+ modis_ndvi_map_id = modis_ndvi.getMapId(vis_params_ndvi)
99
+ folium.TileLayer(
100
+ tiles=modis_ndvi_map_id['tile_fetcher'].url_format,
101
+ attr='Google Earth Engine',
102
+ name='NDVI',
103
+ overlay=True,
104
+ control=True
105
+ ).add_to(folium_map)
106
+
107
+ elif selected_dataset == "dataset_nighttime":
108
+ dataset_nighttime = ee.ImageCollection('NOAA/VIIRS/DNB/MONTHLY_V1/VCMCFG') \
109
+ .filter(ee.Filter.date(start_date_str, end_date_str))
110
+
111
+ nighttime = dataset_nighttime.select('avg_rad').mosaic()
112
+ nighttime_clipped = nighttime.clip(ee_object)
113
+ nighttime_vis = {
114
+ 'min': 0.0,
115
+ 'max': 60.0,
116
+ 'palette': ['1a3678', '2955bc', '5699ff', '8dbae9', 'acd1ff', 'caebff', 'e5f9ff', 'fdffb4', 'ffe6a2', 'ffc969', 'ffa12d', 'ff7c1f', 'ca531a', 'ff0000', 'ab0000']
117
+ }
118
+ nighttime_map_id = nighttime_clipped.getMapId(nighttime_vis)
119
+ folium.TileLayer(
120
+ tiles=nighttime_map_id['tile_fetcher'].url_format,
121
+ attr='Google Earth Engine',
122
+ name='Nighttime Lights',
123
+ overlay=True,
124
+ control=True
125
+ ).add_to(folium_map)
126
+
127
+ elif selected_dataset == "precipitation":
128
+ dataset_precipitation = ee.ImageCollection('UCSB-CHG/CHIRPS/DAILY') \
129
+ .filter(ee.Filter.date(start_date_str, end_date_str))
130
+
131
+ precipitation = dataset_precipitation.mosaic().clip(ee_object)
132
+ precip_vis = {
133
+ 'min': 0,
134
+ 'max': 300,
135
+ 'palette': ['blue', 'cyan', 'lime', 'yellow', 'red']
136
+ }
137
+ precip_map_id = precipitation.getMapId(precip_vis)
138
+ folium.TileLayer(
139
+ tiles=precip_map_id['tile_fetcher'].url_format,
140
+ attr='Google Earth Engine',
141
+ name='Precipitation',
142
+ overlay=True,
143
+ control=True
144
+ ).add_to(folium_map)
145
+
146
+ elif selected_dataset == "GlobalSurfaceWater":
147
+ st.warning("GlobalSurfaceWater dataset is not configured.")
148
+
149
+ elif selected_dataset == "WorldPop":
150
+ dataset = ee.ImageCollection('WorldPop/GP/100m/pop') \
151
+ .filterBounds(ee_object) \
152
+ .filter(ee.Filter.date(start_date_str, end_date_str))
153
+
154
+ population = dataset.mean().clip(ee_object)
155
+ pop_vis = {
156
+ 'min': 0,
157
+ 'max': 1000,
158
+ 'palette': ['blue', 'green', 'yellow', 'red']
159
+ }
160
+ pop_map_id = population.getMapId(pop_vis)
161
+ folium.TileLayer(
162
+ tiles=pop_map_id['tile_fetcher'].url_format,
163
+ attr='Google Earth Engine',
164
+ name='World Population',
165
+ overlay=True,
166
+ control=True
167
+ ).add_to(folium_map)
168
+
169
+ elif selected_dataset == "COPERNICUS":
170
+ dataset = ee.ImageCollection('COPERNICUS/S2') \
171
+ .filterBounds(ee_object) \
172
+ .filter(ee.Filter.date(start_date_str, end_date_str))
173
+
174
+ sentinel = dataset.median().clip(ee_object)
175
+ vis_params = {
176
+ 'bands': ['B4', 'B3', 'B2'],
177
+ 'min': 0,
178
+ 'max': 3000,
179
+ 'gamma': 1.4
180
+ }
181
+ copernicus_map_id = sentinel.getMapId(vis_params)
182
+ folium.TileLayer(
183
+ tiles=copernicus_map_id['tile_fetcher'].url_format,
184
+ attr='Google Earth Engine',
185
+ name='Copernicus Sentinel-2',
186
+ overlay=True,
187
+ control=True
188
+ ).add_to(folium_map)
189
+
190
+ folium_map.add_child(folium.LayerControl())
191
+ except Exception as e:
192
+ st.error(f"Error processing dataset: {e}")
193
+
194
+ folium_map_html = folium_map._repr_html_()
195
+ return folium_map_html
196
+
197
+ def handle_submit(selected_dataset, selected_date_range_From, selected_date_range_To, selected_shape):
198
+ shapefile_name = f'{selected_shape}.shp'
199
+ shapefile_path = os.path.join(SHAPEFILE_DIR, shapefile_name)
200
+
201
+ if os.path.exists(shapefile_path):
202
+ try:
203
+ roi_gdf = gpd.read_file(shapefile_path)
204
+ roi_geojson = roi_gdf.to_crs("EPSG:4326").to_json()
205
+ except Exception as e:
206
+ st.error(f"Error reading shapefile: {e}")
207
+ return
208
+
209
+ try:
210
+ ee_object = geemap.geojson_to_ee(json.loads(roi_geojson))
211
+ except Exception as e:
212
+ st.error(f"Error converting GeoJSON to Earth Engine object: {e}")
213
+ return
214
+
215
+ st.markdown("### Satellite Data Map")
216
+ folium_map_html = create_folium_map(
217
+ selected_dataset,
218
+ ee_object,
219
+ selected_date_range_From.strftime('%Y-%m-%d'),
220
+ selected_date_range_To.strftime('%Y-%m-%d')
221
+ )
222
+ st.session_state.folium_map_html = folium_map_html
223
+ else:
224
+ st.error("Selected shapefile does not exist.")
225
+
226
+ def create_sidebar_controls():
227
+ with st.sidebar:
228
+ selected_dataset = st.selectbox(
229
+ "Select Dataset",
230
+ ["Modis", "dataset_nighttime", 'precipitation', 'GlobalSurfaceWater', 'WorldPop', 'COPERNICUS'],
231
+ key='sidebar_dataset_selectbox'
232
+ )
233
+
234
+ selected_date_range_From = st.date_input(
235
+ "From",
236
+ value=pd.to_datetime("2015-07-01"),
237
+ key='sidebar_date_from'
238
+ )
239
+ selected_date_range_To = st.date_input(
240
+ "To",
241
+ value=pd.to_datetime("2023-09-30"),
242
+ key='sidebar_date_to'
243
+ )
244
+
245
+ shape_options = [
246
+ 'District_Boundary', 'hydro_basins', 'karachi',
247
+ 'National_Constituency_with_Projected_2010_Population',
248
+ 'Provincial_Boundary', 'Provincial_Constituency',
249
+ 'Tehsil_Boundary', 'Union_Council'
250
+ ]
251
+
252
+ selected_shape = st.selectbox(
253
+ "Select Shape",
254
+ shape_options,
255
+ key='sidebar_shape_selectbox'
256
+ )
257
+
258
+ if st.button("Submit", key='sidebar_submit_button'):
259
+ st.session_state.selected_dataset = selected_dataset
260
+ st.session_state.selected_date_range_From = selected_date_range_From
261
+ st.session_state.selected_date_range_To = selected_date_range_To
262
+ st.session_state.selected_shape = selected_shape
263
+ st.session_state.submitted = True
264
+ else:
265
+ st.session_state.submitted = False
266
+
267
+ if 'submitted' in st.session_state and st.session_state.submitted:
268
+ handle_submit(
269
+ st.session_state.selected_dataset,
270
+ st.session_state.selected_date_range_From,
271
+ st.session_state.selected_date_range_To,
272
+ st.session_state.selected_shape
273
+ )
274
+
275
+
276
+ def interactive_map_page():
277
+ st.title("Interactive Map")
278
+ submit_control()
279
+
280
+ #<------------------------------------------------------- Interactive map code------------------------------------------------------------------------------------------------------------------->
281
+
282
+
283
+
284
+ # Create two columns: one for the map and one for the controls
285
+ map_col, control_col = st.columns([3, 1]) # Adjust column width ratios as needed
286
+
287
+ # Map column
288
+ with map_col:
289
+ if 'submitted' in st.session_state and st.session_state.submitted:
290
+ st.markdown("### Satellite Data Map")
291
+ st.components.v1.html(st.session_state.folium_map_html, height=600)
292
+
293
+ # Control column
294
+ with control_col:
295
+ st.header("Map Controls")
296
+ selected_dataset = st.selectbox(
297
+ "Select Dataset",
298
+ ["Modis", "dataset_nighttime", 'precipitation', 'GlobalSurfaceWater', 'WorldPop', 'COPERNICUS']
299
+ )
300
+
301
+ selected_date_range_From = st.date_input("From", value=pd.to_datetime("2015-07-01"))
302
+ selected_date_range_To = st.date_input("To", value=pd.to_datetime("2023-09-30"))
303
+
304
+ shape_options = [
305
+ 'District_Boundary', 'hydro_basins', 'karachi',
306
+ 'National_Constituency_with_Projected_2010_Population',
307
+ 'Provincial_Boundary', 'Provincial_Constituency',
308
+ 'Tehsil_Boundary', 'Union_Council'
309
+ ]
310
+
311
+ selected_shape = st.selectbox("Select Shape", shape_options)
312
+
313
+ if st.button("Submit"):
314
+ handle_submit(
315
+ selected_dataset,
316
+ selected_date_range_From,
317
+ selected_date_range_To,
318
+ selected_shape
319
+ )
320
+
321
+
322
+ def create_folium_map(selected_dataset, ee_object, start_date_str, end_date_str):
323
+ folium_map = folium.Map(location=[25.5973518, 65.54495724], zoom_start=7)
324
+
325
+ try:
326
+ if selected_dataset == "Modis":
327
+ dataset = ee.ImageCollection('MODIS/006/MOD13Q1') \
328
+ .filter(ee.Filter.date(start_date_str, end_date_str)) \
329
+ .filterBounds(ee_object)
330
+
331
+ def clip_image(img):
332
+ return img.clip(ee_object).select('NDVI')
333
+
334
+ clipped_collection = dataset.map(clip_image)
335
+ modis_ndvi = clipped_collection.mean()
336
+ vis_params_ndvi = {
337
+ 'min': 0,
338
+ 'max': 9000,
339
+ 'palette': ['FE8374', 'C0E5DE', '3A837C', '034B48']
340
+ }
341
+ modis_ndvi_map_id = modis_ndvi.getMapId(vis_params_ndvi)
342
+ folium.TileLayer(
343
+ tiles=modis_ndvi_map_id['tile_fetcher'].url_format,
344
+ attr='Google Earth Engine',
345
+ name='NDVI',
346
+ overlay=True,
347
+ control=True
348
+ ).add_to(folium_map)
349
+
350
+ elif selected_dataset == "dataset_nighttime":
351
+ dataset_nighttime = ee.ImageCollection('NOAA/VIIRS/DNB/MONTHLY_V1/VCMCFG') \
352
+ .filter(ee.Filter.date(start_date_str, end_date_str))
353
+
354
+ nighttime = dataset_nighttime.select('avg_rad').mosaic()
355
+ nighttime_clipped = nighttime.clip(ee_object)
356
+ nighttime_vis = {
357
+ 'min': 0.0,
358
+ 'max': 60.0,
359
+ 'palette': ['1a3678', '2955bc', '5699ff', '8dbae9', 'acd1ff', 'caebff', 'e5f9ff', 'fdffb4', 'ffe6a2', 'ffc969', 'ffa12d', 'ff7c1f', 'ca531a', 'ff0000', 'ab0000']
360
+ }
361
+ nighttime_map_id = nighttime_clipped.getMapId(nighttime_vis)
362
+ folium.TileLayer(
363
+ tiles=nighttime_map_id['tile_fetcher'].url_format,
364
+ attr='Google Earth Engine',
365
+ name='Nighttime Lights',
366
+ overlay=True,
367
+ control=True
368
+ ).add_to(folium_map)
369
+
370
+ elif selected_dataset == "precipitation":
371
+ dataset_precipitation = ee.ImageCollection('UCSB-CHG/CHIRPS/DAILY') \
372
+ .filter(ee.Filter.date(start_date_str, end_date_str))
373
+
374
+ precipitation = dataset_precipitation.mosaic().clip(ee_object)
375
+ precip_vis = {
376
+ 'min': 0,
377
+ 'max': 300,
378
+ 'palette': ['blue', 'cyan', 'lime', 'yellow', 'red']
379
+ }
380
+ precip_map_id = precipitation.getMapId(precip_vis)
381
+ folium.TileLayer(
382
+ tiles=precip_map_id['tile_fetcher'].url_format,
383
+ attr='Google Earth Engine',
384
+ name='Precipitation',
385
+ overlay=True,
386
+ control=True
387
+ ).add_to(folium_map)
388
+
389
+ elif selected_dataset == "GlobalSurfaceWater":
390
+ st.warning("GlobalSurfaceWater dataset is not configured.")
391
+
392
+ elif selected_dataset == "WorldPop":
393
+ dataset = ee.ImageCollection('WorldPop/GP/100m/pop') \
394
+ .filterBounds(ee_object) \
395
+ .filter(ee.Filter.date(start_date_str, end_date_str))
396
+
397
+ population = dataset.mean().clip(ee_object)
398
+ pop_vis = {
399
+ 'min': 0,
400
+ 'max': 1000,
401
+ 'palette': ['blue', 'green', 'yellow', 'red']
402
+ }
403
+ pop_map_id = population.getMapId(pop_vis)
404
+ folium.TileLayer(
405
+ tiles=pop_map_id['tile_fetcher'].url_format,
406
+ attr='Google Earth Engine',
407
+ name='World Population',
408
+ overlay=True,
409
+ control=True
410
+ ).add_to(folium_map)
411
+
412
+ elif selected_dataset == "COPERNICUS":
413
+ dataset = ee.ImageCollection('COPERNICUS/S2') \
414
+ .filterBounds(ee_object) \
415
+ .filter(ee.Filter.date(start_date_str, end_date_str))
416
+
417
+ sentinel = dataset.median().clip(ee_object)
418
+ vis_params = {
419
+ 'bands': ['B4', 'B3', 'B2'],
420
+ 'min': 0,
421
+ 'max': 3000,
422
+ 'gamma': 1.4
423
+ }
424
+ copernicus_map_id = sentinel.getMapId(vis_params)
425
+ folium.TileLayer(
426
+ tiles=copernicus_map_id['tile_fetcher'].url_format,
427
+ attr='Google Earth Engine',
428
+ name='Copernicus Sentinel-2',
429
+ overlay=True,
430
+ control=True
431
+ ).add_to(folium_map)
432
+
433
+ folium_map.add_child(folium.LayerControl())
434
+ except Exception as e:
435
+ st.error(f"Error processing dataset: {e}")
436
+
437
+ folium_map_html = folium_map._repr_html_()
438
+ return folium_map_html
439
+
440
+ def handle_submit(selected_dataset, selected_date_range_From, selected_date_range_To, selected_shape):
441
+ shapefile_name = f'{selected_shape}.shp'
442
+ shapefile_path = os.path.join(SHAPEFILE_DIR, shapefile_name)
443
+
444
+ if os.path.exists(shapefile_path):
445
+ try:
446
+ roi_gdf = gpd.read_file(shapefile_path)
447
+ roi_geojson = roi_gdf.to_crs("EPSG:4326").to_json()
448
+ except Exception as e:
449
+ st.error(f"Error reading shapefile: {e}")
450
+ return
451
+
452
+ try:
453
+ ee_object = geemap.geojson_to_ee(json.loads(roi_geojson))
454
+ except Exception as e:
455
+ st.error(f"Error converting GeoJSON to Earth Engine object: {e}")
456
+ return
457
+
458
+ st.markdown("### Satellite Data Map")
459
+ folium_map_html = create_folium_map(
460
+ selected_dataset,
461
+ ee_object,
462
+ selected_date_range_From.strftime('%Y-%m-%d'),
463
+ selected_date_range_To.strftime('%Y-%m-%d')
464
+ )
465
+ html(folium_map_html, height=600)
466
+ else:
467
+ st.error("Selected shapefile does not exist.")
468
+
469
+ def submit_control():
470
+ selected_dataset = st.sidebar.selectbox(
471
+ "Select Dataset",
472
+ ["Modis", "dataset_nighttime", 'precipitation', 'GlobalSurfaceWater', 'WorldPop', 'COPERNICUS']
473
+ )
474
+
475
+ selected_date_range_From = st.sidebar.date_input("From", value=pd.to_datetime("2015-07-01"))
476
+ selected_date_range_To = st.sidebar.date_input("To", value=pd.to_datetime("2023-09-30"))
477
+
478
+ shape_options = [
479
+ 'District_Boundary', 'hydro_basins', 'karachi',
480
+ 'National_Constituency_with_Projected_2010_Population',
481
+ 'Provincial_Boundary', 'Provincial_Constituency',
482
+ 'Tehsil_Boundary', 'Union_Council'
483
+ ]
484
+
485
+ selected_shape = st.sidebar.selectbox("Select Shape", shape_options)
486
+
487
+ if st.sidebar.button("Submit"):
488
+ st.session_state.selected_dataset = selected_dataset
489
+ st.session_state.selected_date_range_From = selected_date_range_From
490
+ st.session_state.selected_date_range_To = selected_date_range_To
491
+ st.session_state.selected_shape = selected_shape
492
+ st.session_state.submitted = True
493
+ else:
494
+ st.session_state.submitted = False
495
+
496
+ if 'submitted' in st.session_state and st.session_state.submitted:
497
+ handle_submit(
498
+ st.session_state.selected_dataset,
499
+ st.session_state.selected_date_range_From,
500
+ st.session_state.selected_date_range_To,
501
+ st.session_state.selected_shape
502
+ )
503
+
504
+ def main():
505
+ st.set_page_config(layout="wide")
506
+ st.title("Satellite Data Visualization")
507
+
508
+ initialize_gee()
509
+
510
+
511
+ if __name__ == "__main__":
512
+ main()
513
+
514
+ #<---------------------------------------------------------------------timelapse pagefunction which is calling it in home (Navigation Purpose)----------------------------------------------------------------------------------------------------->
515
+
516
+ def Timelapse_page():
517
+ try:
518
+ app()
519
+ except Exception as e:
520
+ pass
521
+
522
+ #<------------------------------------------------------------------- timelapse code--------------------------------------------------------------------------------------------------------->
523
+ #create timelapse
524
+
525
+ @st.cache_data
526
+ def ee_authenticate(token_name="EARTHENGINE_TOKEN"):
527
+ geemap.ee_initialize(token_name=token_name)
528
+
529
+
530
+ goes_rois = {
531
+ "Creek Fire, CA (2020-09-05)": {
532
+ "region": Polygon(
533
+ [
534
+ [-121.003418, 36.848857],
535
+ [-121.003418, 39.049052],
536
+ [-117.905273, 39.049052],
537
+ [-117.905273, 36.848857],
538
+ [-121.003418, 36.848857],
539
+ ]
540
+ ),
541
+ "start_time": "2020-09-05T15:00:00",
542
+ "end_time": "2020-09-06T02:00:00",
543
+ },
544
+ "Bomb Cyclone (2021-10-24)": {
545
+ "region": Polygon(
546
+ [
547
+ [-159.5954, 60.4088],
548
+ [-159.5954, 24.5178],
549
+ [-114.2438, 24.5178],
550
+ [-114.2438, 60.4088],
551
+ ]
552
+ ),
553
+ "start_time": "2021-10-24T14:00:00",
554
+ "end_time": "2021-10-25T01:00:00",
555
+ },
556
+ "Hunga Tonga Volcanic Eruption (2022-01-15)": {
557
+ "region": Polygon(
558
+ [
559
+ [-192.480469, -32.546813],
560
+ [-192.480469, -8.754795],
561
+ [-157.587891, -8.754795],
562
+ [-157.587891, -32.546813],
563
+ [-192.480469, -32.546813],
564
+ ]
565
+ ),
566
+ "start_time": "2022-01-15T03:00:00",
567
+ "end_time": "2022-01-15T07:00:00",
568
+ },
569
+ "Hunga Tonga Volcanic Eruption Closer Look (2022-01-15)": {
570
+ "region": Polygon(
571
+ [
572
+ [-178.901367, -22.958393],
573
+ [-178.901367, -17.85329],
574
+ [-171.452637, -17.85329],
575
+ [-171.452637, -22.958393],
576
+ [-178.901367, -22.958393],
577
+ ]
578
+ ),
579
+ "start_time": "2022-01-15T03:00:00",
580
+ "end_time": "2022-01-15T07:00:00",
581
+ },
582
+ }
583
+
584
+
585
+ landsat_rois = {
586
+ "Aral Sea": Polygon(
587
+ [
588
+ [57.667236, 43.834527],
589
+ [57.667236, 45.996962],
590
+ [61.12793, 45.996962],
591
+ [61.12793, 43.834527],
592
+ [57.667236, 43.834527],
593
+ ]
594
+ ),
595
+ "Dubai": Polygon(
596
+ [
597
+ [54.541626, 24.763044],
598
+ [54.541626, 25.427152],
599
+ [55.632019, 25.427152],
600
+ [55.632019, 24.763044],
601
+ [54.541626, 24.763044],
602
+ ]
603
+ ),
604
+ "Hong Kong International Airport": Polygon(
605
+ [
606
+ [113.825226, 22.198849],
607
+ [113.825226, 22.349758],
608
+ [114.085121, 22.349758],
609
+ [114.085121, 22.198849],
610
+ [113.825226, 22.198849],
611
+ ]
612
+ ),
613
+ "Las Vegas, NV": Polygon(
614
+ [
615
+ [-115.554199, 35.804449],
616
+ [-115.554199, 36.558188],
617
+ [-113.903503, 36.558188],
618
+ [-113.903503, 35.804449],
619
+ [-115.554199, 35.804449],
620
+ ]
621
+ ),
622
+ "Pucallpa, Peru": Polygon(
623
+ [
624
+ [-74.672699, -8.600032],
625
+ [-74.672699, -8.254983],
626
+ [-74.279938, -8.254983],
627
+ [-74.279938, -8.600032],
628
+ ]
629
+ ),
630
+ "Sierra Gorda, Chile": Polygon(
631
+ [
632
+ [-69.315491, -22.837104],
633
+ [-69.315491, -22.751488],
634
+ [-69.190006, -22.751488],
635
+ [-69.190006, -22.837104],
636
+ [-69.315491, -22.837104],
637
+ ]
638
+ ),
639
+ }
640
+
641
+ modis_rois = {
642
+ "World": Polygon(
643
+ [
644
+ [-171.210938, -57.136239],
645
+ [-171.210938, 79.997168],
646
+ [177.539063, 79.997168],
647
+ [177.539063, -57.136239],
648
+ [-171.210938, -57.136239],
649
+ ]
650
+ ),
651
+ "Africa": Polygon(
652
+ [
653
+ [-18.6983, 38.1446],
654
+ [-18.6983, -36.1630],
655
+ [52.2293, -36.1630],
656
+ [52.2293, 38.1446],
657
+ ]
658
+ ),
659
+ "USA": Polygon(
660
+ [
661
+ [-127.177734, 23.725012],
662
+ [-127.177734, 50.792047],
663
+ [-66.269531, 50.792047],
664
+ [-66.269531, 23.725012],
665
+ [-127.177734, 23.725012],
666
+ ]
667
+ ),
668
+ }
669
+
670
+ ocean_rois = {
671
+ "Gulf of Mexico": Polygon(
672
+ [
673
+ [-101.206055, 15.496032],
674
+ [-101.206055, 32.361403],
675
+ [-75.673828, 32.361403],
676
+ [-75.673828, 15.496032],
677
+ [-101.206055, 15.496032],
678
+ ]
679
+ ),
680
+ "North Atlantic Ocean": Polygon(
681
+ [
682
+ [-85.341797, 24.046464],
683
+ [-85.341797, 45.02695],
684
+ [-55.810547, 45.02695],
685
+ [-55.810547, 24.046464],
686
+ [-85.341797, 24.046464],
687
+ ]
688
+ ),
689
+ "World": Polygon(
690
+ [
691
+ [-171.210938, -57.136239],
692
+ [-171.210938, 79.997168],
693
+ [177.539063, 79.997168],
694
+ [177.539063, -57.136239],
695
+ [-171.210938, -57.136239],
696
+ ]
697
+ ),
698
+ }
699
+
700
+
701
+ @st.cache_data
702
+ def uploaded_file_to_gdf(data):
703
+ import tempfile
704
+ import os
705
+ import uuid
706
+
707
+ _, file_extension = os.path.splitext(data.name)
708
+ file_id = str(uuid.uuid4())
709
+ file_path = os.path.join(tempfile.gettempdir(), f"{file_id}{file_extension}")
710
+
711
+ with open(file_path, "wb") as file:
712
+ file.write(data.getbuffer())
713
+
714
+ if file_path.lower().endswith(".kml"):
715
+ fiona.drvsupport.supported_drivers["KML"] = "rw"
716
+ gdf = gpd.read_file(file_path, driver="KML")
717
+ else:
718
+ gdf = gpd.read_file(file_path)
719
+
720
+ return gdf
721
+
722
+
723
+ def app():
724
+
725
+ today = date.today()
726
+
727
+ st.title("Create Satellite Timelapse")
728
+
729
+ row1_col1, row1_col2 = st.columns([2, 1])
730
+
731
+ if st.session_state.get("zoom_level") is None:
732
+ st.session_state["zoom_level"] = 4
733
+
734
+ st.session_state["ee_asset_id"] = None
735
+ st.session_state["bands"] = None
736
+ st.session_state["palette"] = None
737
+ st.session_state["vis_params"] = None
738
+
739
+ with row1_col1:
740
+ ee_authenticate(token_name="EARTHENGINE_TOKEN")
741
+ m = geemap.Map(
742
+ basemap="HYBRID",
743
+ plugin_Draw=True,
744
+ Draw_export=True,
745
+ locate_control=True,
746
+ plugin_LatLngPopup=False,
747
+ )
748
+ m.add_basemap("ROADMAP")
749
+
750
+ with row1_col2:
751
+
752
+ keyword = st.text_input("Search for a location:", "")
753
+ if keyword:
754
+ locations = geemap.geocode(keyword)
755
+ if locations is not None and len(locations) > 0:
756
+ str_locations = [str(g)[1:-1] for g in locations]
757
+ location = st.selectbox("Select a location:", str_locations)
758
+ loc_index = str_locations.index(location)
759
+ selected_loc = locations[loc_index]
760
+ lat, lng = selected_loc.lat, selected_loc.lng
761
+ folium.Marker(location=[lat, lng], popup=location).add_to(m)
762
+ m.set_center(lng, lat, 12)
763
+ st.session_state["zoom_level"] = 12
764
+
765
+ collection = st.selectbox(
766
+ "Select a satellite image collection: ",
767
+ [
768
+ "Any Earth Engine ImageCollection",
769
+ "Landsat TM-ETM-OLI Surface Reflectance",
770
+ "Sentinel-2 MSI Surface Reflectance",
771
+ "Geostationary Operational Environmental Satellites (GOES)",
772
+ "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km",
773
+ "MODIS Gap filled Land Surface Temperature Daily",
774
+ "MODIS Ocean Color SMI",
775
+ "USDA National Agriculture Imagery Program (NAIP)","Modis",
776
+ "dataset_nighttime", 'precipitation', 'GlobalSurfaceWater', 'WorldPop', 'COPERNICUS'
777
+ ],
778
+ index=1,
779
+ )
780
+
781
+ if collection in [
782
+ "Landsat TM-ETM-OLI Surface Reflectance",
783
+ "Sentinel-2 MSI Surface Reflectance",
784
+ ]:
785
+ roi_options = ["Uploaded GeoJSON"] + list(landsat_rois.keys())
786
+
787
+ elif collection == "Geostationary Operational Environmental Satellites (GOES)":
788
+ roi_options = ["Uploaded GeoJSON"] + list(goes_rois.keys())
789
+
790
+ elif collection in [
791
+ "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km",
792
+ "MODIS Gap filled Land Surface Temperature Daily",
793
+ ]:
794
+ roi_options = ["Uploaded GeoJSON"] + list(modis_rois.keys())
795
+ elif collection == "MODIS Ocean Color SMI":
796
+ roi_options = ["Uploaded GeoJSON"] + list(ocean_rois.keys())
797
+ else:
798
+ roi_options = ["Uploaded GeoJSON"]
799
+
800
+ if collection == "Any Earth Engine ImageCollection":
801
+ keyword = st.text_input("Enter a keyword to search (e.g., MODIS):", "")
802
+ if keyword:
803
+
804
+ assets = geemap.search_ee_data(keyword)
805
+ ee_assets = []
806
+ for asset in assets:
807
+ if asset["ee_id_snippet"].startswith("ee.ImageCollection"):
808
+ ee_assets.append(asset)
809
+
810
+ asset_titles = [x["title"] for x in ee_assets]
811
+ dataset = st.selectbox("Select a dataset:", asset_titles)
812
+ if len(ee_assets) > 0:
813
+ st.session_state["ee_assets"] = ee_assets
814
+ st.session_state["asset_titles"] = asset_titles
815
+ index = asset_titles.index(dataset)
816
+ ee_id = ee_assets[index]["id"]
817
+ else:
818
+ ee_id = ""
819
+
820
+ if dataset is not None:
821
+ with st.expander("Show dataset details", False):
822
+ index = asset_titles.index(dataset)
823
+ html = geemap.ee_data_html(st.session_state["ee_assets"][index])
824
+ st.markdown(html, True)
825
+ # elif collection == "MODIS Gap filled Land Surface Temperature Daily":
826
+ # ee_id = ""
827
+ else:
828
+ ee_id = ""
829
+
830
+ asset_id = st.text_input("Enter an ee.ImageCollection asset ID:", ee_id)
831
+
832
+ if asset_id:
833
+ with st.expander("Customize band combination and color palette", True):
834
+ try:
835
+ col = ee.ImageCollection.load(asset_id)
836
+ st.session_state["ee_asset_id"] = asset_id
837
+ except:
838
+ st.error("Invalid Earth Engine asset ID.")
839
+ st.session_state["ee_asset_id"] = None
840
+ return
841
+
842
+ img_bands = col.first().bandNames().getInfo()
843
+ if len(img_bands) >= 3:
844
+ default_bands = img_bands[:3][::-1]
845
+ else:
846
+ default_bands = img_bands[:]
847
+ bands = st.multiselect(
848
+ "Select one or three bands (RGB):", img_bands, default_bands
849
+ )
850
+ st.session_state["bands"] = bands
851
+
852
+ if len(bands) == 1:
853
+ palette_options = st.selectbox(
854
+ "Color palette",
855
+ cm.list_colormaps(),
856
+ index=2,
857
+ )
858
+ palette_values = cm.get_palette(palette_options, 15)
859
+ palette = st.text_area(
860
+ "Enter a custom palette:",
861
+ palette_values,
862
+ )
863
+ st.write(
864
+ cm.plot_colormap(cmap=palette_options, return_fig=True)
865
+ )
866
+ st.session_state["palette"] = json.loads(
867
+ palette.replace("'", '"')
868
+ )
869
+
870
+ if bands:
871
+ vis_params = st.text_area(
872
+ "Enter visualization parameters",
873
+ "{'bands': ["
874
+ + ", ".join([f"'{band}'" for band in bands])
875
+ + "]}",
876
+ )
877
+ else:
878
+ vis_params = st.text_area(
879
+ "Enter visualization parameters",
880
+ "{}",
881
+ )
882
+ try:
883
+ st.session_state["vis_params"] = json.loads(
884
+ vis_params.replace("'", '"')
885
+ )
886
+ st.session_state["vis_params"]["palette"] = st.session_state[
887
+ "palette"
888
+ ]
889
+ except Exception as e:
890
+ st.session_state["vis_params"] = None
891
+ st.error(
892
+ f"Invalid visualization parameters. It must be a dictionary."
893
+ )
894
+
895
+
896
+ elif collection == "MODIS Gap filled Land Surface Temperature Daily":
897
+ with st.expander("Show dataset details", False):
898
+ st.markdown(
899
+ """
900
+ See the [Awesome GEE Community Datasets](https://samapriya.github.io/awesome-gee-community-datasets/projects/daily_lst/).
901
+ """
902
+ )
903
+
904
+ MODIS_options = ["Daytime (1:30 pm)", "Nighttime (1:30 am)"]
905
+ MODIS_option = st.selectbox("Select a MODIS dataset:", MODIS_options)
906
+ if MODIS_option == "Daytime (1:30 pm)":
907
+ st.session_state["ee_asset_id"] = (
908
+ "projects/sat-io/open-datasets/gap-filled-lst/gf_day_1km"
909
+ )
910
+ else:
911
+ st.session_state["ee_asset_id"] = (
912
+ "projects/sat-io/open-datasets/gap-filled-lst/gf_night_1km"
913
+ )
914
+
915
+ palette_options = st.selectbox(
916
+ "Color palette",
917
+ cm.list_colormaps(),
918
+ index=90,
919
+ )
920
+ palette_values = cm.get_palette(palette_options, 15)
921
+ palette = st.text_area(
922
+ "Enter a custom palette:",
923
+ palette_values,
924
+ )
925
+ st.write(cm.plot_colormap(cmap=palette_options, return_fig=True))
926
+ st.session_state["palette"] = json.loads(palette.replace("'", '"'))
927
+ elif collection == "MODIS Ocean Color SMI":
928
+ with st.expander("Show dataset details", False):
929
+ st.markdown(
930
+ """
931
+ See the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog/NASA_OCEANDATA_MODIS-Aqua_L3SMI).
932
+ """
933
+ )
934
+
935
+ MODIS_options = ["Aqua", "Terra"]
936
+ MODIS_option = st.selectbox("Select a satellite:", MODIS_options)
937
+ st.session_state["ee_asset_id"] = MODIS_option
938
+ # if MODIS_option == "Daytime (1:30 pm)":
939
+ # st.session_state[
940
+ # "ee_asset_id"
941
+ # ] = "projects/sat-io/open-datasets/gap-filled-lst/gf_day_1km"
942
+ # else:
943
+ # st.session_state[
944
+ # "ee_asset_id"
945
+ # ] = "projects/sat-io/open-datasets/gap-filled-lst/gf_night_1km"
946
+
947
+ band_dict = {
948
+ "Chlorophyll a concentration": "chlor_a",
949
+ "Normalized fluorescence line height": "nflh",
950
+ "Particulate organic carbon": "poc",
951
+ "Sea surface temperature": "sst",
952
+ "Remote sensing reflectance at band 412nm": "Rrs_412",
953
+ "Remote sensing reflectance at band 443nm": "Rrs_443",
954
+ "Remote sensing reflectance at band 469nm": "Rrs_469",
955
+ "Remote sensing reflectance at band 488nm": "Rrs_488",
956
+ "Remote sensing reflectance at band 531nm": "Rrs_531",
957
+ "Remote sensing reflectance at band 547nm": "Rrs_547",
958
+ "Remote sensing reflectance at band 555nm": "Rrs_555",
959
+ "Remote sensing reflectance at band 645nm": "Rrs_645",
960
+ "Remote sensing reflectance at band 667nm": "Rrs_667",
961
+ "Remote sensing reflectance at band 678nm": "Rrs_678",
962
+ }
963
+
964
+ band_options = list(band_dict.keys())
965
+ band = st.selectbox(
966
+ "Select a band",
967
+ band_options,
968
+ band_options.index("Sea surface temperature"),
969
+ )
970
+ st.session_state["band"] = band_dict[band]
971
+
972
+ colors = cm.list_colormaps()
973
+ palette_options = st.selectbox(
974
+ "Color palette",
975
+ colors,
976
+ index=colors.index("coolwarm"),
977
+ )
978
+ palette_values = cm.get_palette(palette_options, 15)
979
+ palette = st.text_area(
980
+ "Enter a custom palette:",
981
+ palette_values,
982
+ )
983
+ st.write(cm.plot_colormap(cmap=palette_options, return_fig=True))
984
+ st.session_state["palette"] = json.loads(palette.replace("'", '"'))
985
+
986
+ sample_roi = st.selectbox(
987
+ "Select a sample ROI or upload a GeoJSON file:",
988
+ roi_options,
989
+ index=0,
990
+ )
991
+
992
+ add_outline = st.checkbox(
993
+ "Overlay an administrative boundary on timelapse", False
994
+ )
995
+
996
+ if add_outline:
997
+
998
+ with st.expander("Customize administrative boundary", True):
999
+
1000
+ overlay_options = {
1001
+ "User-defined": None,
1002
+ "Continents": "continents",
1003
+ "Countries": "countries",
1004
+ "US States": "us_states",
1005
+ "China": "china",
1006
+ }
1007
+
1008
+ overlay = st.selectbox(
1009
+ "Select an administrative boundary:",
1010
+ list(overlay_options.keys()),
1011
+ index=2,
1012
+ )
1013
+
1014
+ overlay_data = overlay_options[overlay]
1015
+
1016
+ if overlay_data is None:
1017
+ overlay_data = st.text_input(
1018
+ "Enter an HTTP URL to a GeoJSON file or an ee.FeatureCollection asset id:",
1019
+ "https://raw.githubusercontent.com/giswqs/geemap/master/examples/data/countries.geojson",
1020
+ )
1021
+
1022
+ overlay_color = st.color_picker(
1023
+ "Select a color for the administrative boundary:", "#000000"
1024
+ )
1025
+ overlay_width = st.slider(
1026
+ "Select a line width for the administrative boundary:", 1, 20, 1
1027
+ )
1028
+ overlay_opacity = st.slider(
1029
+ "Select an opacity for the administrative boundary:",
1030
+ 0.0,
1031
+ 1.0,
1032
+ 1.0,
1033
+ 0.05,
1034
+ )
1035
+ else:
1036
+ overlay_data = None
1037
+ overlay_color = "black"
1038
+ overlay_width = 1
1039
+ overlay_opacity = 1
1040
+
1041
+ with row1_col1:
1042
+
1043
+ with st.expander(
1044
+ "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 👉"
1045
+ ):
1046
+ video_empty = st.empty()
1047
+
1048
+ data = st.file_uploader(
1049
+ "Upload a GeoJSON file to use as an ROI. Customize timelapse parameters and then click the Submit button 😇👇",
1050
+ type=["geojson", "kml", "zip"],
1051
+ )
1052
+
1053
+ crs = "epsg:4326"
1054
+ if sample_roi == "Uploaded GeoJSON":
1055
+ if data is None:
1056
+ # st.info(
1057
+ # "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"
1058
+ # )
1059
+ if collection in [
1060
+ "Geostationary Operational Environmental Satellites (GOES)",
1061
+ "USDA National Agriculture Imagery Program (NAIP)",
1062
+ ] and (not keyword):
1063
+ m.set_center(-100, 40, 3)
1064
+ # else:
1065
+ # m.set_center(4.20, 18.63, zoom=2)
1066
+ else:
1067
+ if collection in [
1068
+ "Landsat TM-ETM-OLI Surface Reflectance",
1069
+ "Sentinel-2 MSI Surface Reflectance",
1070
+ ]:
1071
+ gdf = gpd.GeoDataFrame(
1072
+ index=[0], crs=crs, geometry=[landsat_rois[sample_roi]]
1073
+ )
1074
+ elif (
1075
+ collection
1076
+ == "Geostationary Operational Environmental Satellites (GOES)"
1077
+ ):
1078
+ gdf = gpd.GeoDataFrame(
1079
+ index=[0], crs=crs, geometry=[goes_rois[sample_roi]["region"]]
1080
+ )
1081
+ elif collection == "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km":
1082
+ gdf = gpd.GeoDataFrame(
1083
+ index=[0], crs=crs, geometry=[modis_rois[sample_roi]]
1084
+ )
1085
+
1086
+ if sample_roi != "Uploaded GeoJSON":
1087
+
1088
+ if collection in [
1089
+ "Landsat TM-ETM-OLI Surface Reflectance",
1090
+ "Sentinel-2 MSI Surface Reflectance",
1091
+ ]:
1092
+ gdf = gpd.GeoDataFrame(
1093
+ index=[0], crs=crs, geometry=[landsat_rois[sample_roi]]
1094
+ )
1095
+ elif (
1096
+ collection
1097
+ == "Geostationary Operational Environmental Satellites (GOES)"
1098
+ ):
1099
+ gdf = gpd.GeoDataFrame(
1100
+ index=[0], crs=crs, geometry=[goes_rois[sample_roi]["region"]]
1101
+ )
1102
+ elif collection in [
1103
+ "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km",
1104
+ "MODIS Gap filled Land Surface Temperature Daily",
1105
+ ]:
1106
+ gdf = gpd.GeoDataFrame(
1107
+ index=[0], crs=crs, geometry=[modis_rois[sample_roi]]
1108
+ )
1109
+ elif collection == "MODIS Ocean Color SMI":
1110
+ gdf = gpd.GeoDataFrame(
1111
+ index=[0], crs=crs, geometry=[ocean_rois[sample_roi]]
1112
+ )
1113
+ try:
1114
+ st.session_state["roi"] = geemap.gdf_to_ee(gdf, geodesic=False)
1115
+ except Exception as e:
1116
+ st.error(e)
1117
+ st.error("Please draw another ROI and try again.")
1118
+ return
1119
+ m.add_gdf(gdf, "ROI")
1120
+
1121
+ elif data:
1122
+ gdf = uploaded_file_to_gdf(data)
1123
+ try:
1124
+ st.session_state["roi"] = geemap.gdf_to_ee(gdf, geodesic=False)
1125
+ m.add_gdf(gdf, "ROI")
1126
+ except Exception as e:
1127
+ st.error(e)
1128
+ st.error("Please draw another ROI and try again.")
1129
+ return
1130
+
1131
+ m.to_streamlit(height=600)
1132
+
1133
+ with row1_col2:
1134
+
1135
+ if collection in [
1136
+ "Landsat TM-ETM-OLI Surface Reflectance",
1137
+ "Sentinel-2 MSI Surface Reflectance",
1138
+ ]:
1139
+
1140
+ if collection == "Landsat TM-ETM-OLI Surface Reflectance":
1141
+ sensor_start_year = 1984
1142
+ timelapse_title = "Landsat Timelapse"
1143
+ timelapse_speed = 5
1144
+ elif collection == "Sentinel-2 MSI Surface Reflectance":
1145
+ sensor_start_year = 2015
1146
+ timelapse_title = "Sentinel-2 Timelapse"
1147
+ timelapse_speed = 5
1148
+ video_empty.video("https://youtu.be/VVRK_-dEjR4")
1149
+
1150
+ with st.form("submit_landsat_form"):
1151
+
1152
+ roi = None
1153
+ if st.session_state.get("roi") is not None:
1154
+ roi = st.session_state.get("roi")
1155
+ out_gif = geemap.temp_file_path(".gif")
1156
+
1157
+ title = st.text_input(
1158
+ "Enter a title to show on the timelapse: ", timelapse_title
1159
+ )
1160
+ RGB = st.selectbox(
1161
+ "Select an RGB band combination:",
1162
+ [
1163
+ "Red/Green/Blue",
1164
+ "NIR/Red/Green",
1165
+ "SWIR2/SWIR1/NIR",
1166
+ "NIR/SWIR1/Red",
1167
+ "SWIR2/NIR/Red",
1168
+ "SWIR2/SWIR1/Red",
1169
+ "SWIR1/NIR/Blue",
1170
+ "NIR/SWIR1/Blue",
1171
+ "SWIR2/NIR/Green",
1172
+ "SWIR1/NIR/Red",
1173
+ "SWIR2/NIR/SWIR1",
1174
+ "SWIR1/NIR/SWIR2",
1175
+ ],
1176
+ index=9,
1177
+ )
1178
+
1179
+ frequency = st.selectbox(
1180
+ "Select a temporal frequency:",
1181
+ ["year", "quarter", "month"],
1182
+ index=0,
1183
+ )
1184
+
1185
+ with st.expander("Customize timelapse"):
1186
+
1187
+ speed = st.slider("Frames per second:", 1, 30, timelapse_speed)
1188
+ dimensions = st.slider(
1189
+ "Maximum dimensions (Width*Height) in pixels", 768, 2000, 768
1190
+ )
1191
+ progress_bar_color = st.color_picker(
1192
+ "Progress bar color:", "#0000ff"
1193
+ )
1194
+ years = st.slider(
1195
+ "Start and end year:",
1196
+ sensor_start_year,
1197
+ today.year,
1198
+ (sensor_start_year, today.year),
1199
+ )
1200
+ months = st.slider("Start and end month:", 1, 12, (1, 12))
1201
+ font_size = st.slider("Font size:", 10, 50, 30)
1202
+ font_color = st.color_picker("Font color:", "#ffffff")
1203
+ apply_fmask = st.checkbox(
1204
+ "Apply fmask (remove clouds, shadows, snow)", True
1205
+ )
1206
+ font_type = st.selectbox(
1207
+ "Select the font type for the title:",
1208
+ ["arial.ttf", "alibaba.otf"],
1209
+ index=0,
1210
+ )
1211
+ fading = st.slider(
1212
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1213
+ )
1214
+ mp4 = st.checkbox("Save timelapse as MP4", True)
1215
+
1216
+ empty_text = st.empty()
1217
+ empty_image = st.empty()
1218
+ empty_fire_image = st.empty()
1219
+ empty_video = st.container()
1220
+ submitted = st.form_submit_button("Submit")
1221
+ if submitted:
1222
+
1223
+ if sample_roi == "Uploaded GeoJSON" and data is None:
1224
+ empty_text.warning(
1225
+ "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."
1226
+ )
1227
+ else:
1228
+
1229
+ empty_text.text("Computing... Please wait...")
1230
+
1231
+ start_year = years[0]
1232
+ end_year = years[1]
1233
+ start_date = str(months[0]).zfill(2) + "-01"
1234
+ end_date = str(months[1]).zfill(2) + "-30"
1235
+ bands = RGB.split("/")
1236
+
1237
+ try:
1238
+ if collection == "Landsat TM-ETM-OLI Surface Reflectance":
1239
+ out_gif = geemap.landsat_timelapse(
1240
+ roi=roi,
1241
+ out_gif=out_gif,
1242
+ start_year=start_year,
1243
+ end_year=end_year,
1244
+ start_date=start_date,
1245
+ end_date=end_date,
1246
+ bands=bands,
1247
+ apply_fmask=apply_fmask,
1248
+ frames_per_second=speed,
1249
+ # dimensions=dimensions,
1250
+ dimensions=768,
1251
+ overlay_data=overlay_data,
1252
+ overlay_color=overlay_color,
1253
+ overlay_width=overlay_width,
1254
+ overlay_opacity=overlay_opacity,
1255
+ frequency=frequency,
1256
+ date_format=None,
1257
+ title=title,
1258
+ title_xy=("2%", "90%"),
1259
+ add_text=True,
1260
+ text_xy=("2%", "2%"),
1261
+ text_sequence=None,
1262
+ font_type=font_type,
1263
+ font_size=font_size,
1264
+ font_color=font_color,
1265
+ add_progress_bar=True,
1266
+ progress_bar_color=progress_bar_color,
1267
+ progress_bar_height=5,
1268
+ loop=0,
1269
+ mp4=mp4,
1270
+ fading=fading,
1271
+ )
1272
+ elif collection == "Sentinel-2 MSI Surface Reflectance":
1273
+ out_gif = geemap.sentinel2_timelapse(
1274
+ roi=roi,
1275
+ out_gif=out_gif,
1276
+ start_year=start_year,
1277
+ end_year=end_year,
1278
+ start_date=start_date,
1279
+ end_date=end_date,
1280
+ bands=bands,
1281
+ apply_fmask=apply_fmask,
1282
+ frames_per_second=speed,
1283
+ dimensions=768,
1284
+ # dimensions=dimensions,
1285
+ overlay_data=overlay_data,
1286
+ overlay_color=overlay_color,
1287
+ overlay_width=overlay_width,
1288
+ overlay_opacity=overlay_opacity,
1289
+ frequency=frequency,
1290
+ date_format=None,
1291
+ title=title,
1292
+ title_xy=("2%", "90%"),
1293
+ add_text=True,
1294
+ text_xy=("2%", "2%"),
1295
+ text_sequence=None,
1296
+ font_type=font_type,
1297
+ font_size=font_size,
1298
+ font_color=font_color,
1299
+ add_progress_bar=True,
1300
+ progress_bar_color=progress_bar_color,
1301
+ progress_bar_height=5,
1302
+ loop=0,
1303
+ mp4=mp4,
1304
+ fading=fading,
1305
+ )
1306
+ except:
1307
+ empty_text.error(
1308
+ "An error occurred while computing the timelapse. Your probably requested too much data. Try reducing the ROI or timespan."
1309
+ )
1310
+ st.stop()
1311
+
1312
+ if out_gif is not None and os.path.exists(out_gif):
1313
+
1314
+ empty_text.text(
1315
+ "Right click the GIF to save it to your computer👇"
1316
+ )
1317
+ empty_image.image(out_gif)
1318
+
1319
+ out_mp4 = out_gif.replace(".gif", ".mp4")
1320
+ if mp4 and os.path.exists(out_mp4):
1321
+ with empty_video:
1322
+ st.text(
1323
+ "Right click the MP4 to save it to your computer👇"
1324
+ )
1325
+ st.video(out_gif.replace(".gif", ".mp4"))
1326
+
1327
+ else:
1328
+ empty_text.error(
1329
+ "Something went wrong. You probably requested too much data. Try reducing the ROI or timespan."
1330
+ )
1331
+
1332
+ elif collection == "Geostationary Operational Environmental Satellites (GOES)":
1333
+
1334
+ video_empty.video("https://youtu.be/16fA2QORG4A")
1335
+
1336
+ with st.form("submit_goes_form"):
1337
+
1338
+ roi = None
1339
+ if st.session_state.get("roi") is not None:
1340
+ roi = st.session_state.get("roi")
1341
+ out_gif = geemap.temp_file_path(".gif")
1342
+
1343
+ satellite = st.selectbox("Select a satellite:", ["GOES-17", "GOES-16"])
1344
+ earliest_date = datetime.date(2017, 7, 10)
1345
+ latest_date = datetime.date.today()
1346
+
1347
+ if sample_roi == "Uploaded GeoJSON":
1348
+ roi_start_date = today - datetime.timedelta(days=2)
1349
+ roi_end_date = today - datetime.timedelta(days=1)
1350
+ roi_start_time = datetime.time(14, 00)
1351
+ roi_end_time = datetime.time(1, 00)
1352
+ else:
1353
+ roi_start = goes_rois[sample_roi]["start_time"]
1354
+ roi_end = goes_rois[sample_roi]["end_time"]
1355
+ roi_start_date = datetime.datetime.strptime(
1356
+ roi_start[:10], "%Y-%m-%d"
1357
+ )
1358
+ roi_end_date = datetime.datetime.strptime(roi_end[:10], "%Y-%m-%d")
1359
+ roi_start_time = datetime.time(
1360
+ int(roi_start[11:13]), int(roi_start[14:16])
1361
+ )
1362
+ roi_end_time = datetime.time(
1363
+ int(roi_end[11:13]), int(roi_end[14:16])
1364
+ )
1365
+
1366
+ start_date = st.date_input("Select the start date:", roi_start_date)
1367
+ end_date = st.date_input("Select the end date:", roi_end_date)
1368
+
1369
+ with st.expander("Customize timelapse"):
1370
+
1371
+ add_fire = st.checkbox("Add Fire/Hotspot Characterization", False)
1372
+
1373
+ scan_type = st.selectbox(
1374
+ "Select a scan type:", ["Full Disk", "CONUS", "Mesoscale"]
1375
+ )
1376
+
1377
+ start_time = st.time_input(
1378
+ "Select the start time of the start date:", roi_start_time
1379
+ )
1380
+
1381
+ end_time = st.time_input(
1382
+ "Select the end time of the end date:", roi_end_time
1383
+ )
1384
+
1385
+ start = (
1386
+ start_date.strftime("%Y-%m-%d")
1387
+ + "T"
1388
+ + start_time.strftime("%H:%M:%S")
1389
+ )
1390
+ end = (
1391
+ end_date.strftime("%Y-%m-%d")
1392
+ + "T"
1393
+ + end_time.strftime("%H:%M:%S")
1394
+ )
1395
+
1396
+ speed = st.slider("Frames per second:", 1, 30, 5)
1397
+ add_progress_bar = st.checkbox("Add a progress bar", True)
1398
+ progress_bar_color = st.color_picker(
1399
+ "Progress bar color:", "#0000ff"
1400
+ )
1401
+ font_size = st.slider("Font size:", 10, 50, 20)
1402
+ font_color = st.color_picker("Font color:", "#ffffff")
1403
+ fading = st.slider(
1404
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1405
+ )
1406
+ mp4 = st.checkbox("Save timelapse as MP4", True)
1407
+
1408
+ empty_text = st.empty()
1409
+ empty_image = st.empty()
1410
+ empty_video = st.container()
1411
+ empty_fire_text = st.empty()
1412
+ empty_fire_image = st.empty()
1413
+
1414
+ submitted = st.form_submit_button("Submit")
1415
+ if submitted:
1416
+ if sample_roi == "Uploaded GeoJSON" and data is None:
1417
+ empty_text.warning(
1418
+ "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."
1419
+ )
1420
+ else:
1421
+ empty_text.text("Computing... Please wait...")
1422
+
1423
+ geemap.goes_timelapse(
1424
+ roi,
1425
+ out_gif,
1426
+ start_date=start,
1427
+ end_date=end,
1428
+ data=satellite,
1429
+ scan=scan_type.replace(" ", "_").lower(),
1430
+ dimensions=768,
1431
+ framesPerSecond=speed,
1432
+ date_format="YYYY-MM-dd HH:mm",
1433
+ xy=("3%", "3%"),
1434
+ text_sequence=None,
1435
+ font_type="arial.ttf",
1436
+ font_size=font_size,
1437
+ font_color=font_color,
1438
+ add_progress_bar=add_progress_bar,
1439
+ progress_bar_color=progress_bar_color,
1440
+ progress_bar_height=5,
1441
+ loop=0,
1442
+ overlay_data=overlay_data,
1443
+ overlay_color=overlay_color,
1444
+ overlay_width=overlay_width,
1445
+ overlay_opacity=overlay_opacity,
1446
+ mp4=mp4,
1447
+ fading=fading,
1448
+ )
1449
+
1450
+ if out_gif is not None and os.path.exists(out_gif):
1451
+ empty_text.text(
1452
+ "Right click the GIF to save it to your computer👇"
1453
+ )
1454
+ empty_image.image(out_gif)
1455
+
1456
+ out_mp4 = out_gif.replace(".gif", ".mp4")
1457
+ if mp4 and os.path.exists(out_mp4):
1458
+ with empty_video:
1459
+ st.text(
1460
+ "Right click the MP4 to save it to your computer👇"
1461
+ )
1462
+ st.video(out_gif.replace(".gif", ".mp4"))
1463
+
1464
+ if add_fire:
1465
+ out_fire_gif = geemap.temp_file_path(".gif")
1466
+ empty_fire_text.text(
1467
+ "Delineating Fire Hotspot... Please wait..."
1468
+ )
1469
+ geemap.goes_fire_timelapse(
1470
+ out_fire_gif,
1471
+ start_date=start,
1472
+ end_date=end,
1473
+ data=satellite,
1474
+ scan=scan_type.replace(" ", "_").lower(),
1475
+ region=roi,
1476
+ dimensions=768,
1477
+ framesPerSecond=speed,
1478
+ date_format="YYYY-MM-dd HH:mm",
1479
+ xy=("3%", "3%"),
1480
+ text_sequence=None,
1481
+ font_type="arial.ttf",
1482
+ font_size=font_size,
1483
+ font_color=font_color,
1484
+ add_progress_bar=add_progress_bar,
1485
+ progress_bar_color=progress_bar_color,
1486
+ progress_bar_height=5,
1487
+ loop=0,
1488
+ )
1489
+ if os.path.exists(out_fire_gif):
1490
+ empty_fire_image.image(out_fire_gif)
1491
+ else:
1492
+ empty_text.text(
1493
+ "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."
1494
+ )
1495
+
1496
+ elif collection == "MODIS Vegetation Indices (NDVI/EVI) 16-Day Global 1km":
1497
+
1498
+ video_empty.video("https://youtu.be/16fA2QORG4A")
1499
+
1500
+ satellite = st.selectbox("Select a satellite:", ["Terra", "Aqua"])
1501
+ band = st.selectbox("Select a band:", ["NDVI", "EVI"])
1502
+
1503
+ with st.form("submit_modis_form"):
1504
+
1505
+ roi = None
1506
+ if st.session_state.get("roi") is not None:
1507
+ roi = st.session_state.get("roi")
1508
+ out_gif = geemap.temp_file_path(".gif")
1509
+
1510
+ with st.expander("Customize timelapse"):
1511
+
1512
+ start = st.date_input(
1513
+ "Select a start date:", datetime.date(2000, 2, 8)
1514
+ )
1515
+ end = st.date_input("Select an end date:", datetime.date.today())
1516
+
1517
+ start_date = start.strftime("%Y-%m-%d")
1518
+ end_date = end.strftime("%Y-%m-%d")
1519
+
1520
+ speed = st.slider("Frames per second:", 1, 30, 5)
1521
+ add_progress_bar = st.checkbox("Add a progress bar", True)
1522
+ progress_bar_color = st.color_picker(
1523
+ "Progress bar color:", "#0000ff"
1524
+ )
1525
+ font_size = st.slider("Font size:", 10, 50, 20)
1526
+ font_color = st.color_picker("Font color:", "#ffffff")
1527
+
1528
+ font_type = st.selectbox(
1529
+ "Select the font type for the title:",
1530
+ ["arial.ttf", "alibaba.otf"],
1531
+ index=0,
1532
+ )
1533
+ fading = st.slider(
1534
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1535
+ )
1536
+ mp4 = st.checkbox("Save timelapse as MP4", True)
1537
+
1538
+ empty_text = st.empty()
1539
+ empty_image = st.empty()
1540
+ empty_video = st.container()
1541
+
1542
+ submitted = st.form_submit_button("Submit")
1543
+ if submitted:
1544
+ if sample_roi == "Uploaded GeoJSON" and data is None:
1545
+ empty_text.warning(
1546
+ "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."
1547
+ )
1548
+ else:
1549
+
1550
+ empty_text.text("Computing... Please wait...")
1551
+
1552
+ geemap.modis_ndvi_timelapse(
1553
+ roi,
1554
+ out_gif,
1555
+ satellite,
1556
+ band,
1557
+ start_date,
1558
+ end_date,
1559
+ 768,
1560
+ speed,
1561
+ overlay_data=overlay_data,
1562
+ overlay_color=overlay_color,
1563
+ overlay_width=overlay_width,
1564
+ overlay_opacity=overlay_opacity,
1565
+ mp4=mp4,
1566
+ fading=fading,
1567
+ )
1568
+
1569
+ geemap.reduce_gif_size(out_gif)
1570
+
1571
+ empty_text.text(
1572
+ "Right click the GIF to save it to your computer👇"
1573
+ )
1574
+ empty_image.image(out_gif)
1575
+
1576
+ out_mp4 = out_gif.replace(".gif", ".mp4")
1577
+ if mp4 and os.path.exists(out_mp4):
1578
+ with empty_video:
1579
+ st.text(
1580
+ "Right click the MP4 to save it to your computer👇"
1581
+ )
1582
+ st.video(out_gif.replace(".gif", ".mp4"))
1583
+
1584
+ elif collection == "Any Earth Engine ImageCollection":
1585
+
1586
+ with st.form("submit_ts_form"):
1587
+ with st.expander("Customize timelapse"):
1588
+
1589
+ title = st.text_input(
1590
+ "Enter a title to show on the timelapse: ", "Timelapse"
1591
+ )
1592
+ start_date = st.date_input(
1593
+ "Select the start date:", datetime.date(2020, 1, 1)
1594
+ )
1595
+ end_date = st.date_input(
1596
+ "Select the end date:", datetime.date.today()
1597
+ )
1598
+ frequency = st.selectbox(
1599
+ "Select a temporal frequency:",
1600
+ ["year", "quarter", "month", "day", "hour", "minute", "second"],
1601
+ index=0,
1602
+ )
1603
+ reducer = st.selectbox(
1604
+ "Select a reducer for aggregating data:",
1605
+ ["median", "mean", "min", "max", "sum", "variance", "stdDev"],
1606
+ index=0,
1607
+ )
1608
+ data_format = st.selectbox(
1609
+ "Select a date format to show on the timelapse:",
1610
+ [
1611
+ "YYYY-MM-dd",
1612
+ "YYYY",
1613
+ "YYMM-MM",
1614
+ "YYYY-MM-dd HH:mm",
1615
+ "YYYY-MM-dd HH:mm:ss",
1616
+ "HH:mm",
1617
+ "HH:mm:ss",
1618
+ "w",
1619
+ "M",
1620
+ "d",
1621
+ "D",
1622
+ ],
1623
+ index=0,
1624
+ )
1625
+
1626
+ speed = st.slider("Frames per second:", 1, 30, 5)
1627
+ add_progress_bar = st.checkbox("Add a progress bar", True)
1628
+ progress_bar_color = st.color_picker(
1629
+ "Progress bar color:", "#0000ff"
1630
+ )
1631
+ font_size = st.slider("Font size:", 10, 50, 30)
1632
+ font_color = st.color_picker("Font color:", "#ffffff")
1633
+ font_type = st.selectbox(
1634
+ "Select the font type for the title:",
1635
+ ["arial.ttf", "alibaba.otf"],
1636
+ index=0,
1637
+ )
1638
+ fading = st.slider(
1639
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1640
+ )
1641
+ mp4 = st.checkbox("Save timelapse as MP4", True)
1642
+
1643
+ empty_text = st.empty()
1644
+ empty_image = st.empty()
1645
+ empty_video = st.container()
1646
+ empty_fire_image = st.empty()
1647
+
1648
+ roi = None
1649
+ if st.session_state.get("roi") is not None:
1650
+ roi = st.session_state.get("roi")
1651
+ out_gif = geemap.temp_file_path(".gif")
1652
+
1653
+ submitted = st.form_submit_button("Submit")
1654
+ if submitted:
1655
+
1656
+ if sample_roi == "Uploaded GeoJSON" and data is None:
1657
+ empty_text.warning(
1658
+ "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."
1659
+ )
1660
+ else:
1661
+
1662
+ empty_text.text("Computing... Please wait...")
1663
+ try:
1664
+ geemap.create_timelapse(
1665
+ st.session_state.get("ee_asset_id"),
1666
+ start_date=start_date.strftime("%Y-%m-%d"),
1667
+ end_date=end_date.strftime("%Y-%m-%d"),
1668
+ region=roi,
1669
+ frequency=frequency,
1670
+ reducer=reducer,
1671
+ date_format=data_format,
1672
+ out_gif=out_gif,
1673
+ bands=st.session_state.get("bands"),
1674
+ palette=st.session_state.get("palette"),
1675
+ vis_params=st.session_state.get("vis_params"),
1676
+ dimensions=768,
1677
+ frames_per_second=speed,
1678
+ crs="EPSG:3857",
1679
+ overlay_data=overlay_data,
1680
+ overlay_color=overlay_color,
1681
+ overlay_width=overlay_width,
1682
+ overlay_opacity=overlay_opacity,
1683
+ title=title,
1684
+ title_xy=("2%", "90%"),
1685
+ add_text=True,
1686
+ text_xy=("2%", "2%"),
1687
+ text_sequence=None,
1688
+ font_type=font_type,
1689
+ font_size=font_size,
1690
+ font_color=font_color,
1691
+ add_progress_bar=add_progress_bar,
1692
+ progress_bar_color=progress_bar_color,
1693
+ progress_bar_height=5,
1694
+ loop=0,
1695
+ mp4=mp4,
1696
+ fading=fading,
1697
+ )
1698
+ except:
1699
+ empty_text.error(
1700
+ "An error occurred while computing the timelapse. You probably requested too much data. Try reducing the ROI or timespan."
1701
+ )
1702
+
1703
+ empty_text.text(
1704
+ "Right click the GIF to save it to your computer👇"
1705
+ )
1706
+ empty_image.image(out_gif)
1707
+
1708
+ out_mp4 = out_gif.replace(".gif", ".mp4")
1709
+ if mp4 and os.path.exists(out_mp4):
1710
+ with empty_video:
1711
+ st.text(
1712
+ "Right click the MP4 to save it to your computer👇"
1713
+ )
1714
+ st.video(out_gif.replace(".gif", ".mp4"))
1715
+
1716
+ elif collection in [
1717
+ "MODIS Gap filled Land Surface Temperature Daily",
1718
+ "MODIS Ocean Color SMI",
1719
+ ]:
1720
+
1721
+ with st.form("submit_ts_form"):
1722
+ with st.expander("Customize timelapse"):
1723
+
1724
+ title = st.text_input(
1725
+ "Enter a title to show on the timelapse: ",
1726
+ "Surface Temperature",
1727
+ )
1728
+ start_date = st.date_input(
1729
+ "Select the start date:", datetime.date(2018, 1, 1)
1730
+ )
1731
+ end_date = st.date_input(
1732
+ "Select the end date:", datetime.date(2020, 12, 31)
1733
+ )
1734
+ frequency = st.selectbox(
1735
+ "Select a temporal frequency:",
1736
+ ["year", "quarter", "month", "week", "day"],
1737
+ index=2,
1738
+ )
1739
+ reducer = st.selectbox(
1740
+ "Select a reducer for aggregating data:",
1741
+ ["median", "mean", "min", "max", "sum", "variance", "stdDev"],
1742
+ index=0,
1743
+ )
1744
+
1745
+ vis_params = st.text_area(
1746
+ "Enter visualization parameters",
1747
+ "",
1748
+ help="Enter a string in the format of a dictionary, such as '{'min': 23, 'max': 32}'",
1749
+ )
1750
+
1751
+ speed = st.slider("Frames per second:", 1, 30, 5)
1752
+ add_progress_bar = st.checkbox("Add a progress bar", True)
1753
+ progress_bar_color = st.color_picker(
1754
+ "Progress bar color:", "#0000ff"
1755
+ )
1756
+ font_size = st.slider("Font size:", 10, 50, 30)
1757
+ font_color = st.color_picker("Font color:", "#ffffff")
1758
+ font_type = st.selectbox(
1759
+ "Select the font type for the title:",
1760
+ ["arial.ttf", "alibaba.otf"],
1761
+ index=0,
1762
+ )
1763
+ add_colorbar = st.checkbox("Add a colorbar", True)
1764
+ colorbar_label = st.text_input(
1765
+ "Enter the colorbar label:", "Surface Temperature (°C)"
1766
+ )
1767
+ fading = st.slider(
1768
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1769
+ )
1770
+ mp4 = st.checkbox("Save timelapse as MP4", True)
1771
+
1772
+ empty_text = st.empty()
1773
+ empty_image = st.empty()
1774
+ empty_video = st.container()
1775
+
1776
+ roi = None
1777
+ if st.session_state.get("roi") is not None:
1778
+ roi = st.session_state.get("roi")
1779
+ out_gif = geemap.temp_file_path(".gif")
1780
+
1781
+ submitted = st.form_submit_button("Submit")
1782
+ if submitted:
1783
+
1784
+ if sample_roi == "Uploaded GeoJSON" and data is None:
1785
+ empty_text.warning(
1786
+ "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."
1787
+ )
1788
+ else:
1789
+
1790
+ empty_text.text("Computing... Please wait...")
1791
+ try:
1792
+ if (
1793
+ collection
1794
+ == "MODIS Gap filled Land Surface Temperature Daily"
1795
+ ):
1796
+ out_gif = geemap.create_timelapse(
1797
+ st.session_state.get("ee_asset_id"),
1798
+ start_date=start_date.strftime("%Y-%m-%d"),
1799
+ end_date=end_date.strftime("%Y-%m-%d"),
1800
+ region=roi,
1801
+ bands=None,
1802
+ frequency=frequency,
1803
+ reducer=reducer,
1804
+ date_format=None,
1805
+ out_gif=out_gif,
1806
+ palette=st.session_state.get("palette"),
1807
+ vis_params=None,
1808
+ dimensions=768,
1809
+ frames_per_second=speed,
1810
+ crs="EPSG:3857",
1811
+ overlay_data=overlay_data,
1812
+ overlay_color=overlay_color,
1813
+ overlay_width=overlay_width,
1814
+ overlay_opacity=overlay_opacity,
1815
+ title=title,
1816
+ title_xy=("2%", "90%"),
1817
+ add_text=True,
1818
+ text_xy=("2%", "2%"),
1819
+ text_sequence=None,
1820
+ font_type=font_type,
1821
+ font_size=font_size,
1822
+ font_color=font_color,
1823
+ add_progress_bar=add_progress_bar,
1824
+ progress_bar_color=progress_bar_color,
1825
+ progress_bar_height=5,
1826
+ add_colorbar=add_colorbar,
1827
+ colorbar_label=colorbar_label,
1828
+ loop=0,
1829
+ mp4=mp4,
1830
+ fading=fading,
1831
+ )
1832
+ elif collection == "MODIS Ocean Color SMI":
1833
+ if vis_params.startswith("{") and vis_params.endswith(
1834
+ "}"
1835
+ ):
1836
+ vis_params = json.loads(
1837
+ vis_params.replace("'", '"')
1838
+ )
1839
+ else:
1840
+ vis_params = None
1841
+ out_gif = geemap.modis_ocean_color_timelapse(
1842
+ st.session_state.get("ee_asset_id"),
1843
+ start_date=start_date.strftime("%Y-%m-%d"),
1844
+ end_date=end_date.strftime("%Y-%m-%d"),
1845
+ region=roi,
1846
+ bands=st.session_state["band"],
1847
+ frequency=frequency,
1848
+ reducer=reducer,
1849
+ date_format=None,
1850
+ out_gif=out_gif,
1851
+ palette=st.session_state.get("palette"),
1852
+ vis_params=vis_params,
1853
+ dimensions=768,
1854
+ frames_per_second=speed,
1855
+ crs="EPSG:3857",
1856
+ overlay_data=overlay_data,
1857
+ overlay_color=overlay_color,
1858
+ overlay_width=overlay_width,
1859
+ overlay_opacity=overlay_opacity,
1860
+ title=title,
1861
+ title_xy=("2%", "90%"),
1862
+ add_text=True,
1863
+ text_xy=("2%", "2%"),
1864
+ text_sequence=None,
1865
+ font_type=font_type,
1866
+ font_size=font_size,
1867
+ font_color=font_color,
1868
+ add_progress_bar=add_progress_bar,
1869
+ progress_bar_color=progress_bar_color,
1870
+ progress_bar_height=5,
1871
+ add_colorbar=add_colorbar,
1872
+ colorbar_label=colorbar_label,
1873
+ loop=0,
1874
+ mp4=mp4,
1875
+ fading=fading,
1876
+ )
1877
+ except:
1878
+ empty_text.error(
1879
+ "Something went wrong. You probably requested too much data. Try reducing the ROI or timespan."
1880
+ )
1881
+
1882
+ if out_gif is not None and os.path.exists(out_gif):
1883
+
1884
+ geemap.reduce_gif_size(out_gif)
1885
+
1886
+ empty_text.text(
1887
+ "Right click the GIF to save it to your computer👇"
1888
+ )
1889
+ empty_image.image(out_gif)
1890
+
1891
+ out_mp4 = out_gif.replace(".gif", ".mp4")
1892
+ if mp4 and os.path.exists(out_mp4):
1893
+ with empty_video:
1894
+ st.text(
1895
+ "Right click the MP4 to save it to your computer👇"
1896
+ )
1897
+ st.video(out_gif.replace(".gif", ".mp4"))
1898
+
1899
+ else:
1900
+ st.error(
1901
+ "Something went wrong. You probably requested too much data. Try reducing the ROI or timespan."
1902
+ )
1903
+
1904
+ elif collection == "USDA National Agriculture Imagery Program (NAIP)":
1905
+
1906
+ with st.form("submit_naip_form"):
1907
+ with st.expander("Customize timelapse"):
1908
+
1909
+ title = st.text_input(
1910
+ "Enter a title to show on the timelapse: ", "NAIP Timelapse"
1911
+ )
1912
+
1913
+ years = st.slider(
1914
+ "Start and end year:",
1915
+ 2003,
1916
+ today.year,
1917
+ (2003, today.year),
1918
+ )
1919
+
1920
+ bands = st.selectbox(
1921
+ "Select a band combination:", ["N/R/G", "R/G/B"], index=0
1922
+ )
1923
+
1924
+ speed = st.slider("Frames per second:", 1, 30, 3)
1925
+ add_progress_bar = st.checkbox("Add a progress bar", True)
1926
+ progress_bar_color = st.color_picker(
1927
+ "Progress bar color:", "#0000ff"
1928
+ )
1929
+ font_size = st.slider("Font size:", 10, 50, 30)
1930
+ font_color = st.color_picker("Font color:", "#ffffff")
1931
+ font_type = st.selectbox(
1932
+ "Select the font type for the title:",
1933
+ ["arial.ttf", "alibaba.otf"],
1934
+ index=0,
1935
+ )
1936
+ fading = st.slider(
1937
+ "Fading duration (seconds) for each frame:", 0.0, 3.0, 0.0
1938
+ )
1939
+ mp4 = st.checkbox("Save timelapse as MP4", True)
1940
+
1941
+ empty_text = st.empty()
1942
+ empty_image = st.empty()
1943
+ empty_video = st.container()
1944
+ empty_fire_image = st.empty()
1945
+
1946
+ roi = None
1947
+ if st.session_state.get("roi") is not None:
1948
+ roi = st.session_state.get("roi")
1949
+ out_gif = geemap.temp_file_path(".gif")
1950
+
1951
+ submitted = st.form_submit_button("Submit")
1952
+ if submitted:
1953
+
1954
+ if sample_roi == "Uploaded GeoJSON" and data is None:
1955
+ empty_text.warning(
1956
+ "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."
1957
+ )
1958
+ else:
1959
+
1960
+ empty_text.text("Computing... Please wait...")
1961
+ try:
1962
+ geemap.naip_timelapse(
1963
+ roi,
1964
+ years[0],
1965
+ years[1],
1966
+ out_gif,
1967
+ bands=bands.split("/"),
1968
+ palette=st.session_state.get("palette"),
1969
+ vis_params=None,
1970
+ dimensions=768,
1971
+ frames_per_second=speed,
1972
+ crs="EPSG:3857",
1973
+ overlay_data=overlay_data,
1974
+ overlay_color=overlay_color,
1975
+ overlay_width=overlay_width,
1976
+ overlay_opacity=overlay_opacity,
1977
+ title=title,
1978
+ title_xy=("2%", "90%"),
1979
+ add_text=True,
1980
+ text_xy=("2%", "2%"),
1981
+ text_sequence=None,
1982
+ font_type=font_type,
1983
+ font_size=font_size,
1984
+ font_color=font_color,
1985
+ add_progress_bar=add_progress_bar,
1986
+ progress_bar_color=progress_bar_color,
1987
+ progress_bar_height=5,
1988
+ loop=0,
1989
+ mp4=mp4,
1990
+ fading=fading,
1991
+ )
1992
+ except:
1993
+ empty_text.error(
1994
+ "Something went wrong. You either requested too much data or the ROI is outside the U.S."
1995
+ )
1996
+
1997
+ if out_gif is not None and os.path.exists(out_gif):
1998
+
1999
+ empty_text.text(
2000
+ "Right click the GIF to save it to your computer👇"
2001
+ )
2002
+ empty_image.image(out_gif)
2003
+
2004
+ out_mp4 = out_gif.replace(".gif", ".mp4")
2005
+ if mp4 and os.path.exists(out_mp4):
2006
+ with empty_video:
2007
+ st.text(
2008
+ "Right click the MP4 to save it to your computer👇"
2009
+ )
2010
+ st.video(out_gif.replace(".gif", ".mp4"))
2011
+
2012
+ else:
2013
+ st.error(
2014
+ "Something went wrong. You either requested too much data or the ROI is outside the U.S."
2015
+ )
2016
+
2017
+ #<----------------------------------------------------------------base map code for calling in home page(Navigation purpose)---------------------------------------------------------------->
2018
+
2019
+ def basemap_page():
2020
+ st.title("Search Basemaps")
2021
+ base_map()
2022
+
2023
+
2024
+ #<----------------------------------------------------------------basemap code------------------------------------------------------------------------------------------------------>
2025
+
2026
+ def base_map():
2027
+
2028
+ with st.expander("See demo"):
2029
+ st.image("https://i.imgur.com/0SkUhZh.gif")
2030
+
2031
+ row1_col1, row1_col2 = st.columns([3, 1])
2032
+ width = 800
2033
+ height = 600
2034
+ tiles = None
2035
+
2036
+ with row1_col2:
2037
+
2038
+ checkbox = st.checkbox("Search Quick Map Services (QMS)")
2039
+ keyword = st.text_input("Enter a keyword to search and press Enter:")
2040
+ empty = st.empty()
2041
+
2042
+ if keyword:
2043
+ options = leafmap.search_xyz_services(keyword=keyword)
2044
+ if checkbox:
2045
+ qms = leafmap.search_qms(keyword=keyword)
2046
+ if qms is not None:
2047
+ options = options + qms
2048
+
2049
+ tiles = empty.multiselect("Select XYZ tiles to add to the map:", options)
2050
+
2051
+ with row1_col1:
2052
+ m = leafmap.Map()
2053
+
2054
+ if tiles is not None:
2055
+ for tile in tiles:
2056
+ m.add_xyz_service(tile)
2057
+
2058
+ m.to_streamlit(height=height)
2059
+
2060
+
2061
+ #<-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->
2062
+
2063
+
2064
+ # Create a dictionary of pages
2065
+ pages = {
2066
+ "Home": page_home,
2067
+ "About": page_about,
2068
+ "Interactive Map": interactive_map_page,
2069
+ "Timelapse": Timelapse_page, # Placeholder for Timelapse page function
2070
+ "Basemap": basemap_page,
2071
+ }
2072
+
2073
+ # Add a sidebar for navigation
2074
+ st.sidebar.title("Navigation")
2075
+ selection = st.sidebar.radio("Go to", list(pages.keys()))
2076
+
2077
+ # Call the function of the selected page
2078
+ page = pages[selection]
2079
+ page()
Timelapse.py CHANGED
@@ -12,11 +12,6 @@ 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
 
 
12
  from datetime import date
13
  from shapely.geometry import Polygon
14
 
 
 
 
 
 
15
  st.set_page_config(layout="wide")
16
  warnings.filterwarnings("ignore")
17
 
requirements.txt CHANGED
@@ -1,14 +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==1.5.3
14
- numpy==1.23.5
 
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
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
+