aassiiyAA123 commited on
Commit
b78b8b4
·
verified ·
1 Parent(s): 08db64b

Upload 3 files

Browse files
y_gee_ee-muzzamil1-37ebc3dece52.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "type": "service_account",
3
+ "project_id": "ee-muzzamil1",
4
+ "private_key_id": "37ebc3dece52ae603066e6e3e6b614e8d4ba10cb",
5
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDA+XUtzhc3TZV5\nYrcV4a/9CN4gBO8zHLQjbWonnxp2eaogzByhRouctGSqJ5KVvnYFQFZcfN4wa+06\nj0Fr9uktH+PHkqDZ2OprRED0dzhgwCoSG59YoRgURbxWH5qCdr6dDYWd9/u4aJLW\nIywyqB/6XsuEnqkuQ5NnFcwrM/5rxn5y/3aXygNipiW9k5s/Q5UQXY8rh1QsTGZj\nJQmYokZZbCYGeoKd+c+tqVDPeR7nO1TT2bqzXAmNB+9MRIW3SBGhvNJu4ejHNti+\ncKb70j5KxJQ/PDAGbW1oZg2MUSGiLS16eRgpROlsNOqMWLAQo9iLl/KFSEpolAEC\nM+ocQJSTAgMBAAECggEARki1NpUo3IIb7mWXVFdqT0kzCctySZXrQDoCH2Mx8rO2\nVJKy3MSCZfVH8rdOCs8fUiNQMQhjrpQoh5sUk1uPKtnCDvanMiDwpFfsJn3joU1s\nJUM9Qr0NtZh+k4mYL2tLWo1JvLLM0in4TRjraJnWZ8yt6GQXL1v6bGHChnu97wdv\nIb411CSEsL7uW/RuAPr2UWhdx5D6FqzXtPEhsHgG9Iq/g7JGyP0/s854CxkWjVA/\nr0jxmzVfgg+lMtZYffp3PEA26XzZTAvxPPZ9sqvIyfQKu2lJnEUQfevoBtfJrlxj\n6Kd184ps4vaoDBellIZsKI46RAfdF2H1Wn4YaCYYsQKBgQDkHnR0JEI8D+rXAIUt\nap6rBiTKOLUv8Ai1UpwlZrRCJ22/UgvQgyLdUejFKqq5MGQDShnugm4q4Yk/8rP/\n+rjKzZfZLE85nJdubpeL7F1jozJDV8bJ7ZqZHYsadR6WpbLG9sU8WJ0nuUAzGpBt\n6l4H2ZTUp6fDzJVtNJL4kgN+YwKBgQDYj2Bov21oXIA2N5CTv/IB78RAR/w2yFra\ngLxi0CiR+/QogYBvXwM7xTQldfVGFlllgJVVTZTJKAKhs9d0M/5ZAVWt77K/t102\nVvNvDoSpxd23TolEQPBAHb3hS5HL7gaDnGHVNV09f6yILqGM0gMIvS73uZQ5E2fn\nptTkHBUQEQKBgQCZVMsr4c9PddeBCs15mIfsJuYFsxY+kZYY4t0n2p/hM4V2Ktzc\nG7kMkGjoVmSIs7kV6PIDOlJ4qj5J6IYK0mjxkD238SuTaujyho2AtLCVL3WyhEaP\nJhFbR9tfPkgANII1cFtk059WuxMnBnz8FKN9nUeHpOWEG3h4/fSn9eU5RwKBgQCR\nywzT2DQ28zdZyNSrs6igxyNvR0c0NnR77/lj6NG3XlFEx9KIqAWMQrpVkfE7ayZq\nIEPo9t75Adert2CQmcRddXmSLPJBAZheUfF3TeXgShZ3JwdgjPtxntRLjc2s5iU6\ni5iNqmyIT6D+2a3nGSfzxTGOk0CHoFnuabGflIxVkQKBgAIXy7g1Qb8nF88w4G6N\nHAmtRYsrvVQV9pG0atGJTEu4lPprbLmZNRWRxP9GPDOnf4WlLQ81g2Dk7J9vTt68\noLUsSgUNGR/FY68V/56fM3VwPuctE+6WrHpx9F09kMLPJaFTmmGF5SDcaH1OjPel\nsWmCRdg+vzGkP88aqRqxCJ/N\n-----END PRIVATE KEY-----\n",
6
+ "client_email": "[email protected]",
7
+ "client_id": "101116468635843693944",
8
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
9
+ "token_uri": "https://oauth2.googleapis.com/token",
10
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
11
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/geo-spatial-app%40ee-muzzamil1.iam.gserviceaccount.com",
12
+ "universe_domain": "googleapis.com"
13
+ }
y_gee_gee.py ADDED
The diff for this file is too large to render. See raw diff
 
y_gee_views.py ADDED
@@ -0,0 +1,1064 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django.shortcuts import render,redirect
2
+ import geopandas as gpd
3
+ from folium import GeoJson
4
+ import json
5
+ import geemap
6
+ import os
7
+ # generic base view
8
+ from django.views.generic import TemplateView
9
+
10
+ # folium
11
+ import folium
12
+ from folium import plugins
13
+
14
+ # gee
15
+ import ee
16
+
17
+ #---
18
+ from .forms import *
19
+ from django.http import HttpResponse
20
+ from django.shortcuts import render
21
+ from django.http import JsonResponse
22
+ from .gee import type_map, data_gee
23
+ from django.contrib.auth.decorators import login_required
24
+ import geemap.foliumap as geemap
25
+ from django.views.decorators.csrf import csrf_exempt
26
+ from django.contrib.auth import login as auth_login
27
+ from django.urls import reverse_lazy
28
+ from django.views.generic import UpdateView
29
+ from django.shortcuts import render
30
+ import ee
31
+ import pandas as pd
32
+ import numpy as np
33
+ from scipy import optimize
34
+ import matplotlib.pyplot as plt
35
+ import matplotlib.pyplot as plt
36
+ import numpy as np
37
+ from scipy import optimize
38
+
39
+
40
+ from django.shortcuts import render
41
+ import ee
42
+ import pandas as pd
43
+ import numpy as np
44
+ from scipy import optimize
45
+ from django.http import JsonResponse
46
+ import plotly.graph_objs as go
47
+ from datetime import datetime
48
+
49
+
50
+
51
+
52
+
53
+
54
+ #e.Authenticate()
55
+ ## Credenciales de EE
56
+
57
+
58
+ # D:\Desktop\Django_app_12_sep-2023\gee\ee-muzzamil.json
59
+
60
+ def index(request):
61
+
62
+ print("I am in index")
63
+ return render (request, "index.html")
64
+
65
+ # ee.Initialize()
66
+ @csrf_exempt
67
+
68
+ @login_required
69
+ def home(request):
70
+ template_name = 'home.html'
71
+
72
+
73
+
74
+ if request.method == 'GET':
75
+ selected_dataset = request.GET.get('dataset')
76
+ selected_shapefile = request.GET.get('shapefile')
77
+ selected_date_range_From = request.GET.get('dateRangeFrom')
78
+ selected_date_range_To = request.GET.get('dateRangeTo')
79
+
80
+ print(f'Selected Dataset: {selected_dataset}')
81
+ print(f'Selected Dataset: {selected_shapefile}')
82
+
83
+ figure = folium.Figure()
84
+
85
+ m = folium.Map(
86
+ location=[25.5973518, 65.54495724],
87
+ zoom_start=7,
88
+ )
89
+ m.add_to(figure)
90
+
91
+ #----------------------------------------------------------------------------------------------------------------------#
92
+ if selected_dataset == "Modis":
93
+ if selected_shapefile != None:
94
+
95
+ shapefile_path = ('C:\\Users\\piv\\Desktop\\y\\media\\shp')
96
+
97
+
98
+
99
+ roi_gdf = gpd.read_file(shapefile_path)
100
+ roi_geojson = roi_gdf.to_crs("EPSG:4326").to_json()
101
+
102
+ # Create a folium GeoJson layer for visualization
103
+ roi_geojson_layer = folium.GeoJson(roi_geojson, name='ROI GeoJSON')
104
+ roi_geojson_layer.add_to(m)
105
+
106
+ # Convert the GeoJSON content to Earth Engine object
107
+ ee_object = geemap.geojson_to_ee(json.loads(roi_geojson))
108
+ if selected_date_range_From != None:
109
+ if selected_date_range_To != None:
110
+ print("I am here")
111
+ F = selected_date_range_From
112
+ T = selected_date_range_To
113
+ print(F,"==>",T)
114
+
115
+
116
+ dataset = ee.ImageCollection('MODIS/006/MOD13Q1').filter(ee.Filter.date(F, T)).filterBounds(ee_object)
117
+
118
+ modisndvi = dataset.select('NDVI')
119
+
120
+ modisndvi = modisndvi.clip(ee_object)
121
+
122
+
123
+
124
+ vis_paramsNDVI = {
125
+ 'min': 0,
126
+ 'max': 9000,
127
+ 'palette': ['FE8374', 'C0E5DE', '3A837C', '034B48']}
128
+
129
+ map_id_dict = ee.Image(modisndvi).getMapId(vis_paramsNDVI)
130
+ folium.raster_layers.TileLayer(
131
+ tiles=map_id_dict['tile_fetcher'].url_format,
132
+ attr='Google Earth Engine',
133
+ name='NDVI',
134
+ overlay=True,
135
+ control=True
136
+ ).add_to(m)
137
+
138
+
139
+
140
+ m.add_child(folium.LayerControl())
141
+ figure.render()
142
+
143
+ else:
144
+ F = "2015-07-01"
145
+ T = "2019-11-30"
146
+ print("Date TO is Missing")
147
+ else:
148
+ F = "2015-07-01"
149
+ T = "2019-11-30"
150
+ print("Date From is Missing")
151
+
152
+ else:
153
+ pass
154
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+ #--------------------------------------------------------------------------------------------------------------------------------#
163
+ elif selected_dataset == "dataset_nighttime":
164
+ if selected_shapefile != None:
165
+
166
+ shapefile_path = ('C:\\Users\\piv\\Desktop\\y\\media\\shp')
167
+
168
+ # D:\Desktop\final_working1-New-2023\final\media
169
+
170
+ roi_gdf = gpd.read_file(shapefile_path)
171
+ roi_geojson = roi_gdf.to_crs("EPSG:4326").to_json()
172
+
173
+ # Create a folium GeoJson layer for visualization
174
+ roi_geojson_layer = folium.GeoJson(roi_geojson, name='ROI GeoJSON')
175
+ roi_geojson_layer.add_to(m)
176
+
177
+ # Convert the GeoJSON content to Earth Engine object
178
+ ee_object = geemap.geojson_to_ee(json.loads(roi_geojson))
179
+ if selected_date_range_From != None:
180
+ if selected_date_range_To != None:
181
+ print("I am here")
182
+ F = selected_date_range_From
183
+ T = selected_date_range_To
184
+ print(F,"==>",T)
185
+
186
+
187
+ dataset_nighttime = ee.ImageCollection('NOAA/VIIRS/DNB/MONTHLY_V1/VCMCFG').filter(ee.Filter.date(F, T))
188
+
189
+
190
+
191
+ # Mosaic the image collection to a single image
192
+ nighttime = dataset_nighttime.select('avg_rad').mosaic()
193
+
194
+ # Clip the nighttime lights image to the defined region
195
+ nighttime_clipped = nighttime.clip(ee_object)
196
+
197
+ nighttimeVis = {'min': 0.0, 'max': 60.0,'palette': ['1a3678', '2955bc', '5699ff', '8dbae9', 'acd1ff', 'caebff', 'e5f9ff',
198
+ 'fdffb4', 'ffe6a2', 'ffc969', 'ffa12d', 'ff7c1f', 'ca531a', 'ff0000',
199
+ 'ab0000']}
200
+ nighttime_layer = folium.TileLayer(
201
+ tiles=nighttime_clipped.getMapId(nighttimeVis)['tile_fetcher'].url_format,
202
+ attr='Google Earth Engine',
203
+ name='Nighttime Lights',
204
+ overlay=True,
205
+ control=True
206
+ ).add_to(m)
207
+
208
+ m.add_child(folium.LayerControl())
209
+ figure.render()
210
+
211
+ else:
212
+ F = "2015-07-01"
213
+ T = "2023-09-30"
214
+ print("Date TO is Missing")
215
+ else:
216
+ F = "2015-07-01"
217
+ T = "2023-09-30"
218
+ print("Date From is Missing")
219
+
220
+ else:
221
+ pass
222
+ #------------------------------------------------------------------------------------------------------------------------------------#
223
+
224
+ #------------------------------------------------------------------------------------------------------------------------------------#
225
+ elif selected_dataset == "precipitation":
226
+ if selected_shapefile != None:
227
+
228
+ shapefile_path = ('C:\\Users\\piv\\Desktop\\y\\media\\shp')
229
+
230
+
231
+
232
+ roi_gdf = gpd.read_file(shapefile_path)
233
+ roi_geojson = roi_gdf.to_crs("EPSG:4326").to_json()
234
+
235
+ # Create a folium GeoJson layer for visualization
236
+ roi_geojson_layer = folium.GeoJson(roi_geojson, name='ROI GeoJSON')
237
+ roi_geojson_layer.add_to(m)
238
+
239
+ # Convert the GeoJSON content to Earth Engine object
240
+ ee_object = geemap.geojson_to_ee(json.loads(roi_geojson))
241
+ if selected_date_range_From != None:
242
+ if selected_date_range_To != None:
243
+ print("I am here")
244
+ F = selected_date_range_From
245
+ T = selected_date_range_To
246
+ print(F,"==>",T)
247
+
248
+
249
+
250
+ # Load the dataset
251
+ dataset = (ee.ImageCollection('UCSB-CHG/CHIRPS/DAILY').filterBounds(ee_object).filter(ee.Filter.date(F, T)))
252
+
253
+
254
+
255
+
256
+ # Calculate the sum of the dataset
257
+ dataset1 = dataset.sum()
258
+
259
+ # Clip the summed dataset to the defined region
260
+ dataset2 = dataset1.clip(ee_object)
261
+
262
+ # Select the 'precipitation' band
263
+ precipitation = dataset2.select('precipitation')
264
+
265
+ # Define visualization parameters
266
+ imageVisParam = {
267
+ 'min': 80,
268
+ 'max': 460,
269
+ 'palette': ["001137","0aab1e","e7eb05","ff4a2d","e90000"]
270
+ }
271
+
272
+ # Clip the precipitation data to the region
273
+ precipitation_clipped = precipitation.clip(ee_object)
274
+
275
+ # Add precipitation layer to the map
276
+ folium.TileLayer(
277
+ tiles=precipitation_clipped.getMapId(imageVisParam)['tile_fetcher'].url_format,
278
+ attr='Google Earth Engine',
279
+ name='Precipitation',
280
+ overlay=True,
281
+ control=True
282
+ ).add_to(m)
283
+
284
+ m.add_child(folium.LayerControl())
285
+ figure.render()
286
+
287
+ else:
288
+ F = "2015-07-01"
289
+ T = "2023-09-30"
290
+ print("Date TO is Missing")
291
+ else:
292
+ F = "2015-07-01"
293
+ T = "2023-09-30"
294
+ print("Date From is Missing")
295
+
296
+ else:
297
+ pass
298
+
299
+ #------------------------------------------------------------------------------------------------------------------------------------#
300
+
301
+
302
+ #------------------------------------------------------------------------------------------------------------------------------------#
303
+
304
+
305
+
306
+ #to be rendered
307
+ dataset_options = ['Modis',
308
+ 'dataset_nighttime',
309
+ 'precipitation',
310
+ 'GlobalSurfaceWater',
311
+ 'WorldPop',
312
+ 'COPERNICUS']
313
+
314
+
315
+
316
+
317
+ shapes_options = ['District_Boundary',
318
+ 'hydro_basins',
319
+ 'karachi',
320
+ 'National_Constituency_with_Projected_2010_Population',
321
+ 'Provincial_Boundary',
322
+ 'Provincial_Constituency',
323
+ 'Tehsil_Boundary',
324
+ 'Union_Council']
325
+ # print(figure)
326
+ # map_html = m._repr_html_()
327
+ m.save('ndvi_map.html')
328
+
329
+
330
+
331
+
332
+ context = {"map": figure,"dataset_options":dataset_options,"shapes_options": shapes_options}
333
+ return render(request, template_name , context)
334
+ @login_required
335
+ def generate_ndvi_map(request):
336
+ # Create a response object for the HTML file
337
+ response = HttpResponse(content_type='text/html')
338
+ # Open and read the HTML file
339
+ with open('ndvi_map.html', 'rb') as html_file:
340
+ response.write(html_file.read())
341
+
342
+ # Set the Content-Disposition header to suggest a filename for download
343
+ response['Content-Disposition'] = 'attachment; filename="ndvi_map.html"'
344
+
345
+ return response
346
+ @login_required
347
+ def generate_chart(request):
348
+ template_name = 'results.html'
349
+
350
+ water_threshold=0.2
351
+ if request.method == 'GET':
352
+ selected_dataset = request.GET.get('dataset')
353
+ selected_shapefile = request.GET.get('shapefile')
354
+ selected_date_range_From = request.GET.get('dateRangeFrom')
355
+ selected_date_range_To = request.GET.get('dateRangeTo')
356
+
357
+ print(f'Selected Dataset: {selected_dataset}')
358
+ print(f'Selected Dataset: {selected_shapefile}')
359
+
360
+ figure = folium.Figure()
361
+
362
+ m = folium.Map(
363
+ location=[25.5973518, 65.54495724],
364
+ zoom_start=7,
365
+ )
366
+ m.add_to(figure)
367
+
368
+
369
+ #----------------------------------------------------------------------------------------------------------------------#
370
+ if selected_dataset == "Modis":
371
+ if selected_shapefile != None:
372
+
373
+ shapefile_path = ('C:\\Users\\piv\\Desktop\\y\\media\\shp')
374
+
375
+
376
+ roi_gdf = gpd.read_file(shapefile_path)
377
+ roi_geojson = roi_gdf.to_crs("EPSG:4326").to_json()
378
+
379
+ # Create a folium GeoJson layer for visualization
380
+ roi_geojson_layer = folium.GeoJson(roi_geojson, name='ROI GeoJSON')
381
+ roi_geojson_layer.add_to(m)
382
+
383
+ # Convert the GeoJSON content to Earth Engine object
384
+ ee_object = geemap.geojson_to_ee(json.loads(roi_geojson))
385
+ if selected_date_range_From != None:
386
+ if selected_date_range_To != None:
387
+ print("I am here")
388
+ F = selected_date_range_From
389
+ T = selected_date_range_To
390
+ print(F,"==>",T)
391
+
392
+
393
+ dataset = ee.ImageCollection('MODIS/006/MOD13Q1').filter(ee.Filter.date(F, T)).filterBounds(ee_object).first()
394
+
395
+ modisndvi = dataset.select('NDVI')
396
+
397
+ def water_function(image):
398
+ ndwi = image.normalizedDifference(['B3', 'B5']).rename('NDWI')
399
+ ndwi1 = ndwi.select('NDWI')
400
+ water01 = ndwi1.gt(water_threshold)
401
+ image = image.updateMask(water01).addBands(ndwi1)
402
+ area = ee.Image.pixelArea()
403
+ water_area = water01.multiply(area).rename('waterArea')
404
+ image = image.addBands(water_area)
405
+ stats = water_area.reduceRegion({
406
+ 'reducer': ee.Reducer.sum(),
407
+ 'geometry': shapefile_path,
408
+ 'scale': 30,
409
+ })
410
+ return image.set(stats)
411
+
412
+
413
+
414
+ modisndvi = modisndvi.clip(ee_object)
415
+
416
+ vis_paramsNDVI = {
417
+ 'min': 0,
418
+ 'max': 9000,
419
+ 'palette': ['FE8374', 'C0E5DE', '3A837C', '034B48']}
420
+
421
+ map_id_dict = ee.Image(modisndvi).getMapId(vis_paramsNDVI)
422
+ folium.raster_layers.TileLayer(
423
+ tiles=map_id_dict['tile_fetcher'].url_format,
424
+ attr='Google Earth Engine',
425
+ name='NDVI',
426
+ overlay=True,
427
+ control=True
428
+ ).add_to(m)
429
+
430
+ m.add_child(folium.LayerControl())
431
+ figure.render()
432
+
433
+ else:
434
+ F = "2015-07-01"
435
+ T = "2019-11-30"
436
+ print("Date TO is Missing")
437
+ else:
438
+ F = "2015-07-01"
439
+ T = "2019-11-30"
440
+ print("Date From is Missing")
441
+
442
+ else:
443
+ pass
444
+
445
+
446
+
447
+
448
+ #--------------------------------------------------------------------------------------------------------------------------------#
449
+ elif selected_dataset == "dataset_nighttime":
450
+ if selected_shapefile != None:
451
+
452
+ shapefile_path =('C:\\Users\\piv\\Desktop\\y\\media\\shp')
453
+ # D:\Desktop\final_working1-New-2023\final\media
454
+
455
+ roi_gdf = gpd.read_file(shapefile_path)
456
+ roi_geojson = roi_gdf.to_crs("EPSG:4326").to_json()
457
+
458
+ # Create a folium GeoJson layer for visualization
459
+ roi_geojson_layer = folium.GeoJson(roi_geojson, name='ROI GeoJSON')
460
+ roi_geojson_layer.add_to(m)
461
+
462
+ # Convert the GeoJSON content to Earth Engine object
463
+ ee_object = geemap.geojson_to_ee(json.loads(roi_geojson))
464
+ if selected_date_range_From != None:
465
+ if selected_date_range_To != None:
466
+ print("I am here")
467
+ F = selected_date_range_From
468
+ T = selected_date_range_To
469
+ print(F,"==>",T)
470
+
471
+
472
+ dataset_nighttime = ee.ImageCollection('NOAA/VIIRS/DNB/MONTHLY_V1/VCMCFG').filter(ee.Filter.date(F, T))
473
+
474
+
475
+
476
+ # Mosaic the image collection to a single image
477
+ nighttime = dataset_nighttime.select('avg_rad').mosaic()
478
+
479
+ # Clip the nighttime lights image to the defined region
480
+ nighttime_clipped = nighttime.clip(ee_object)
481
+
482
+ nighttimeVis = {'min': 0.0, 'max': 60.0,'palette': ['1a3678', '2955bc', '5699ff', '8dbae9', 'acd1ff', 'caebff', 'e5f9ff',
483
+ 'fdffb4', 'ffe6a2', 'ffc969', 'ffa12d', 'ff7c1f', 'ca531a', 'ff0000',
484
+ 'ab0000']}
485
+ nighttime_layer = folium.TileLayer(
486
+ tiles=nighttime_clipped.getMapId(nighttimeVis)['tile_fetcher'].url_format,
487
+ attr='Google Earth Engine',
488
+ name='Nighttime Lights',
489
+ overlay=True,
490
+ control=True
491
+ ).add_to(m)
492
+
493
+ m.add_child(folium.LayerControl())
494
+ figure.render()
495
+
496
+ else:
497
+ F = "2015-07-01"
498
+ T = "2023-09-30"
499
+ print("Date TO is Missing")
500
+ else:
501
+ F = "2015-07-01"
502
+ T = "2023-09-30"
503
+ print("Date From is Missing")
504
+
505
+ else:
506
+ pass
507
+
508
+ elif selected_dataset == "precipitation":
509
+ if selected_shapefile != None:
510
+ shapefile_path = ('C:\\Users\\piv\\Desktop\\y\\media\\shp')
511
+
512
+ roi_gdf = gpd.read_file(shapefile_path)
513
+ roi_geojson = roi_gdf.to_crs("EPSG:4326").to_json()
514
+
515
+ # Create a folium GeoJson layer for visualization
516
+ roi_geojson_layer = folium.GeoJson(roi_geojson, name='ROI GeoJSON')
517
+ roi_geojson_layer.add_to(m)
518
+
519
+ # Convert the GeoJSON content to Earth Engine object
520
+ ee_object = geemap.geojson_to_ee(json.loads(roi_geojson))
521
+ if selected_date_range_From != None:
522
+ if selected_date_range_To != None:
523
+ print("I am here")
524
+ F = selected_date_range_From
525
+ T = selected_date_range_To
526
+ print(F, "=>", T)
527
+
528
+ # Load the dataset
529
+ dataset = (ee.ImageCollection('UCSB-CHG/CHIRPS/DAILY').filterBounds(ee_object).filter(ee.Filter.date(F, T)))
530
+
531
+ # Calculate the sum of the dataset
532
+ dataset1 = dataset.sum()
533
+
534
+ # Clip the summed dataset to the defined region
535
+ dataset2 = dataset1.clip(ee_object)
536
+
537
+ # Select the 'precipitation' band
538
+ precipitation = dataset2.select('precipitation')
539
+
540
+ # Define visualization parameters
541
+ imageVisParam = {
542
+ 'min': 80,
543
+ 'max': 460,
544
+ 'palette': ["001137", "0aab1e", "e7eb05", "ff4a2d", "e90000"]
545
+ }
546
+
547
+ # Clip the precipitation data to the region
548
+ precipitation_clipped = precipitation.clip(ee_object)
549
+
550
+ # Add precipitation layer to the map
551
+ folium.TileLayer(
552
+ tiles=precipitation_clipped.getMapId(imageVisParam)['tile_fetcher'].url_format,
553
+ attr='Google Earth Engine',
554
+ name='Precipitation',
555
+ overlay=True,
556
+ control=True
557
+ ).add_to(m)
558
+
559
+ m.add_child(folium.LayerControl())
560
+ figure.render()
561
+ else:
562
+ F = "2015-07-01"
563
+ T = "2023-09-30"
564
+ print("Date TO is Missing")
565
+ else:
566
+ F = "2015-07-01"
567
+ T = "2023-09-30"
568
+ print("Date From is Missing")
569
+
570
+
571
+
572
+ elif selected_dataset == "WorldPop":
573
+ shapefile_path = ('C:\\Users\\piv\\Desktop\\y\\media\\shp')
574
+
575
+ roi_gdf = gpd.read_file(shapefile_path)
576
+ roi_geojson = roi_gdf.to_crs("EPSG:4326").to_json()
577
+
578
+ # Create a folium GeoJson layer for visualization
579
+ m = folium.Map(location=[25.5, 61], zoom_start=6)
580
+ roi_geojson_layer = folium.GeoJson(roi_geojson, name='ROI GeoJSON')
581
+ roi_geojson_layer.add_to(m)
582
+
583
+ # Convert the GeoJSON content to Earth Engine object
584
+ ee_object = geemap.geojson_to_ee(json.loads(roi_geojson))
585
+
586
+ if selected_date_range_From and selected_date_range_To:
587
+ F = selected_date_range_From
588
+ T = selected_date_range_To
589
+
590
+ # Load the image collection
591
+ collection = (ee.ImageCollection("WorldPop/GP/100m/pop")
592
+ .filterBounds(ee_object)
593
+ .filter(ee.Filter.date(F, T)))
594
+
595
+ # Calculate the sum of population for the specified region and time range
596
+ s2median = collection.sum()
597
+
598
+ # Clip the result to the ROI
599
+ roi = s2median.clip(ee_object)
600
+
601
+ # Create an image time series chart
602
+ chart = (ee.Image.cat(collection)
603
+ .reduceRegion(ee.Reducer.sum(), roi, 200)
604
+ .getInfo())
605
+
606
+ # Return the chart as JSON and map HTML as a response
607
+ clipped_image_url = roi.getThumbUrl({
608
+ 'min': 0,
609
+ 'max': 2000,
610
+ 'dimensions': 512,
611
+ 'palette': ['000000', 'ffffff']
612
+ })
613
+
614
+ # Add the clipped population image as a layer to the map
615
+ folium.TileLayer(
616
+ tiles=clipped_image_url,
617
+ attr="Population year17",
618
+ overlay=True,
619
+ control=True,
620
+ ).add_to(m)
621
+
622
+ # Return the folium map as HTML in the JSON response
623
+ map_html = m.get_root().render()
624
+ response_data = {'chart': chart, 'map_html': map_html}
625
+ return JsonResponse(response_data)
626
+
627
+
628
+
629
+ #to be rendered
630
+ dataset_options = ['Modis',
631
+ 'dataset_nighttime',
632
+ 'precipitation',
633
+ 'GlobalSurfaceWater',
634
+ 'WorldPop',
635
+ 'COPERNICUS']
636
+
637
+
638
+
639
+
640
+ shapes_options = ['District_Boundary',
641
+ 'hydro_basins',
642
+ 'karachi',
643
+ 'National_Constituency_with_Projected_2010_Population',
644
+ 'Provincial_Boundary',
645
+ 'Provincial_Constituency',
646
+ 'Tehsil_Boundary',
647
+ 'Union_Council']
648
+ # print(figure)
649
+ # map_html = m._repr_html_()
650
+ m.save('ndvi_map.html')
651
+
652
+
653
+
654
+
655
+ context = {"map": figure,"dataset_options":dataset_options,"shapes_options": shapes_options}
656
+ return render(request, template_name , context)
657
+ # You can continue with the existing code or add more logic as needed
658
+ @login_required
659
+ def map (request):
660
+ template_name='map.html'
661
+
662
+
663
+ return render(request,template_name)
664
+
665
+ @login_required
666
+ def GEE(request):
667
+ if request.method == 'POST':
668
+ formulario = dataset_geemap(data=request.POST)
669
+ if formulario.is_valid():
670
+ option = formulario.cleaned_data['option']
671
+
672
+ # Apply custom styles to the form fields or widgets
673
+ formulario.fields['option'].widget.attrs['class'] = 'custom-select'
674
+
675
+ figure = folium.Figure()
676
+ Map = geemap.Map(
677
+ plugin_Draw = True,
678
+ Draw_export = False,
679
+ plugin_LayerControl = False,
680
+ location = [25, 67],
681
+ zoom_start = 10,
682
+ plugin_LatLngPopup = False)
683
+ Map.add_basemap('HYBRID')
684
+ type_map(Map, option)
685
+ file, url_d = data_gee()
686
+ Map.add_layer_control()
687
+ url = url_d[url_d['id'] == option].reset_index()
688
+ url = url['asset_url'].iloc[0]
689
+ form = dataset_geemap(data=request.POST)
690
+ else:
691
+ form = dataset_geemap()
692
+
693
+ figure = folium.Figure()
694
+ Map = geemap.Map(
695
+ plugin_Draw = True,
696
+ Draw_export = False,
697
+ plugin_LayerControl = False,
698
+ location = [25, 67],
699
+ zoom_start = 10,
700
+ plugin_LatLngPopup = False)
701
+ Map.add_basemap('HYBRID')
702
+ dataset = ee.ImageCollection('BIOPAMA/GlobalOilPalm/v1')
703
+ opClass = dataset.select('classification')
704
+ mosaic = opClass.mosaic()
705
+ classificationVis = {
706
+ 'min': 1,
707
+ 'max': 3,
708
+ 'palette': ['ff0000','ef00ff', '696969']
709
+ }
710
+ mask = mosaic.neq(3)
711
+ mask = mask.where(mask.eq(0), 0.6)
712
+
713
+ Map.addLayer(mosaic.updateMask(mask),
714
+ classificationVis, 'Oil palm plantation type', True)
715
+ Map.setCenter(25,67,8)
716
+
717
+ url = 'https://developers.google.com/earth-engine/datasets/catalog/BIOPAMA_GlobalOilPalm_v1#terms-of-use'
718
+
719
+
720
+ Map.add_to(figure)
721
+ figure = figure._repr_html_() #updated
722
+
723
+ return render(request, 'gee.html', {'form':form, 'map':figure, 'url':url})
724
+
725
+
726
+
727
+
728
+
729
+
730
+
731
+ # Define your ee_array_to_df, t_modis_to_celsius, and fit_func functions here
732
+
733
+
734
+ def result_options(request):
735
+
736
+ return render (request, "result_options.html" )
737
+
738
+ def temp_result(request):
739
+
740
+ if request.method == 'GET':
741
+ selected_shapefile = request.GET.get('shapefile')
742
+ selected_date_range_From = request.GET.get('dateRangeFrom')
743
+ selected_date_range_To = request.GET.get('dateRangeTo')
744
+
745
+ print(selected_shapefile)
746
+ print(selected_date_range_From)
747
+ print(selected_date_range_To)
748
+
749
+ if selected_date_range_From == None or selected_date_range_To == None:
750
+ i_date ='2022-06-24'
751
+ f_date ='2023-09-19'
752
+ else:
753
+ i_date = selected_date_range_From
754
+ f_date = selected_date_range_To
755
+
756
+ # Import the MODIS land surface temperature collection.
757
+ lst = ee.ImageCollection('MODIS/006/MOD11A1')
758
+
759
+ # Selection of appropriate bands and dates for LST.
760
+ lst = lst.select('LST_Day_1km', 'QC_Day').filterDate(i_date, f_date)
761
+
762
+ if selected_shapefile == None:
763
+ u_lon = 4.8148
764
+ u_lat = 45.7758
765
+ u_poi = ee.Geometry.Point(u_lon, u_lat)
766
+ else:
767
+ shapefile_path = ('C:\\Users\\piv\\Desktop\\y\\media\\shp')
768
+
769
+
770
+ roi_gdf = gpd.read_file(shapefile_path)
771
+ roi_geojson = roi_gdf.to_crs("EPSG:4326").to_json()
772
+
773
+ # Create a folium GeoJson layer for visualization
774
+ ee_object = geemap.geojson_to_ee(json.loads(roi_geojson))
775
+
776
+ u_poi = ee_object
777
+
778
+ # Get the data for the pixel intersecting the point in the urban area.
779
+ scale = 1000 # scale in meters
780
+ lst_u_poi = lst.getRegion(u_poi, scale).getInfo()
781
+
782
+ # Convert the Earth Engine data to a DataFrame using the provided function.
783
+ lst_df_urban = ee_array_to_df(lst_u_poi, ['LST_Day_1km'])
784
+
785
+ # Apply the function to convert temperature units to Celsius.
786
+ lst_df_urban['LST_Day_1km'] = lst_df_urban['LST_Day_1km'].apply(t_modis_to_celsius)
787
+
788
+ # Fitting curves.
789
+ ## First, extract x values (times) from the df.
790
+ x_data_u = np.asanyarray(lst_df_urban['time'].apply(float))
791
+
792
+ ## Then, extract y values (LST) from the df.
793
+ y_data_u = np.asanyarray(lst_df_urban['LST_Day_1km'].apply(float))
794
+
795
+ ## Define the fitting function with parameters.
796
+ def fit_func(t, lst0, delta_lst, tau, phi):
797
+ return lst0 + (delta_lst/2)*np.sin(2*np.pi*t/tau + phi)
798
+
799
+ ## Optimize the parameters using a good start p0.
800
+ lst0 = 20
801
+ delta_lst = 40
802
+ tau = 365*24*3600*1000 # milliseconds in a year
803
+ phi = 2*np.pi*4*30.5*3600*1000/tau # offset regarding when we expect LST(t)=LST0
804
+
805
+ params_u, params_covariance_u = optimize.curve_fit(
806
+ fit_func, x_data_u, y_data_u, p0=[lst0, delta_lst, tau, phi])
807
+
808
+
809
+ x_data_u_formatted = [datetime.utcfromtimestamp(ts / 1000).strftime('%d %m %Y') for ts in x_data_u]
810
+ # x_data_r_formatted = [datetime.utcfromtimestamp(ts / 1000).strftime('%d %m %Y') for ts in x_data_r]
811
+
812
+ # return render(request, 'chart.html', {'chart_data': chart_data})
813
+ urban_trace = go.Scatter(
814
+ x=x_data_u_formatted, # Use the formatted dates
815
+ y=fit_func(x_data_u, *params_u), # Use your fit_func to generate y values
816
+ mode='lines',
817
+ name='Urban Area'
818
+ )
819
+
820
+ # Create a Plotly figure for the rural data
821
+
822
+
823
+ data = [urban_trace]
824
+
825
+ layout = go.Layout(
826
+ title='Land Surface Temperature over Time',
827
+ xaxis=dict(title='Time'),
828
+ yaxis=dict(title='LST (°C)'),
829
+ showlegend=True
830
+ )
831
+
832
+ fig = go.Figure(data=data, layout=layout)
833
+
834
+ # Convert the Plotly figure to HTML
835
+ plot_div = fig.to_html(full_html=False, default_height=500, default_width=700)
836
+
837
+ shapes_options = ['District_Boundary',
838
+ 'hydro_basins',
839
+ 'karachi',
840
+ 'National_Constituency_with_Projected_2010_Population',
841
+ 'Provincial_Boundary',
842
+ 'Provincial_Constituency',
843
+ 'Tehsil_Boundary',
844
+ 'Union_Council']
845
+
846
+
847
+ context={
848
+ "shapes_options":shapes_options,
849
+ "plot_div":plot_div
850
+
851
+ }
852
+
853
+
854
+
855
+ return render(request, "temp_result.html",context )
856
+
857
+
858
+ else:
859
+
860
+
861
+
862
+
863
+
864
+ shapes_options = ['District_Boundary',
865
+ 'hydro_basins',
866
+ 'karachi',
867
+ 'National_Constituency_with_Projected_2010_Population',
868
+ 'Provincial_Boundary',
869
+ 'Provincial_Constituency',
870
+ 'Tehsil_Boundary',
871
+ 'Union_Council']
872
+
873
+
874
+ context={
875
+ "shapes_options":shapes_options
876
+
877
+ }
878
+
879
+
880
+
881
+ return render(request, "temp_result.html",context )
882
+
883
+
884
+ def chart(request):
885
+ # Define the date range of interest.
886
+
887
+
888
+ #replaceble with dates
889
+ i_date = '2017-01-01'
890
+ f_date = '2020-01-01'
891
+
892
+ # Import the MODIS land surface temperature collection.
893
+ lst = ee.ImageCollection('MODIS/006/MOD11A1')
894
+
895
+ # Selection of appropriate bands and dates for LST.
896
+ lst = lst.select('LST_Day_1km', 'QC_Day').filterDate(i_date, f_date)
897
+
898
+ # Define the urban location of interest as a point near Lyon, France.
899
+ #replaceble with shapefile
900
+ u_lon = 4.8148
901
+ u_lat = 45.7758
902
+ u_poi = ee.Geometry.Point(u_lon, u_lat)
903
+
904
+ # Get the data for the pixel intersecting the point in the urban area.
905
+ scale = 1000 # scale in meters
906
+ lst_u_poi = lst.getRegion(u_poi, scale).getInfo()
907
+
908
+ # Convert the Earth Engine data to a DataFrame using the provided function.
909
+ lst_df_urban = ee_array_to_df(lst_u_poi, ['LST_Day_1km'])
910
+
911
+ # Apply the function to convert temperature units to Celsius.
912
+ lst_df_urban['LST_Day_1km'] = lst_df_urban['LST_Day_1km'].apply(t_modis_to_celsius)
913
+
914
+ # Fitting curves.
915
+ ## First, extract x values (times) from the df.
916
+ x_data_u = np.asanyarray(lst_df_urban['time'].apply(float))
917
+
918
+ ## Then, extract y values (LST) from the df.
919
+ y_data_u = np.asanyarray(lst_df_urban['LST_Day_1km'].apply(float))
920
+
921
+ ## Define the fitting function with parameters.
922
+ def fit_func(t, lst0, delta_lst, tau, phi):
923
+ return lst0 + (delta_lst/2)*np.sin(2*np.pi*t/tau + phi)
924
+
925
+ ## Optimize the parameters using a good start p0.
926
+ lst0 = 20
927
+ delta_lst = 40
928
+ tau = 365*24*3600*1000 # milliseconds in a year
929
+ phi = 2*np.pi*4*30.5*3600*1000/tau # offset regarding when we expect LST(t)=LST0
930
+
931
+ params_u, params_covariance_u = optimize.curve_fit(
932
+ fit_func, x_data_u, y_data_u, p0=[lst0, delta_lst, tau, phi])
933
+
934
+
935
+ x_data_u_formatted = [datetime.utcfromtimestamp(ts / 1000).strftime('%d %m %Y') for ts in x_data_u]
936
+ # x_data_r_formatted = [datetime.utcfromtimestamp(ts / 1000).strftime('%d %m %Y') for ts in x_data_r]
937
+
938
+ # return render(request, 'chart.html', {'chart_data': chart_data})
939
+ urban_trace = go.Scatter(
940
+ x=x_data_u_formatted, # Use the formatted dates
941
+ y=fit_func(x_data_u, *params_u), # Use your fit_func to generate y values
942
+ mode='lines',
943
+ name='Urban Area'
944
+ )
945
+
946
+ # Create a Plotly figure for the rural data
947
+
948
+
949
+ data = [urban_trace]
950
+
951
+ layout = go.Layout(
952
+ title='Land Surface Temperature over Time',
953
+ xaxis=dict(title='Time'),
954
+ yaxis=dict(title='LST (°C)'),
955
+ showlegend=True
956
+ )
957
+
958
+ fig = go.Figure(data=data, layout=layout)
959
+
960
+ # Convert the Plotly figure to HTML
961
+ plot_div = fig.to_html(full_html=False, default_height=500, default_width=700)
962
+
963
+ return render(request, 'chart.html', {'plot_div': plot_div})
964
+
965
+
966
+
967
+
968
+
969
+
970
+
971
+
972
+
973
+
974
+ #Auth
975
+ def signup (request):
976
+ form = SignUpForm()
977
+ if request.method == "POST":
978
+
979
+ form = SignUpForm(request.POST)
980
+ if form.is_valid():
981
+ user = form.save()
982
+ auth_login(request,user)
983
+ return redirect('index')
984
+
985
+
986
+
987
+ return render(request, 'signup.html', {'form':form})
988
+
989
+
990
+ class UserUpdateView(UpdateView):
991
+ model=User
992
+ fields =('first_name','last_name', 'email',)
993
+ template_name = 'my_account.html'
994
+ success_url = reverse_lazy('my_account')
995
+
996
+ def get_object(self):
997
+ return self.request.user
998
+
999
+
1000
+
1001
+
1002
+
1003
+
1004
+
1005
+
1006
+
1007
+
1008
+
1009
+
1010
+
1011
+
1012
+
1013
+
1014
+
1015
+
1016
+
1017
+
1018
+
1019
+
1020
+
1021
+
1022
+
1023
+
1024
+
1025
+
1026
+
1027
+
1028
+
1029
+
1030
+
1031
+
1032
+
1033
+ def ee_array_to_df(arr, list_of_bands):
1034
+ """Transforms client-side ee.Image.getRegion array to pandas.DataFrame."""
1035
+ df = pd.DataFrame(arr)
1036
+
1037
+ # Rearrange the header.
1038
+ headers = df.iloc[0]
1039
+ df = pd.DataFrame(df.values[1:], columns=headers)
1040
+
1041
+ # Remove rows without data inside.
1042
+ df = df[['longitude', 'latitude', 'time', *list_of_bands]].dropna()
1043
+
1044
+ # Convert the data to numeric values.
1045
+ for band in list_of_bands:
1046
+ df[band] = pd.to_numeric(df[band], errors='coerce')
1047
+
1048
+ # Convert the time field into a datetime.
1049
+ df['datetime'] = pd.to_datetime(df['time'], unit='ms')
1050
+
1051
+ # Keep the columns of interest.
1052
+ df = df[['time', 'datetime', *list_of_bands]]
1053
+ print(df)
1054
+
1055
+ return df
1056
+
1057
+ def t_modis_to_celsius(t_modis):
1058
+ """Converts MODIS LST units to degrees Celsius."""
1059
+ t_celsius = 0.02 * t_modis - 273.15
1060
+ return t_celsius
1061
+
1062
+ def fit_func(t, lst0, delta_lst, tau, phi):
1063
+ """Fitting function for the curve."""
1064
+ return lst0 + (delta_lst / 2) * np.sin(2 * np.pi * t / tau + phi)