├── 00016_population_monitoring ├── 00077_shapefile_upload ├── 0142_landsat_landcover ├── 00041_cropland_modis_monitoring ├── 00095_heatwave ├── 00011_class_area ├── 00092_river_level_swot ├── 00006_dem ├── 00034_night_light ├── 0103_xee_lake_desiccation ├── 00098_gridding_images ├── 00079_temp_conversion ├── 0105_xee_correlation_map ├── 00076_image_mosaicking ├── 0101_xee_intro ├── 00037_pr_clustering ├── 00074_reducers ├── 0114_xee_growing_season_length ├── 00073_img_expression ├── 0108_xee_sen_slope ├── 00001_lake_area_estimation ├── 00087_land_subsidence ├── 00002_lake_area_monitoring ├── 00090_python_series_plot ├── 0102_xee_anomaly ├── 0143_xee_mod_snow_gap_filling ├── 00088_jrc_lake ├── 0129_export_ee ├── 00005_dry_wet_days ├── 00024_otsu_water ├── 00053_modis_snow_duration ├── 0144_xee_pr_pca ├── 00020_water_turbidity ├── 00065_snow_collection ├── 00069_sentinel2_water_chlorophyll ├── 00086_temp_harmonic ├── 0110_xee_irrigation_index ├── 0111_xee_pr_forecast ├── 00038_flood_ndvi_change ├── 0120_xee_veg_opt_depth ├── 00052_landsat_vegetation_moisture_index ├── 0139_xee_ndvi_phenology ├── 00009_ndvi_trend_analysis ├── 0109_xee_dry_spell ├── 0140_xee_trend_seasonal ├── 00027_dust_clustering ├── 00028_dust_change_detection ├── 00097_flood_depth ├── 0116_xee_heatwave ├── 00078_zonal_stat ├── 00025_coastline_change ├── 0150_xee_landsat_cloud_masking ├── 00043_sen3_ndvi ├── 0138_xee_snow_season ├── 0145_xee_embedding_kmeans ├── 0135_xee_esi ├── 0121_xee_lake_clustering ├── 0159_xee_sen2_turbidity ├── 00085_heavy_pr_valencia ├── 0131_xee_sg_filter ├── 0136_xee_interp ├── 00031_canopy_height_1m ├── 00089_snowmelt_temp ├── 00032_oil_spill_sentinel1 ├── 00018_et_cwsi_mapping ├── 0112_xee_wildefire ├── 0155_evaporation_viirs ├── 0134_xee_dem_clustering ├── 0156_xee_sen2_chl_water ├── 00075_charts ├── 0151_xee_sen2_cloud_masking ├── 00003_precipitation_anomaly ├── 00014_daily_wind_speed ├── 00007_sen1_flood ├── 00022_urban_built_up ├── 00091_python_mann_kendall ├── 00004_temp_per_change ├── 0160_xee_sen2_cdom ├── 0119_xee_gap_filling ├── 00013_landcover_temperature ├── 0099_built_percentage_api ├── 0141_xee_dust_wind ├── 0152_xee_svi_viirs ├── 0164_xee_utci ├── 0167_xee_lake_ice_cover ├── 00064_climate_classification ├── 00012_snow_area ├── 00059_spei_classification ├── 00083_pr_intensity ├── 0104_xee_pm25 ├── 00081_lc8_tree_cover ├── 00094_sen1_speckel_filtering ├── 00048_sen2_green_space ├── 0127_xee_wetland_detection ├── 00049_sen2_deforestation ├── 0133_xee_temp_anomaly ├── 107_xee_water_consumption ├── 0118_xee_ndvi_phenology ├── 0100_pop_growth_rate ├── 00070_ground_water_gldas ├── 00082_carbon_stock └── 00062_sentinel1_croptype /00016_population_monitoring: -------------------------------------------------------------------------------- 1 | /* 2 | Tutorial Code by Amirhossein Ahrari 3 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 4 | 5 | This code is part of a tutorial series on Earth Engine programming techniques 6 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 7 | this code for academic and non-academic purposes. Don't forget to subscribe to 8 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 9 | */ 10 | 11 | 12 | 13 | var cor = [49.648641123960516,37.29255382495616] 14 | 15 | var loc = ee.Geometry.MultiPoint(cor) 16 | 17 | var roi = table.filterBounds(loc); 18 | 19 | Map.centerObject(roi) 20 | Map.addLayer(roi) 21 | 22 | var pop = ee.ImageCollection("JRC/GHSL/P2023A/GHS_POP") 23 | 24 | Map.addLayer(pop.toBands().clip(roi),[],'pop',false) 25 | 26 | print( 27 | ui.Chart.image.series(pop, roi, ee.Reducer.sum(), 28 | 100, 'system:time_start') 29 | ) 30 | 31 | 32 | -------------------------------------------------------------------------------- /00077_shapefile_upload: -------------------------------------------------------------------------------- 1 | /* 2 | Tutorial Code by Amirhossein Ahrari 3 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 4 | 5 | This code is part of a tutorial series on Earth Engine programming techniques 6 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 7 | this code for academic and non-academic purposes. Don't forget to subscribe to 8 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 9 | */ 10 | 11 | 12 | Map.centerObject(table) 13 | Map.addLayer(table,{color: 'red'}) 14 | 15 | print(table.geometry()) 16 | 17 | var roi = table.map(function(feature){ 18 | return feature.simplify(1000) 19 | }) 20 | 21 | Map.addLayer(roi) 22 | 23 | print(roi.geometry()) 24 | 25 | var lst = ee.ImageCollection("MODIS/061/MOD11A2") 26 | .select('LST_Day_1km') 27 | .filterDate('2023','2024').mean().multiply(0.02).subtract(273.15) 28 | 29 | 30 | Map.addLayer(lst.clip(roi),{palette: ['blue','white','red']},'lst',false) 31 | 32 | 33 | Export.image.toDrive({ 34 | image: lst.clip(roi), 35 | description: 'lst_data', 36 | scale: 1000, 37 | region: roi, 38 | crs: 'EPSG:4326', 39 | folder: 'test' 40 | 41 | }) 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /0142_landsat_landcover: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | 5 | Tutorial Code by Amirhossein Ahrari 6 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 7 | Tutorial Video: Google Earth Engine Tutorial-147: Landsat Landcover Product (1984-2022) 8 | 9 | This code is part of a tutorial series on Earth Engine programming techniques 10 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 11 | this code for academic and non-academic purposes. Don't forget to subscribe to 12 | the Amirhossein Ahrari channel and follow the videos to support the instructor 13 | 14 | 15 | */ 16 | 17 | 18 | var cor = [49.64500915431612,37.14344151987502] 19 | 20 | var geometry = ee.Geometry.Point(cor) 21 | 22 | var roi = ee.FeatureCollection("FAO/GAUL/2015/level1") 23 | .filterBounds(geometry).geometry().simplify(1000) 24 | 25 | Map.centerObject(roi) 26 | Map.addLayer(roi) 27 | 28 | var annual = ee.ImageCollection("projects/sat-io/open-datasets/GLC-FCS30D/annual") 29 | .filterBounds(roi) 30 | .mosaic() 31 | 32 | print(annual) 33 | 34 | Map.addLayer(annual.clip(roi),[],'landcover',false) 35 | 36 | Export.image.toDrive({ 37 | image: annual.clip(roi), 38 | description: 'annual_map_guilan', 39 | scale: 100, 40 | region: roi, 41 | crs: 'EPSG:4326', 42 | folder: 'test', 43 | maxPixels: 1e13 44 | 45 | }) 46 | -------------------------------------------------------------------------------- /00041_cropland_modis_monitoring: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | var cor = [ 13 | [44.73934589893846,35.494599065738065], 14 | [47.99129902393846,35.494599065738065], 15 | [47.99129902393846,37.994365217637785], 16 | [44.73934589893846,37.994365217637785], 17 | [44.73934589893846,35.494599065738065] 18 | ] 19 | 20 | var roi = ee.Geometry.Polygon(cor) 21 | 22 | 23 | Map.centerObject(roi); 24 | 25 | var time_start = '2001', time_end = '2024' 26 | 27 | var modis = ee.ImageCollection("MODIS/061/MCD12Q1") 28 | .select('LC_Type1') 29 | .filterDate(time_start, time_end); 30 | 31 | function cropland_area(img){ 32 | var thr = img.eq(12).or(img.eq(14)); 33 | var mask = thr.updateMask(thr); 34 | var area = mask.multiply(ee.Image.pixelArea().divide(1e6)); 35 | return area 36 | .copyProperties(img, ['system:time_start', 'system:time_end']) 37 | } 38 | 39 | var cropland = modis.map(cropland_area); 40 | 41 | print( 42 | ui.Chart.image.series(cropland, roi, ee.Reducer.sum(), 43 | 500, 'system:time_start') 44 | ) 45 | -------------------------------------------------------------------------------- /00095_heatwave: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | /* 5 | Tutorial Code by Amirhossein Ahrari 6 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 7 | Tutorial Video: Google Earth Engine Tutorial-100: Heatwave Mapping 8 | 9 | This code is part of a tutorial series on Earth Engine programming techniques 10 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 11 | this code for academic and non-academic purposes. Don't forget to subscribe to 12 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 13 | */ 14 | 15 | 16 | var cor = [ 17 | [45.178862816860004,23.21836640777923], 18 | [66.44839406686,23.21836640777923], 19 | [66.44839406686,41.22596686419348], 20 | [45.178862816860004,41.22596686419348], 21 | [45.178862816860004,23.21836640777923] 22 | ] 23 | 24 | var geometry = ee.Geometry.Polygon(cor) 25 | 26 | var temp = ee.ImageCollection("ECMWF/ERA5_LAND/MONTHLY_AGGR") 27 | .select('temperature_2m') 28 | .filterDate('2000','2025') 29 | 30 | var baseline = temp.reduce(ee.Reducer.percentile([90])) 31 | 32 | Map.addLayer(baseline,[],'baseline',false) 33 | 34 | var heatwave = temp.filterDate('2005','2010') 35 | .map(function(img){ 36 | return img.gt(baseline) 37 | }).sum() 38 | 39 | Map.addLayer(heatwave,[],'heatwave_index',false) 40 | 41 | Export.image.toDrive({ 42 | image: heatwave, 43 | description: 'heatwave_global', 44 | scale: 10000, 45 | region: geometry, 46 | folder: 'test', 47 | crs: 'EPSG:4326' 48 | }) 49 | -------------------------------------------------------------------------------- /00011_class_area: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | var cor = [ 13 | [43.89239103939352,35.313917425058115], 14 | [49.165828539393516,35.313917425058115], 15 | [49.165828539393516,39.29702833107737], 16 | [43.89239103939352,39.29702833107737], 17 | [43.89239103939352,35.313917425058115] 18 | ] 19 | 20 | var roi = ee.Geometry.Polygon(cor) 21 | 22 | Map.centerObject(roi); 23 | 24 | var modis = ee.ImageCollection("MODIS/061/MCD12Q1") 25 | .select('LC_Type1').mode(); 26 | 27 | var igbpLandCoverVis = { 28 | min: 1.0, 29 | max: 17.0, 30 | palette: [ 31 | '05450a', '086a10', '54a708', '78d203', '009900', 'c6b044', 'dcd159', 32 | 'dade48', 'fbff13', 'b6ff05', '27ff87', 'c24f44', 'a5a5a5', 'ff6d4c', 33 | '69fff8', 'f9ffa4', '1c0dff' 34 | ], 35 | }; 36 | 37 | Map.addLayer(modis.clip(roi),igbpLandCoverVis,'modis_lc',false); 38 | 39 | print( 40 | ui.Chart.image.histogram(modis,roi,500) 41 | ) 42 | 43 | 44 | var modis_area = ee.Image.pixelArea().divide(1e6).addBands(modis); 45 | 46 | print( 47 | ui.Chart.image.byClass(modis_area, 'LC_Type1', 48 | roi, ee.Reducer.sum(), 500) 49 | ) 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /00092_river_level_swot: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-97: River Water Level Extraction, using SWOT 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 12 | */ 13 | 14 | var cor = [ 15 | [45.722100047300216,36.042910275520335], 16 | [46.688896922300216,36.042910275520335], 17 | [46.688896922300216,37.23298149260607], 18 | [45.722100047300216,37.23298149260607], 19 | [45.722100047300216,36.042910275520335] 20 | ] 21 | 22 | var geometry = ee.Geometry.Polygon(cor) 23 | 24 | Map.centerObject(geometry) 25 | 26 | var nodes_merged = ee.FeatureCollection("projects/sat-io/open-datasets/SWORD/nodes_merged"); 27 | var reaches_merged = ee.FeatureCollection("projects/sat-io/open-datasets/SWORD/reaches_merged"); 28 | 29 | var nodes = nodes_merged.filterBounds(geometry) 30 | var reach = reaches_merged.filterBounds(geometry) 31 | 32 | Map.addLayer(nodes,{color: 'blue'}) 33 | Map.addLayer(reach, {color: 'red'}) 34 | 35 | 36 | Export.table.toDrive({ 37 | collection: nodes, description: 'nodes_zarrine', folder: 'test', fileFormat: 'SHP' 38 | }) 39 | 40 | Export.table.toDrive({ 41 | collection: reach, description: 'raech_zarrine', folder: 'test', fileFormat: 'SHP' 42 | }) 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /00006_dem: -------------------------------------------------------------------------------- 1 | /* 2 | Tutorial Code by Amirhossein Ahrari 3 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 4 | 5 | This code is part of a tutorial series on Earth Engine programming techniques 6 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 7 | this code for academic and non-academic purposes. Don't forget to subscribe to 8 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 9 | */ 10 | 11 | var cor = [ 12 | [48.646401641929856,35.98889945187288], 13 | [50.211953399742356,35.98889945187288], 14 | [50.211953399742356,37.15353368743586], 15 | [48.646401641929856,37.15353368743586], 16 | [48.646401641929856,35.98889945187288] 17 | ] 18 | 19 | var roi = ee.Geometry.Polygon(cor) 20 | 21 | Map.centerObject(roi); 22 | 23 | var srtm = image.select('elevation'); 24 | 25 | Map.addLayer(srtm.clip(roi),[],'dem30',false) 26 | 27 | print( 28 | ui.Chart.image.histogram(srtm,roi,100) 29 | ) 30 | 31 | var slope = ee.Terrain.slope(srtm); 32 | 33 | Map.addLayer(slope.clip(roi),[],'slope', false); 34 | 35 | var aspect = ee.Terrain.aspect(srtm); 36 | 37 | Map.addLayer(aspect.clip(roi),[],'aspect',false); 38 | 39 | var product = ee.Terrain.products(srtm); 40 | 41 | print(product); 42 | 43 | Export.image.toDrive({ 44 | image: product.clip(roi).float(), 45 | description: 'dem_product', 46 | scale: 30, 47 | region: roi, 48 | crs: product.getInfo().crs, 49 | folder: 'dem', 50 | maxPixels: 1e13 51 | }) 52 | 53 | // 54 | 55 | var alos = imageCollection.select('DSM').mean() 56 | 57 | print( 58 | ui.Chart.image.histogram(alos, roi, 100) 59 | ) 60 | -------------------------------------------------------------------------------- /00034_night_light: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | 13 | var table = ee.FeatureCollection("FAO/GAUL/2015/level1") 14 | 15 | 16 | var cor = [2.3495010435451746,48.8768460308918] 17 | 18 | var geometry = ee.Geometry.Point(cor) 19 | 20 | var roi = table.filterBounds(geometry); 21 | 22 | Map.addLayer(roi) 23 | 24 | Map.centerObject(roi) 25 | 26 | function night_light(time_start, time_end, loc_name){ 27 | 28 | var viirs = ee.ImageCollection("NOAA/VIIRS/DNB/MONTHLY_V1/VCMCFG") 29 | .select('avg_rad') 30 | .filterDate(time_start, time_end) 31 | .mean(); 32 | 33 | var stats = viirs.reduceRegion({ 34 | reducer: ee.Reducer.mean().combine({reducer2: ee.Reducer.minMax(), sharedInputs: true}), geometry: roi, scale: 500 35 | }) 36 | 37 | print('night light stat for '+time_start, stats) 38 | 39 | 40 | Map.addLayer(viirs.clip(roi),[],loc_name+time_start,false) 41 | 42 | Export.image.toDrive({ 43 | image: viirs.clip(roi), 44 | description: loc_name+time_start, 45 | scale: 500, 46 | crs: viirs.getInfo().crs, 47 | region: roi, 48 | folder: 'test' 49 | }) 50 | 51 | return viirs 52 | 53 | } 54 | 55 | var helsinki2013 = night_light('2013','2014', 'Paris') 56 | 57 | var helsinki2023 = night_light('2023','2024', 'Paris') 58 | -------------------------------------------------------------------------------- /0103_xee_lake_desiccation: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0011_lake_desiccation.ipynb 3 | 4 | utorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-108: Lake Mapping, using Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 12 | 13 | """ 14 | 15 | import ee 16 | import xarray as xr 17 | import numpy as np 18 | import matplotlib.pyplot as plt 19 | 20 | !pip install xee 21 | import xee 22 | 23 | ee.Authenticate() 24 | ee.Initialize(project = 'ee-your project info', opt_url='https://earthengine-highvolume.googleapis.com') 25 | 26 | mod = ee.ImageCollection("MODIS/061/MOD09A1").select('sur_refl_b02', 'sur_refl_b04').filterDate('2001','2025') 27 | 28 | loc = ee.Geometry.Rectangle([44.77438907535245, 37.23809308226242, 46.29050235660245, 38.27171994382565]) 29 | 30 | ds = xr.open_dataset(mod, engine = 'ee', crs = 'EPSG:4326', scale = 0.01, geometry = loc) 31 | 32 | ds 33 | 34 | green = ds.sur_refl_b04 * 0.0001 35 | nir = ds.sur_refl_b02 * 0.0001 36 | 37 | nir 38 | 39 | ndwi = (green - nir) / (green + nir) 40 | 41 | ndwi 42 | 43 | ndwi_annual = ndwi.resample(time = 'YE').mean('time') 44 | 45 | ndwi_annual 46 | 47 | ndwi_annual.plot(x = 'lon', y = 'lat', cmap = 'Blues', col = 'time', col_wrap = 5, robust = True) 48 | plt.savefig('lake_desiccation.png', dpi = 360, bbox_inches = 'tight') 49 | -------------------------------------------------------------------------------- /00098_gridding_images: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | Tutorial Video: Google Earth Engine Tutorial-103: Gridding Satellite Images 6 | 7 | This code is part of a tutorial series on Earth Engine programming techniques 8 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 9 | this code for academic and non-academic purposes. Don't forget to subscribe to 10 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 11 | */ 12 | 13 | var cor = [51.23677824859797,35.673392008559226] 14 | 15 | var geometry = ee.Geometry.Point(cor) 16 | 17 | var roi = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level1") 18 | .filterBounds(geometry) 19 | 20 | Map.addLayer(roi) 21 | 22 | var grid = roi.geometry().coveringGrid('EPSG:4326', 5000) 23 | 24 | Map.addLayer(grid) 25 | 26 | Map.centerObject(grid) 27 | 28 | 29 | 30 | var modis = ee.ImageCollection("MODIS/061/MOD11A2") 31 | .select(['LST_Day_1km', 'LST_Night_1km'],['day','night']) 32 | .filterDate('2021','2022') 33 | .map(function(img){ 34 | var temp = img.multiply(0.02).subtract(273.15) 35 | return temp 36 | .copyProperties(img, img.propertyNames()) 37 | }).mean() 38 | 39 | print(modis) 40 | 41 | var stat = grid.map(function(feature){ 42 | var vals = modis.reduceRegion({ 43 | reducer: ee.Reducer.mean(), 44 | geometry: feature.geometry(), 45 | scale: 1000 46 | }) 47 | return feature 48 | .set(vals) 49 | }) 50 | 51 | 52 | print(stat) 53 | 54 | 55 | Export.table.toDrive({ 56 | collection: stat, description: 'Tehran_LST_Day_Night', fileFormat: 'SHP', folder: 'test' 57 | 58 | }) 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /00079_temp_conversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | 7 | This code is part of a tutorial series on Earth Engine programming techniques 8 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 9 | this code for academic and non-academic purposes. Don't forget to subscribe to 10 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 11 | */ 12 | 13 | var cor = [-98.627734375,43.59139671684014] 14 | 15 | var geometry = ee.Geometry.Point(cor) 16 | 17 | var time_start = ee.Date('2010') 18 | var time_end = ee.Date('2024') 19 | var time_dif = time_end.difference(time_start, 'year').round() 20 | var delta = ee.Number(1) 21 | 22 | print(time_dif) 23 | 24 | 25 | var modis = ee.ImageCollection("MODIS/061/MOD11A1") 26 | .select('LST_Day_1km') 27 | .filterDate(time_start, time_end) 28 | 29 | 30 | var list = ee.List.sequence(0, ee.Number(time_dif).subtract(1), delta).map(function(interval){ 31 | return time_start.advance(interval, 'year') 32 | }) 33 | 34 | var modis8days = ee.ImageCollection(list.map(function(date){ 35 | var start_date = ee.Date(date) 36 | var end_date = start_date.advance(delta, 'year') 37 | var img = modis.filterDate(start_date, end_date).reduce(ee.Reducer.median()) 38 | return img 39 | .set('system:time_start', start_date.millis() ) 40 | .set('system:index', start_date.format('YYYY-MM-dd')) 41 | })) 42 | 43 | print(modis8days ) 44 | 45 | 46 | 47 | print( 48 | ui.Chart.image.series(modis, geometry, ee.Reducer.first(), 1000, 'system:time_start') 49 | ) 50 | 51 | print( 52 | ui.Chart.image.series(modis8days, geometry, ee.Reducer.first(), 1000, 'system:time_start') 53 | ) 54 | -------------------------------------------------------------------------------- /0105_xee_correlation_map: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0013_correlation_map.ipynb 3 | 4 | utorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-110: Corraltion Map, using Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 12 | 13 | """ 14 | 15 | import ee 16 | import xarray as xr 17 | 18 | !pip install xee 19 | import xee 20 | 21 | ee.Authenticate() 22 | ee.Initialize(project = '******', opt_url='https://earthengine-highvolume.googleapis.com') 23 | 24 | col = ee.ImageCollection("IDAHO_EPSCOR/TERRACLIMATE").filterDate('2010','2020').select('pr', 'tmmn', 'tmmx') 25 | 26 | loc = [41.86012129914674, 25.315629595884804, 66.20582442414674, 39.902491623606075] 27 | 28 | ds = xr.open_dataset(col, engine = 'ee', crs = 'EPSG:4326', scale = 0.05, geometry = loc) 29 | 30 | ds 31 | 32 | pr_annual = ds.pr.resample(time = 'YE').sum('time') 33 | 34 | pr_annual 35 | 36 | import matplotlib.pyplot as plt 37 | 38 | pr_annual.plot(x = 'lon', y = 'lat', cmap = 'Blues', col = 'time', col_wrap = 5, robust = True) 39 | 40 | temp = (((ds.tmmn + ds.tmmx)/2) * 0.1).round(2).rename('temp') 41 | 42 | temp 43 | 44 | temp_annual = temp.resample(time = 'YE').mean('time') 45 | 46 | temp_annual 47 | 48 | temp_annual.plot(x = 'lon', y = 'lat', cmap = 'coolwarm', robust = True, col = 'time', col_wrap = 5) 49 | 50 | cor_map = xr.corr(temp_annual, pr_annual, dim = 'time') 51 | 52 | cor_map 53 | 54 | cor_map.plot(x = 'lon', y = 'lat', robust = True) 55 | -------------------------------------------------------------------------------- /00076_image_mosaicking: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | 13 | var cor = [49.460707394140904,37.284294138744144] 14 | 15 | var geometry = ee.Geometry.Point(cor) 16 | 17 | var roi = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level1") 18 | .filterBounds(geometry) 19 | 20 | Map.addLayer(roi) 21 | Map.centerObject(roi) 22 | 23 | var time_start = ee.Date('2023') 24 | var time_end = ee.Date('2024') 25 | var time_dif = time_end.difference(time_start, 'day') 26 | 27 | var list = ee.List.sequence(0, ee.Number(time_dif).subtract(1), 5).map(function(number){ 28 | return time_start.advance(number, 'days') 29 | }) 30 | 31 | var sen2 = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED") 32 | .select('B[2-4]','B8') 33 | .filterDate('2023', '2024') 34 | .filterBounds(roi) 35 | 36 | 37 | var sen2_mosaic = ee.ImageCollection(list.map(function(date){ 38 | var start_date = ee.Date(date) 39 | var end_date = start_date.advance(5, 'days') 40 | var img = sen2.filterDate(start_date, end_date).mosaic() 41 | return img 42 | .set('system:time_start', start_date.millis()) 43 | .set('system:time_end', end_date.millis()) 44 | })) 45 | 46 | 47 | 48 | Map.addLayer(sen2_mosaic.select(['B8']).filter(ee.Filter.calendarRange(8, 8, 'month')).toBands().clip(roi),[], 'mosaic', false) 49 | Map.addLayer(sen2.select('B8').filter(ee.Filter.calendarRange(8, 8, 'month')).toBands().clip(roi),[],'original',false) 50 | -------------------------------------------------------------------------------- /0101_xee_intro: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0009_xee_intro3.ipynb 3 | 4 | 5 | Tutorial Code by Amirhossein Ahrari 6 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 7 | Tutorial Video: Google Earth Engine Tutorial-106: Introduction to Xee, for GEE Python API 8 | 9 | This code is part of a tutorial series on Earth Engine programming techniques 10 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 11 | this code for academic and non-academic purposes. Don't forget to subscribe to 12 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 13 | 14 | 15 | """ 16 | 17 | import ee 18 | import xarray as xr 19 | 20 | !pip install xee 21 | 22 | import xee 23 | 24 | ee.Authenticate() 25 | ee.Initialize(project = 'ee-amirhosseinahrari', opt_url='https://earthengine-highvolume.googleapis.com') 26 | 27 | temp = ee.ImageCollection("ECMWF/ERA5_LAND/DAILY_AGGR").select('temperature_2m')\ 28 | .filterDate('2010','2011') 29 | 30 | ds = xr.open_dataset(temp, engine = 'ee') 31 | 32 | ds 33 | 34 | jan = ds.sel(time = '2010-01-01') 35 | 36 | jan 37 | 38 | jan['temperature_2m'].plot(x = 'lon', y = 'lat', cmap = 'jet') 39 | 40 | temp_cel = ds - 273.15 41 | 42 | temp_cel 43 | 44 | jan_cel = temp_cel.sel(time = '2010-01-01') 45 | 46 | import matplotlib.pyplot as plt 47 | 48 | jan_cel['temperature_2m'].plot(x = 'lon', y = 'lat', cmap = 'jet') 49 | plt.savefig('jan012010.png', dpi = 360) 50 | 51 | weekly = ds.resample(time = 'W').mean() 52 | 53 | weekly 54 | 55 | monthly = ds.resample(time = 'M').max() 56 | 57 | monthly 58 | 59 | sub = monthly.sel(lon = slice(0, 150), lat = slice(0, 90), time = '2010-03-31' ) 60 | 61 | sub 62 | 63 | sub['temperature_2m'].plot(x = 'lon', y = 'lat', cmap = 'jet' ) 64 | 65 | !pip install netCDF4 66 | 67 | sub.to_netcdf('monthly_max.nc') 68 | -------------------------------------------------------------------------------- /00037_pr_clustering: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | 13 | var cor = [52.29632817890257,33.99522092192627] 14 | 15 | var point = ee.Geometry.Point(cor) 16 | 17 | var table = ee.FeatureCollection("FAO/GAUL/2015/level0") 18 | 19 | var roi = table.filterBounds(point); 20 | 21 | Map.centerObject(roi) 22 | Map.addLayer(roi) 23 | 24 | 25 | function pr_clustering(id, time_start, time_end, numclass){ 26 | 27 | var pr = ee.ImageCollection(id).filterDate(time_start, time_end); 28 | 29 | var pr_dataset = pr.toBands(); 30 | 31 | var training = pr_dataset.sample({ 32 | region: roi, scale: 5000, numPixels: 1000 33 | }) 34 | 35 | var clusterer = ee.Clusterer.wekaKMeans(numclass).train(training) 36 | 37 | var pr_map = pr_dataset.cluster(clusterer); 38 | 39 | Map.addLayer(pr_map.clip(roi),{min: 0, max: 4},'pr_map',false) 40 | 41 | var pr_sum = pr.sum() 42 | 43 | var pr_stat = pr_sum.addBands(pr_map).reduceRegion({ 44 | reducer: ee.Reducer.mean().combine({reducer2: ee.Reducer.stdDev(), sharedInputs: true}) 45 | .group(1), geometry: roi, scale: 5000 46 | }) 47 | 48 | print('statistical inf for pr zones:', pr_stat) 49 | 50 | Export.image.toDrive({ 51 | image: pr_map, 52 | description: 'pr_map', 53 | scale: 5000, 54 | region: roi, 55 | crs: pr_map.getInfo().crs, 56 | folder: 'test' 57 | }) 58 | 59 | return pr_map 60 | 61 | } 62 | 63 | var pr_pattern = pr_clustering("UCSB-CHG/CHIRPS/DAILY", '2020', '2021', 5); 64 | 65 | 66 | -------------------------------------------------------------------------------- /00074_reducers: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | 7 | This code is part of a tutorial series on Earth Engine programming techniques 8 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 9 | this code for academic and non-academic purposes. Don't forget to subscribe to 10 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 11 | */ 12 | 13 | var cor = [ 14 | [-114.7744262311347,42.12127672144149], 15 | [-113.09077144597845,42.12127672144149], 16 | [-113.09077144597845,42.94700331032601], 17 | [-114.7744262311347,42.94700331032601], 18 | [-114.7744262311347,42.12127672144149] 19 | ] 20 | 21 | var geometry = ee.Geometry.Polygon(cor) 22 | 23 | Map.centerObject(geometry) 24 | 25 | 26 | var ndvi = ee.ImageCollection("MODIS/061/MOD13Q1") 27 | .select('NDVI') 28 | .filterDate('2023', '2024') 29 | .map(function(img){ 30 | var bands = img.multiply(0.0001) 31 | var projected = bands.reproject('EPSG:4326', null, 250) 32 | return projected 33 | .copyProperties(img,img.propertyNames()) 34 | }) 35 | 36 | 37 | var stack = ndvi.toBands() 38 | 39 | Map.addLayer(stack.clip(geometry),[],'ndvi_stack',false) 40 | 41 | 42 | var ndvi_mean = ndvi.mean() 43 | 44 | Map.addLayer(ndvi_mean.clip(geometry),[],'ndvi_mean', false) 45 | 46 | var ndvi_max = ndvi.max() 47 | 48 | Map.addLayer(ndvi_max.clip(geometry),[],'ndvi_max',false) 49 | 50 | var ndvi_min = ndvi.min() 51 | var ndvi_median = ndvi.median() 52 | var ndvi_std = ndvi.reduce(ee.Reducer.stdDev()) 53 | 54 | Map.addLayer(ndvi_std.clip(geometry),[],'ndvi_std',false) 55 | 56 | 57 | 58 | Export.image.toDrive({ 59 | image: ndvi_median, 60 | description: 'ndvi_median', 61 | scale: 250, 62 | region: geometry, 63 | crs: 'EPSG:4326', 64 | folder: 'test' 65 | 66 | }) 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /0114_xee_growing_season_length: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0022_growing_season_length.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-119: Growing Season Length, using Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | """ 14 | 15 | import ee 16 | import geemap 17 | import xarray as xr 18 | 19 | !pip install xee 20 | import xee 21 | 22 | ee.Authenticate() 23 | ee.Initialize(project ='ee-amirhosseinahrari', opt_url = 'https://earthengine-highvolume.googleapis.com') 24 | 25 | map = geemap.Map(basemap = 'SATELLITE') 26 | map 27 | 28 | roi = map.draw_last_feature.geometry() 29 | 30 | roi 31 | 32 | collection = ee.ImageCollection("ECMWF/ERA5_LAND/DAILY_AGGR").filterDate('2000','2020').select('temperature_2m').map( 33 | lambda img: img.subtract(273.15).copyProperties(img, img.propertyNames()) 34 | ) 35 | 36 | collection.limit(10) 37 | 38 | ds = xr.open_dataset(collection, engine = 'ee', crs = 'EPSG:4326', scale = 0.27, geometry = roi) 39 | 40 | ds 41 | 42 | xr.infer_freq(ds.time) 43 | 44 | ds['temperature_2m'].attrs['units'] = 'degC' 45 | 46 | ds 47 | 48 | !pip install xclim 49 | import xclim 50 | 51 | gsl = xclim.indices.growing_season_length( 52 | tas = ds.temperature_2m, 53 | thresh = '5.0 degC', 54 | window = 6, 55 | mid_date = '07-01', 56 | freq = 'YS' 57 | ) 58 | 59 | gsl 60 | 61 | import matplotlib.pyplot as plt 62 | 63 | gsl.plot(x = 'lon', y = 'lat', col = 'time', col_wrap = 5, robust = True) 64 | plt.savefig('gsl.png', dpi = 360, bbox_inches = 'tight') 65 | -------------------------------------------------------------------------------- /00073_img_expression: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | 7 | This code is part of a tutorial series on Earth Engine programming techniques 8 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 9 | this code for academic and non-academic purposes. Don't forget to subscribe to 10 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 11 | */ 12 | 13 | var cor = [ 14 | [24.601591838871006,60.127836641299616], 15 | [25.150908245121006,60.127836641299616], 16 | [25.150908245121006,60.331035392660304], 17 | [24.601591838871006,60.331035392660304], 18 | [24.601591838871006,60.127836641299616] 19 | ] 20 | 21 | var geometry = ee.Geometry.Polygon(cor) 22 | 23 | var sen2 = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED") 24 | .filterBounds(geometry) 25 | .filterDate('2023-07-01','2024-09-01') 26 | .filter(ee.Filter.lt('CLOUDY_PIXEL_OVER_LAND_PERCENTAGE', 10)) 27 | .map(function(img){ 28 | var bands = img.select('B.*').multiply(0.0001) 29 | // ndvi = (nir - red)/(nir + red) 30 | var ndvi1 = bands.expression('(nir - red)/(nir + red)',{'nir': bands.select('B8'), 'red': bands.select('B4')}).rename('ndvi1') 31 | var ndvi2 = (bands.select('B8').subtract(bands.select('B4'))).divide(bands.select('B8').add(bands.select('B4'))).rename('ndvi2') 32 | var ndvi3 = bands.normalizedDifference(['B8','B4']).rename('ndvi3') 33 | return ee.Image.cat([ndvi1, ndvi2, ndvi3]) 34 | .copyProperties(img, img.propertyNames()) 35 | 36 | }) 37 | 38 | 39 | var sen2_img = ee.Image('COPERNICUS/S2_SR_HARMONIZED/20230914T095031_20230914T095325_T34VFN') 40 | 41 | var sen2_bands = sen2_img.select('B.*').expression('img * 0.0001',{'img': sen2_img.select('B.*')}) 42 | 43 | var sen2_ndvi = sen2_bands.normalizedDifference(['B8','B4']).rename('ndvi') 44 | 45 | Map.addLayer(sen2_ndvi, [], 'ndvi', false) 46 | 47 | 48 | -------------------------------------------------------------------------------- /0108_xee_sen_slope: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0016_sen_slope.ipynb 3 | 4 | utorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-113: Sen Slope Trend Analysis, using Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | 14 | """ 15 | 16 | import ee 17 | import geemap as gee 18 | import xarray as xr 19 | 20 | !pip install xee 21 | import xee 22 | 23 | ee.Authenticate() 24 | ee.Initialize(project = 'ee-amirhosseinahrari', opt_url = 'https://earthengine-highvolume.googleapis.com') 25 | 26 | collection = ee.ImageCollection("ECMWF/ERA5/MONTHLY").select('mean_2m_air_temperature').filterDate('2000','2024') 27 | 28 | map = gee.Map(basemap = 'SATELLITE') 29 | map 30 | 31 | roi = map.draw_last_feature.geometry() 32 | 33 | ds = xr.open_dataset(collection, engine = 'ee', crs = 'EPSG:4326', scale = 0.27, geometry = roi) 34 | 35 | ds 36 | 37 | annual = ds.resample(time = 'YE').mean('time') 38 | 39 | annual 40 | 41 | annual.mean_2m_air_temperature.plot(x = 'lon', y = 'lat', cmap = 'jet', robust = True, col = 'time', col_wrap =7) 42 | 43 | !pip install pymannkendall 44 | import pymannkendall as mk 45 | 46 | import numpy as np 47 | 48 | def sen_fun(img): 49 | clean = img[~np.isnan(img)] 50 | return mk.original_test(clean).slope 51 | 52 | sen_slope_map = xr.apply_ufunc( 53 | sen_fun, 54 | ds.mean_2m_air_temperature, 55 | input_core_dims = [['time']], 56 | output_dtypes = [float], 57 | vectorize = True, 58 | dask = 'allows' 59 | 60 | ) 61 | 62 | sen_slope_map 63 | 64 | sen_slope_map.plot(x = 'lon', y = 'lat', robust = True) 65 | -------------------------------------------------------------------------------- /00001_lake_area_estimation: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | var coordinates = [ 13 | [42.000552219688586, 38.18969302118053], 14 | [43.868228000938586, 38.18969302118053], 15 | [43.868228000938586, 39.209978258633186], 16 | [42.000552219688586, 39.209978258633186], 17 | [42.000552219688586, 38.18969302118053] 18 | ]; 19 | 20 | var roi = ee.Geometry.Polygon(coordinates); 21 | 22 | Map.addLayer(roi) 23 | 24 | var time_start = '2013', time_end = '2021' 25 | 26 | var landsat = imageCollection 27 | .filterDate(time_start, time_end) 28 | .filter(ee.Filter.lt('CLOUD_COVER', 10)) 29 | .filter(ee.Filter.calendarRange(6,9,'month')) 30 | .filterBounds(geometry).map(function(img){ 31 | var bands = img.select('SR_.*').multiply(2.75e-05).add(-0.2); 32 | var ndwi = bands.normalizedDifference(['SR_B3','SR_B5']).rename('ndwi'); 33 | return ndwi 34 | .copyProperties(img, img.propertyNames()) 35 | }).median(); 36 | 37 | 38 | Map.addLayer(landsat.clip(geometry), [], 'ndwi_summer', false); 39 | Map.addLayer(landsat.clip(geometry).gt(0), [], 'ndwi_thr', false); 40 | 41 | var thr = landsat.gt(0.1); 42 | var mask = thr.updateMask(thr); 43 | 44 | Map.addLayer(mask, [], 'ndwi_masked', false); 45 | 46 | 47 | var pixel_area = mask.multiply(ee.Image.pixelArea().divide(1e6)); 48 | 49 | Map.addLayer(pixel_area.clip(geometry), [], 'ndwi_pixel_area', false); 50 | 51 | var lake_area = pixel_area.reduceRegion({ 52 | reducer: ee.Reducer.sum(), geometry: geometry, scale: 100 53 | }).values().get(0); 54 | 55 | 56 | print(ee.Number(lake_area)) 57 | -------------------------------------------------------------------------------- /00087_land_subsidence: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | Tutorial Video: Google Earth Engine Tutorial-92: Land Subsidence Product 6 | 7 | This code is part of a tutorial series on Earth Engine programming techniques 8 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 9 | this code for academic and non-academic purposes. Don't forget to subscribe to 10 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 11 | */ 12 | 13 | 14 | 15 | var cor = [45.987522953102534,37.16840692552587] 16 | 17 | var geometry = ee.Geometry.Point(cor) 18 | 19 | 20 | var prob = ee.Image("projects/sat-io/open-datasets/global_subsidence/Final_subsidence_proba_greater_1cm_2013_2019_recoded"); 21 | 22 | Map.addLayer(prob,{palette:['white', 'yellow','orange','red','brown','black']}, 'prob',false) 23 | 24 | var roi = ee.FeatureCollection("WWF/HydroSHEDS/v1/Basins/hybas_5") 25 | .filterBounds(geometry).map(function(feature){ 26 | return feature.simplify(1000) 27 | }) 28 | 29 | Map.centerObject(roi) 30 | Map.addLayer(roi) 31 | 32 | var prob_roi = prob.clip(roi) 33 | 34 | Map.addLayer(prob_roi,{palette:['white', 'yellow','orange','red','brown','black']}, 'roi_prob',false) 35 | 36 | 37 | var land_sub = ee.Image("projects/sat-io/open-datasets/global_subsidence/Final_subsidence_prediction_recoded"); 38 | 39 | Map.addLayer(land_sub.updateMask(land_sub.neq(1)),{palette:['white', 'yellow','orange','red','brown','black']}, 'class',false) 40 | 41 | 42 | var land_sub_roi = land_sub.clip(roi) 43 | 44 | Map.addLayer(land_sub_roi,{palette:['white', 'yellow','orange','red','brown','black']}, 'roi_class',false) 45 | 46 | 47 | 48 | 49 | Export.image.toDrive({ 50 | image: land_sub_roi, 51 | description: 'land_sub_ex', 52 | scale: 100, 53 | region: roi, 54 | maxPixels: 1e13, 55 | crs: 'EPSG:4326', 56 | folder: 'test' 57 | 58 | }) 59 | 60 | -------------------------------------------------------------------------------- /00002_lake_area_monitoring: -------------------------------------------------------------------------------- 1 | /* 2 | Tutorial Code by Amirhossein Ahrari 3 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 4 | 5 | This code is part of a tutorial series on Earth Engine programming techniques 6 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 7 | this code for academic and non-academic purposes. Don't forget to subscribe to 8 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 9 | */ 10 | 11 | 12 | var cor = [[44.82021271860131,37.08040466447922], 13 | [46.11659943735131,37.08040466447922], 14 | [46.11659943735131,38.37506300104177], 15 | [44.82021271860131,38.37506300104177], 16 | [44.82021271860131,37.08040466447922] 17 | ] 18 | 19 | var roi = ee.Geometry.Polygon(cor) 20 | 21 | Map.addLayer(roi) 22 | Map.centerObject(roi) 23 | 24 | var time_start = '2001', time_end = '2023' 25 | 26 | var modis = ee.ImageCollection("MODIS/061/MOD09A1") 27 | .filterDate(time_start, time_end); 28 | 29 | var ndwi = modis.map(function(img){ 30 | var band = img.select('sur.*').multiply(0.0001); 31 | var index = band.normalizedDifference(['sur_refl_b04','sur_refl_b02']).rename('ndwi'); 32 | return index 33 | .copyProperties(img, img.propertyNames()) 34 | }); 35 | 36 | Map.addLayer(ndwi.filterDate('2010','2011').toBands().clip(roi), [],'ndwi', false); 37 | 38 | 39 | var ndwi_average = ndwi.filterDate('2010', '2011').median(); 40 | 41 | print( 42 | ui.Chart.image.histogram(ndwi_average, roi, 500) 43 | ) 44 | 45 | 46 | 47 | var lake_area = ndwi.map(function(img){ 48 | var thr = img.gt(0.1) 49 | var mask = thr.updateMask(thr); 50 | var area = mask.multiply(ee.Image.pixelArea().divide(1e6)); 51 | return area 52 | .copyProperties(img, img.propertyNames()) 53 | }); 54 | 55 | 56 | print( 57 | ui.Chart.image.series(lake_area, roi, ee.Reducer.sum(), 58 | 500, 'system:time_start') 59 | ) 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /00090_python_series_plot: -------------------------------------------------------------------------------- 1 | 2 | """GEE_0005_temperature_plot3.ipynb 3 | 4 | 5 | Tutorial Code by Amirhossein Ahrari 6 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 7 | Tutorial Video: Google Earth Engine Tutorial-95: Time Series Plot using Google Colab 8 | 9 | This code is part of a tutorial series on Earth Engine programming techniques 10 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 11 | this code for academic and non-academic purposes. Don't forget to subscribe to 12 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 13 | 14 | """ 15 | 16 | import ee 17 | import geemap as gee 18 | 19 | ee.Authenticate() 20 | ee.Initialize(project = 'ee-amirhosseinahrari') 21 | 22 | temp = ee.ImageCollection("ECMWF/ERA5_LAND/MONTHLY_AGGR").filterDate('2022','2024').select('temperature_2m') 23 | 24 | temp 25 | 26 | map = gee.Map(basemap = 'SATELLITE') 27 | map 28 | 29 | roi = map.draw_last_feature.geometry() 30 | 31 | roi 32 | 33 | def temp_val(img): 34 | date = img.date().format('YYYY-MM-dd') 35 | temp_mean = img.reduceRegion(reducer = ee.Reducer.mean(), geometry = roi, scale = 10000).values().get(0) 36 | return ee.Feature(None, {'date': date, 'temp': temp_mean}) 37 | 38 | features = temp.map(temp_val) 39 | 40 | features 41 | 42 | data_list = features.toList(features.size()).getInfo() 43 | 44 | data_list 45 | 46 | date = [item['properties']['date'] for item in data_list] 47 | temp_list = [item['properties']['temp'] for item in data_list] 48 | 49 | temp_list 50 | 51 | import pandas as pd 52 | 53 | df = pd.DataFrame({'date': date, 'temp': temp_list}).round(2) 54 | 55 | df 56 | 57 | df.to_csv('temp_2022-2023.csv') 58 | 59 | df['date'] = pd.to_datetime(df['date']) 60 | 61 | import matplotlib.pyplot as plt 62 | 63 | plt.plot(df['date'], df['temp'], lw = 2, ls = '--', color = 'red', marker = 'o') 64 | plt.title('temperature') 65 | plt.ylabel('K$^o$') 66 | plt.savefig('temp_fig.png',dpi = 360) 67 | -------------------------------------------------------------------------------- /0102_xee_anomaly: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0010_anomaly_mapping.ipynb 3 | 4 | utorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-107: Anomaly Mapping, using Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 12 | 13 | """ 14 | 15 | import ee 16 | 17 | import xarray as xr 18 | import geopandas as gpd 19 | import matplotlib.pyplot as plt 20 | 21 | !pip install xee 22 | 23 | import xee 24 | 25 | ee.Authenticate() 26 | ee.Initialize(project = 'ee-amirhosseinahrari', opt_url='https://earthengine-highvolume.googleapis.com') 27 | 28 | sm = ee.ImageCollection("IDAHO_EPSCOR/TERRACLIMATE").select('soil').filterDate('2000', '2024') 29 | 30 | sm_ds = xr.open_dataset(sm, engine = 'ee') 31 | 32 | sm_ds 33 | 34 | sm_annual = sm_ds.resample(time = 'YE').mean('time') * 0.1 35 | 36 | sm_annual 37 | 38 | sm_mean = sm_annual.mean('time') 39 | 40 | sm_mean 41 | 42 | sm_mean['soil'].plot(x = 'lon', y = 'lat', cmap = 'jet', figsize = (7,4), vmin = 10, vmax = 100) 43 | plt.savefig('sm_mean.png', dpi = 360) 44 | 45 | anomaly = sm_annual - sm_mean 46 | 47 | anomaly 48 | 49 | shp = gpd.read_file('/content/World_Countries_Generalized.shp') 50 | 51 | shp 52 | 53 | shp.crs 54 | 55 | countries = shp.to_crs('EPSG:4326') 56 | 57 | countries.crs 58 | 59 | sub = anomaly.sel(lon = slice(0,180), lat = slice(0,90), time = '2020-12-31') 60 | 61 | fig, ax = plt.subplots(figsize = (9,4)) 62 | sub['soil'].plot(x = 'lon', y = 'lat', cmap = 'coolwarm_r', vmin = -10, vmax = 10, ax = ax) 63 | countries.boundary.plot(ax = ax, lw = 1, color = 'black') 64 | 65 | plt.savefig('sm_anomaly.png', dpi = 360) 66 | -------------------------------------------------------------------------------- /0143_xee_mod_snow_gap_filling: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0060_snow_gapfilling.ipynb 3 | 4 | 5 | utorial Code by Amirhossein Ahrari 6 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 7 | Tutorial Video: Google Earth Engine Tutorial-148: MODIS Snow Cover Product Gap-Filling, using Python API (Xee) 8 | 9 | This code is part of a tutorial series on Earth Engine programming techniques 10 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 11 | this code for academic and non-academic purposes. Don't forget to subscribe to 12 | the Amirhossein Ahrari channel and follow the videos to support the instructor 13 | 14 | """ 15 | 16 | import ee 17 | import geemap 18 | !pip install xee 19 | import xee 20 | import xarray as xr 21 | 22 | ee.Authenticate() 23 | ee.Initialize( 24 | project = 'ee-amirhosseinahrari', 25 | opt_url = 'https://earthengine-highvolume.googleapis.com' 26 | ) 27 | 28 | map = geemap.Map(basemap = 'SATELLITE') 29 | map 30 | 31 | roi = map.draw_last_feature.geometry() 32 | 33 | roi 34 | 35 | mod = ( 36 | ee.ImageCollection("MODIS/061/MOD10A1") 37 | .filterDate('2020','2021') 38 | .select('NDSI_Snow_Cover') 39 | ) 40 | 41 | mod 42 | 43 | ds = xr.open_dataset( 44 | mod, 45 | engine = 'ee', 46 | crs = 'EPSG:4326', 47 | geometry = roi, 48 | scale = 0.01 49 | ) 50 | 51 | ds 52 | 53 | ds.sel(time = ds.time.dt.month == 1).NDSI_Snow_Cover.plot( 54 | x = 'lon', 55 | y = 'lat', 56 | col = 'time', 57 | col_wrap = 7, 58 | robust = True 59 | ) 60 | 61 | ds_rolling = ds.rolling(time = 10, center = True, min_periods = 1).median('time') 62 | 63 | ds_fill = ds.fillna(ds_rolling) 64 | 65 | ds_fill.sel(time = ds_rolling.time.dt.month == 1).NDSI_Snow_Cover.plot( 66 | x = 'lon', 67 | y = 'lat', 68 | col = 'time', 69 | col_wrap = 7, 70 | robust = True 71 | ) 72 | 73 | !pip install netCDF4 74 | import netCDF4 75 | 76 | ds_fill.to_netcdf('snow_cover.nc') 77 | -------------------------------------------------------------------------------- /00088_jrc_lake: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | Tutorial Video: Google Earth Engine Tutorial-93: Lake Spatial Monitoring 6 | 7 | This code is part of a tutorial series on Earth Engine programming techniques 8 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 9 | this code for academic and non-academic purposes. Don't forget to subscribe to 10 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 11 | */ 12 | 13 | 14 | 15 | var cor = [ 16 | [53.27413375651567,29.04282136448216], 17 | [54.38100631510942,29.04282136448216], 18 | [54.38100631510942,29.941704158637535], 19 | [53.27413375651567,29.941704158637535], 20 | [53.27413375651567,29.04282136448216] 21 | ] 22 | 23 | var geometry = ee.Geometry.Polygon(cor) 24 | 25 | 26 | var jrc = ee.Image("JRC/GSW1_4/GlobalSurfaceWater") 27 | 28 | print(jrc) 29 | 30 | 31 | var occ = jrc.select('occurrence') 32 | 33 | Map.addLayer(occ, [], 'occurrence', false) 34 | 35 | var abs_change = jrc.select('change_abs') 36 | 37 | Map.addLayer(abs_change,[],'abs_change',false) 38 | 39 | var norm_change = jrc.select('change_norm') 40 | 41 | Map.addLayer(norm_change,[],'change_norm', false) 42 | 43 | var seasonal = jrc.select('seasonality') 44 | 45 | Map.addLayer(seasonal,[], 'seasonal', false) 46 | 47 | var rec = jrc.select('recurrence') 48 | 49 | Map.addLayer(rec,[],'recurrence',false) 50 | 51 | 52 | var transition = jrc.select('transition') 53 | 54 | Map.addLayer(transition,{min: 0, max: 10, palette:[ 55 | '#ffffff', '#0000ff', '#22b14c', '#d1102d', '#99d9ea', '#b5e61d', '#e6a1aa', '#ff7f27', '#ffc90e', 56 | '#7f7f7f', '#c3c3c3' 57 | ]},'transition',false) 58 | 59 | 60 | Export.image.toDrive({ 61 | image: transition.clip(geometry), 62 | description: 'transition', 63 | scale: 30, 64 | region: geometry, 65 | crs: 'EPSG:4326', 66 | folder: 'test' 67 | }) 68 | 69 | 70 | -------------------------------------------------------------------------------- /0129_export_ee: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0043_export_xarray.ipynb 3 | 4 | 5 | Tutorial Code by Amirhossein Ahrari 6 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 7 | Tutorial Video: Google Earth Engine Tutorial-134: Export from Xee Files, in Python API 8 | 9 | This code is part of a tutorial series on Earth Engine programming techniques 10 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 11 | this code for academic and non-academic purposes. Don't forget to subscribe to 12 | the Amirhossein Ahrari channel and follow the videos to support the instructor 13 | 14 | """ 15 | 16 | import ee 17 | import geemap 18 | import xarray as xr 19 | 20 | !pip install xee 21 | import xee 22 | 23 | ee.Authenticate() 24 | ee.Initialize( 25 | project = 'ee-amirhosseinahrari', 26 | opt_url = 'https://earthengine-highvolume.googleapis.com' 27 | ) 28 | 29 | map = geemap.Map(basemap = 'SATELLITE') 30 | map 31 | 32 | roi = map.draw_last_feature.geometry() 33 | 34 | roi 35 | 36 | pr = ( 37 | ee.ImageCollection("NOAA/PERSIANN-CDR") 38 | .filterDate('2015','2016') 39 | ) 40 | pr 41 | 42 | ds = xr.open_dataset( 43 | pr, 44 | engine = 'ee', 45 | crs = 'EPSG:4326', 46 | scale = 0.3, 47 | geometry = roi 48 | ) 49 | 50 | ds 51 | 52 | monthly = ds.resample(time = 'M').sum('time') 53 | 54 | !pip install rioxarray 55 | import rioxarray 56 | 57 | monthly = monthly.rio.write_crs('EPSG:4326', inplace = True) 58 | monthly = monthly.rio.set_spatial_dims(x_dim = 'lon', y_dim = 'lat', inplace = True) 59 | monthly.rio.write_coordinate_system(inplace = True) 60 | 61 | !pip install netCDF4 62 | import netCDF4 63 | 64 | monthly.to_netcdf('monthly_pr.nc') 65 | 66 | import matplotlib.pyplot as plt 67 | 68 | monthly.precipitation.plot( 69 | x = 'lon', 70 | y = 'lat', 71 | col = 'time', 72 | col_wrap = 4, 73 | robust = True 74 | ) 75 | 76 | plt.savefig('monthly_pr.png', dpi = 360, bbox_inches = 'tight') 77 | 78 | -------------------------------------------------------------------------------- /00005_dry_wet_days: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | var cor = [ 13 | [52.44694261887793,36.17836425046897], 14 | [53.04020433762793,36.17836425046897], 15 | [53.04020433762793,36.61168836568063], 16 | [52.44694261887793,36.61168836568063], 17 | [52.44694261887793,36.17836425046897] 18 | ] 19 | 20 | var roi = ee.Geometry.Polygon(cor); 21 | 22 | Map.centerObject(roi); 23 | 24 | 25 | var time_start = '2010' , time_end = '2020' 26 | 27 | var pr = imageCollection 28 | .filterDate(time_start, time_end); 29 | 30 | function pr_class(img){ 31 | var pr_mean = img.reduceRegion({ 32 | reducer: ee.Reducer.mean(), geometry: roi, scale: 27000 33 | }).values().get(0); 34 | var pr_max = img.reduceRegion({ 35 | reducer: ee.Reducer.max(), geometry: roi, scale: 27000 36 | }).values().get(0); 37 | return img 38 | .copyProperties(img, img.propertyNames()) 39 | .set('pr_mean', pr_mean) 40 | .set('pr_max', pr_max) 41 | } 42 | 43 | var pr_values = pr.map(pr_class); 44 | 45 | var dry = pr_values 46 | .filter(ee.Filter.lt('pr_mean',0.5)); 47 | 48 | print( 49 | ui.Chart.image.series(dry, roi, ee.Reducer.mean(), 50 | 27000, 'system:time_start').setChartType('ColumnChart') 51 | ) 52 | 53 | var wet = pr_values.filter(ee.Filter.gt('pr_mean',1)); 54 | 55 | print( 56 | ui.Chart.image.series(wet, roi, ee.Reducer.mean(), 57 | 270000, 'system:time_start').setChartType('ColumnChart') 58 | ) 59 | 60 | var mid = pr_values 61 | .filter(ee.Filter.gte('pr_mean',0.5)) 62 | .filter(ee.Filter.lte('pr_mean', 1)); 63 | 64 | print(mid.aggregate_array('pr_mean')) 65 | 66 | -------------------------------------------------------------------------------- /00024_otsu_water: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | 7 | This code is part of a tutorial series on Earth Engine programming techniques 8 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 9 | this code for academic and non-academic purposes. Don't forget to subscribe to 10 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 11 | */ 12 | 13 | var cor = [ 14 | [44.89140339357055,37.09921636762552], 15 | [46.05595417482055,37.09921636762552], 16 | [46.05595417482055,38.354790162350284], 17 | [44.89140339357055,38.354790162350284], 18 | [44.89140339357055,37.09921636762552] 19 | ] 20 | 21 | var roi = ee.Geometry.Polygon(cor) 22 | 23 | Map.centerObject(roi); 24 | Map.addLayer(roi) 25 | 26 | // call modis surface reflectance image 27 | 28 | var modis = ee.ImageCollection("MODIS/061/MOD09A1") 29 | .filterDate('2001','2023') 30 | .map(function(img){ 31 | var bands = img.select('sur_refl.*').multiply(0.0001); 32 | var ndwi = bands.normalizedDifference(['sur_refl_b04','sur_refl_b02']).rename('ndwi'); 33 | return ndwi 34 | .copyProperties(img, img.propertyNames()) 35 | }); 36 | 37 | Map.addLayer(modis.median().clip(roi),[],'modis',false); 38 | 39 | print( 40 | ui.Chart.image.histogram(modis.median(),roi,500) 41 | ) 42 | 43 | // otsu function to find the accurate threshold 44 | 45 | 46 | var oeel=require('users/OEEL/lib:loadAll'); 47 | 48 | var otsu = oeel.ImageCollection.OtsuThreshold(modis, 'ndwi'); 49 | 50 | print( 51 | ui.Chart.image.histogram(otsu,roi,500) 52 | ) 53 | 54 | var thr = ee.Number(otsu.reduceRegion({ 55 | reducer: ee.Reducer.mean(), geometry: roi, scale: 500 56 | }).values().get(0)); 57 | 58 | 59 | print('water body threshold',thr) 60 | 61 | 62 | // apply a threshold on image 63 | 64 | var ndwis = modis.filterDate('2020','2021').toBands().gt(thr); 65 | 66 | Map.addLayer(ndwis.clip(roi),[],'ndwi_thr',false) 67 | 68 | -------------------------------------------------------------------------------- /00053_modis_snow_duration: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | var cor = [24.852452283823133,60.25776822930124] 13 | 14 | var geometry = ee.Geometry.Point(cor) 15 | 16 | var table = ee.FeatureCollection("FAO/GAUL/2015/level1") 17 | 18 | 19 | var roi = table.filterBounds(geometry).map(function(feature){ 20 | return feature.simplify(1000) 21 | }) 22 | 23 | Map.centerObject(roi) 24 | Map.addLayer(roi) 25 | 26 | 27 | var modis = ee.ImageCollection("MODIS/061/MOD10A1") 28 | .select('NDSI_Snow_Cover') 29 | .filterDate('2023', '2024'); 30 | 31 | 32 | 33 | 34 | var days = 7 35 | var mill = ee.Number(days).multiply(1000 * 24 * 3600) 36 | var filter = ee.Filter.maxDifference({ 37 | difference: mill, leftField: 'system:time_start', rightField: 'system:time_start' 38 | }); 39 | var join = ee.Join.saveAll('images') 40 | var join_collection = ee.ImageCollection(join.apply(modis, modis, filter)) 41 | 42 | var smooth_collection = join_collection.map(function(img){ 43 | var images = ee.ImageCollection.fromImages(img.get('images')).reduce(ee.Reducer.percentile([75])).rename('smoothed') 44 | return img.rename('original').addBands(images) 45 | }) 46 | 47 | print( 48 | ui.Chart.image.series(smooth_collection, roi, ee.Reducer.mean(), 500, 'system:time_start') 49 | ) 50 | 51 | Map.addLayer(smooth_collection.toBands().clip(roi),[],'modis_ndsi_smoothed',false) 52 | 53 | 54 | var snow_duration = smooth_collection.select('smoothed').map(function(img){ 55 | var thr = img.gt(40) 56 | return thr 57 | }).sum(); 58 | 59 | Map.addLayer(snow_duration.clip(roi), [],'snow_duration',false) 60 | 61 | -------------------------------------------------------------------------------- /0144_xee_pr_pca: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0062_precipitation_pattern_pca.ipynb 3 | 4 | utorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-149: Precipitation Spatio-Temporal Analysis using PCA, using Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | 14 | """ 15 | 16 | import ee 17 | import geemap 18 | import xarray as xr 19 | !pip install xee 20 | import xee 21 | 22 | ee.Authenticate() 23 | ee.Initialize( 24 | project = 'ee-amirhosseinahrari', 25 | opt_url = 'https://earthengine-highvolume.googleapis.com' 26 | ) 27 | 28 | roi = ee.FeatureCollection("UN/Geodata/BNDA_simplified/current").filter(ee.Filter.stringContains('nam_en', 'Iran')).geometry() 29 | roi 30 | 31 | map = geemap.Map(basemap = 'SATELLITE') 32 | map.centerObject(roi, 5) 33 | map.addLayer(roi, {}, 'roi') 34 | map 35 | 36 | pr = ( 37 | ee.ImageCollection("NOAA/PERSIANN-CDR") 38 | .filterDate('2001','2010') 39 | .map(lambda img: img.clip(roi).copyProperties(img, img.propertyNames())) 40 | 41 | ) 42 | 43 | pr 44 | 45 | ds = xr.open_dataset( 46 | pr, 47 | engine = 'ee', 48 | crs = 'EPSG:4326', 49 | geometry = roi, 50 | scale = 0.27 51 | ) 52 | 53 | ds 54 | 55 | ds_mean = ds.mean(dim = 'time') 56 | 57 | ds_mean.precipitation.plot( 58 | x = 'lon', 59 | y = 'lat', 60 | robust = True 61 | ) 62 | 63 | !pip install xeofs 64 | import xeofs as xf 65 | 66 | pca = xf.single.EOF(n_modes = 10) 67 | pca.fit(ds, dim = 'time') 68 | 69 | comp = pca.components() 70 | 71 | comp.precipitation.plot( 72 | x = 'lon', 73 | y = 'lat', 74 | robust = True, 75 | col = 'mode', 76 | col_wrap = 5 77 | ) 78 | -------------------------------------------------------------------------------- /00020_water_turbidity: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | 7 | This code is part of a tutorial series on Earth Engine programming techniques 8 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 9 | this code for academic and non-academic purposes. Don't forget to subscribe to 10 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 11 | */ 12 | 13 | 14 | var cor = [ 15 | [48.69819149851601,29.554928660523107], 16 | [49.91767392039101,29.554928660523107], 17 | [49.91767392039101,30.671567766536796], 18 | [48.69819149851601,30.671567766536796], 19 | [48.69819149851601,29.554928660523107] 20 | ] 21 | 22 | var roi = ee.Geometry.Polygon(cor) 23 | 24 | Map.centerObject(roi); 25 | 26 | // sentinel-2 images 27 | 28 | var sen = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED") 29 | .select(['B[2-4]','B8']) 30 | .filterDate('2023','2024') 31 | .filterBounds(roi) 32 | .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',10)) 33 | .median().multiply(0.0001); 34 | 35 | Map.addLayer(sen.clip(roi), 36 | {bands:['B8','B4','B3']},'false color', false) 37 | 38 | var ndwi = sen.normalizedDifference(['B3','B8']).rename('ndwi'); 39 | 40 | Map.addLayer(ndwi.clip(roi),[],'ndwi',false); 41 | 42 | print( 43 | ui.Chart.image.histogram(ndwi,roi,100) 44 | ) 45 | 46 | var thr = ndwi.gt(0.1); 47 | 48 | Map.addLayer(thr.clip(roi),[],'thr',false) 49 | 50 | 51 | var sen_mask = sen.updateMask(thr); 52 | 53 | Map.addLayer(sen_mask.clip(roi),[],'sen_mask',false) 54 | 55 | var ndti = sen_mask.normalizedDifference(['B4','B3']).rename('ndti') 56 | 57 | Map.addLayer(ndti.clip(roi),{ 58 | palette: ['blue','green','yellow','orange','red'] 59 | }, 'ndti', false) 60 | 61 | 62 | Export.image.toDrive({ 63 | image: ndti.clip(roi), 64 | description: 'sen2_ndti', 65 | region: roi, 66 | scale: 10, 67 | crs: ndti.getInfo().crs, 68 | maxPixels: 1e13, 69 | folder: 'test' 70 | }) 71 | 72 | 73 | -------------------------------------------------------------------------------- /00065_snow_collection: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | 13 | var time_start = ee.Date('1950') 14 | var time_end = ee.Date('2023') 15 | var time_dif = time_end.difference(time_start, 'year').round() 16 | 17 | 18 | var cor = [-104.91143662929535,42.855066925273036] 19 | 20 | var geometry = ee.Geometry.Point(cor) 21 | 22 | var era = ee.ImageCollection("ECMWF/ERA5_LAND/DAILY_AGGR") 23 | .select('snow_cover') 24 | .filterDate(time_start,time_end) 25 | 26 | var era_mean = era.filterDate('2020','2021').mean() 27 | 28 | Map.addLayer(era_mean, [],'era_mean', false) 29 | 30 | var test_snow = era.filterDate('2020','2021') 31 | .map(function(img){return img.gt(10)}).sum(); 32 | 33 | Map.addLayer(test_snow,{min: 0, max: 365},'snow_frequ',false) 34 | 35 | var list = ee.List.sequence(0, time_dif).map(function(i){ 36 | return ee.Date.fromYMD(1950, 1, 1).advance(i, 'year') 37 | }) 38 | 39 | print(list) 40 | 41 | var annual_frequency = ee.ImageCollection(list.map(function(date){ 42 | var start_date = ee.Date(date); 43 | var end_date = start_date.advance(1, 'year') 44 | var annual_snow = era.filterDate(start_date, end_date) 45 | .map(function(img){return img.gt(10)}).sum(); 46 | return annual_snow 47 | .set('system:time_start', start_date.millis()) 48 | .set('system:time_end', end_date.millis()) 49 | .set('date', start_date.format('YYYY')) 50 | })); 51 | 52 | Map.addLayer(annual_frequency.toBands(), [], 'snow_frequency_coll', false) 53 | 54 | 55 | print( 56 | ui.Chart.image.series(annual_frequency, geometry, ee.Reducer.first(), 57 | 10000, 'system:time_start') 58 | ) 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /00069_sentinel2_water_chlorophyll: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | 7 | This code is part of a tutorial series on Earth Engine programming techniques 8 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 9 | this code for academic and non-academic purposes. Don't forget to subscribe to 10 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 11 | */ 12 | 13 | var cor = [-119.54665080086161,40.038023972187226] 14 | 15 | var geometry = ee.Geometry.Point(cor) 16 | 17 | var cor2 = [ 18 | [-119.77142190684849,39.825295708288806], 19 | [-119.31274270762974,39.825295708288806], 20 | [-119.31274270762974,40.25006751768576], 21 | [-119.77142190684849,40.25006751768576], 22 | [-119.77142190684849,39.825295708288806] 23 | ] 24 | 25 | var geometry2 = ee.Geometry.Polygon(cor2) 26 | 27 | Map.centerObject(geometry2) 28 | 29 | 30 | var sentinel = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED") 31 | .filterDate('2021-09-01','2021-10-01') 32 | .filterBounds(geometry) 33 | .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',45)) 34 | .map(function(img){ 35 | var bands = img.select('B.*').multiply(0.0001) 36 | var ndwi = bands.normalizedDifference(['B3','B8']).rename('ndwi') 37 | var thr = ndwi.gt(0.1) 38 | var ndci = bands.normalizedDifference(['B5','B4']).rename('ndci') 39 | return ndci.updateMask(thr) 40 | .copyProperties(img,['system:time_start','system:time_end']) 41 | }) 42 | 43 | print(sentinel) 44 | 45 | Map.addLayer(sentinel.toBands().clip(geometry2), [], 'ndci', false) 46 | 47 | 48 | var target = sentinel.filterDate('2021-09-08','2021-09-09') 49 | 50 | Map.addLayer(target.toBands().select([0]).clip(geometry2), [], 'ndci-target', false) 51 | 52 | 53 | Export.image.toDrive({ 54 | image: target.mean().clip(geometry2), 55 | description: 'ndci', 56 | scale: 20, 57 | region: geometry2, 58 | maxPixels: 1e13, 59 | crs: 'EPSG:4326', 60 | folder: 'Chlorophyll' 61 | }) 62 | 63 | -------------------------------------------------------------------------------- /00086_temp_harmonic: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-91: Temeprature Seasonal Analysis, using Harmonic Modelling 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 12 | */ 13 | 14 | 15 | var cor = [ 16 | [42.592923031675824,20.1105768020536], 17 | [64.91714178167582,20.1105768020536], 18 | [64.91714178167582,41.35451307842085], 19 | [42.592923031675824,41.35451307842085], 20 | [42.592923031675824,20.1105768020536] 21 | ] 22 | 23 | var geometry = ee.Geometry.Polygon(cor) 24 | 25 | 26 | 27 | Map.centerObject(geometry) 28 | 29 | var temp = ee.ImageCollection("ECMWF/ERA5_LAND/MONTHLY_AGGR") 30 | .select('temperature_2m') 31 | .filterDate('1980','2021') 32 | 33 | print(temp.size()) 34 | print(temp.limit(20)) 35 | 36 | 37 | var para = temp.map(function(img){ 38 | var date = ee.Date(img.get('system:time_start')) 39 | var phase = date.getFraction('year').multiply(2 * Math.PI) 40 | var sin = phase.sin() 41 | var cos = phase.cos() 42 | var time = date.difference(ee.Date('1970'), 'year') 43 | var indep = ee.Image.cat([sin, cos, time, 1]).double() 44 | return indep.addBands(img) 45 | .copyProperties(img, ['system:time_start','system:time_end']) 46 | }); 47 | 48 | var model = para.reduce(ee.Reducer.linearRegression(4, 1)) 49 | 50 | var coef = model.select('coefficients').arrayProject([0]).arrayFlatten([['sin','cos','slope', 'offset']]) 51 | 52 | Map.addLayer(coef.clip(geometry),[],'coef',false) 53 | 54 | Export.image.toDrive({ 55 | image: coef.clip(geometry), 56 | description: 'harmonic', 57 | scale: 11000, 58 | region: geometry, 59 | crs: 'EPSG:4326', 60 | folder: 'test' 61 | }) 62 | 63 | -------------------------------------------------------------------------------- /0110_xee_irrigation_index: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0018_irrigation_index.ipynb 3 | 4 | utorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-115: Simple Irrigation Index, using Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | """ 14 | 15 | import ee 16 | import geemap as gee 17 | import xarray as xr 18 | 19 | !pip install xee 20 | import xee 21 | 22 | ee.Authenticate() 23 | ee.Initialize(project = 'ee-amirhosseinahrari', opt_url = 'https://earthengine-highvolume.googleapis.com') 24 | 25 | map = gee.Map(basemap = 'SATELLITE') 26 | map 27 | 28 | roi = map.draw_last_feature.geometry() 29 | 30 | ndvi = ee.ImageCollection("MODIS/061/MOD13A2").select('NDVI').filterDate('2020','2021').max().multiply(0.0001) 31 | 32 | ndvi_mask = ndvi.gt(0.5) 33 | 34 | ndvi_ds = xr.open_dataset(ndvi, engine = 'ee', scale = 0.01, crs = 'EPSG:4326', geometry = roi) 35 | 36 | ndvi_ds 37 | 38 | ndvi_ds.NDVI.plot(x = 'lon', y = 'lat', cmap = 'gist_earth_r', robust = True) 39 | 40 | thr = ndvi_ds.NDVI > 0.5 41 | 42 | thr 43 | 44 | thr.plot(x = 'lon', y = 'lat') 45 | 46 | terra = ee.ImageCollection("IDAHO_EPSCOR/TERRACLIMATE").filterDate('2020','2021').select('aet','pr') 47 | 48 | def masking(img): 49 | return img.updateMask(ndvi_mask).copyProperties(img, img.propertyNames()) 50 | 51 | terra_mask = terra.map(masking) 52 | 53 | terra_ds = xr.open_dataset(terra_mask, engine = 'ee', scale = 0.05, crs = 'EPSG:4326', geometry = roi) 54 | 55 | terra_ds 56 | 57 | terra_ds['deficit'] = terra_ds.pr - (terra_ds.aet * 0.1) 58 | 59 | terra_ds 60 | 61 | terra_ds.deficit.plot(x = 'lon', y = 'lat', cmap = 'coolwarm_r', robust = True, col = 'time', col_wrap = 4, vmin = -20) 62 | -------------------------------------------------------------------------------- /0111_xee_pr_forecast: -------------------------------------------------------------------------------- 1 | 2 | """GEE_0019_precipitaion_forecast.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-116: Precipitation Forecast, using Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | """ 14 | 15 | 16 | 17 | import ee 18 | import geemap as gee 19 | import xarray as xr 20 | 21 | !pip install xee 22 | import xee 23 | 24 | ee.Authenticate() 25 | ee.Initialize(project = 'ee-amirhosseinahrari', opt_url = 'https://earthengine-highvolume.googleapis.com') 26 | 27 | map = gee.Map(basemap = 'SATELLITE') 28 | map 29 | 30 | roi = map.draw_last_feature.geometry() 31 | 32 | collection = ee.ImageCollection("NOAA/PERSIANN-CDR").filterDate('2005','2024') 33 | 34 | ds = xr.open_dataset(collection, engine = 'ee', crs = 'EPSG:4326', geometry = roi, scale = 0.27) 35 | 36 | ds 37 | 38 | ds_mean = ds.mean('time') 39 | 40 | ds_mean 41 | 42 | ds_mean.precipitation.plot(x = 'lon', y = 'lat', robust = True) 43 | 44 | ds_var = ds.var('time') 45 | 46 | ds_var.precipitation.plot(x = 'lon', y = 'lat', robust = True) 47 | 48 | monthly = ds.resample(time = 'M').sum() 49 | 50 | monthly 51 | 52 | point = monthly.sel(lon = 48.73310048088049, lat = 31.808809525085334, method ='nearest') 53 | 54 | point 55 | 56 | df = point.to_dataframe()['precipitation'] 57 | 58 | df 59 | 60 | df.plot() 61 | 62 | from statsmodels.tsa.statespace.sarimax import SARIMAX 63 | 64 | model = SARIMAX(df, order = (1,1,1), seasonal_order = (1,1,0,48)) # this gives a better result 65 | result = model.fit() 66 | 67 | forecast = result.get_forecast(steps = 10 * 12) 68 | 69 | df.plot() 70 | forecast.predicted_mean.plot() 71 | 72 | forecast.predicted_mean.to_csv('pr_forecasted.csv') 73 | -------------------------------------------------------------------------------- /00038_flood_ndvi_change: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | var cor = [[54.38668797159735,36.92373567956783], 13 | [54.62976048136297,36.92373567956783], 14 | [54.62976048136297,37.075089492834536], 15 | [54.38668797159735,37.075089492834536], 16 | [54.38668797159735,36.92373567956783]] 17 | 18 | 19 | var roi = ee.Geometry.Polygon(cor) 20 | 21 | Map.centerObject(roi); 22 | 23 | var time_start = '2019', time_end = '2020' 24 | 25 | var before = ee.ImageCollection("LANDSAT/LC08/C02/T1_L2") 26 | .select('SR.*') 27 | .filterDate(time_start, time_end) 28 | .filterBounds(roi) 29 | .filter(ee.Filter.calendarRange(2,2,'month')) 30 | .median().multiply(0.0000275).add(-0.2); 31 | 32 | var ndvi_before = before.normalizedDifference(['SR_B5','SR_B4']) 33 | 34 | 35 | Map.addLayer(ndvi_before.clip(roi),[],'before', false); 36 | 37 | var after = ee.ImageCollection("LANDSAT/LC08/C02/T1_L2") 38 | .select('SR.*') 39 | .filterDate(time_start, time_end) 40 | .filterBounds(roi) 41 | .filter(ee.Filter.calendarRange(4,4,'month')) 42 | .median().multiply(0.0000275).add(-0.2); 43 | 44 | var ndvi_after = after.normalizedDifference(['SR_B5','SR_B4']); 45 | 46 | Map.addLayer(ndvi_after.clip(roi), [], 'ndvi_after', false ) 47 | 48 | 49 | var ndvi_change = ndvi_before.subtract(ndvi_after); 50 | 51 | Map.addLayer(ndvi_change.clip(roi),[],'ndvi_change', false) 52 | 53 | var change_percent = ((ndvi_after.subtract(ndvi_before)).divide(ndvi_before)).multiply(100) 54 | var change_thr = change_percent.lt(0); 55 | var change_mask = change_percent.updateMask(change_thr); 56 | 57 | Map.addLayer(change_mask.clip(roi),[],'change_percent', false) 58 | -------------------------------------------------------------------------------- /0120_xee_veg_opt_depth: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | 4 | 5 | Tutorial Code by Amirhossein Ahrari 6 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 7 | Tutorial Video: Google Earth Engine Tutorial-125: Vegetation Optical Depth Product, in Python API (Xee) 8 | 9 | This code is part of a tutorial series on Earth Engine programming techniques 10 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 11 | this code for academic and non-academic purposes. Don't forget to subscribe to 12 | the Amirhossein Ahrari channel and follow the videos to support the instructor 13 | 14 | 15 | """ 16 | 17 | 18 | 19 | import ee 20 | import geemap 21 | import xarray as xr 22 | 23 | !pip install xee 24 | import xee 25 | 26 | ee.Authenticate() 27 | ee.Initialize(project ='ee-amirhosseinahrari', opt_url = 'https://earthengine-highvolume.googleapis.com') 28 | 29 | map = geemap.Map() 30 | map 31 | 32 | point = map.draw_last_feature.geometry() 33 | point 34 | 35 | feature = ee.FeatureCollection("WWF/HydroSHEDS/v1/Basins/hybas_2").filterBounds(point).geometry().simplify(1000) 36 | 37 | map2 = geemap.Map() 38 | map2.centerObject(feature, 5) 39 | map2.addLayer(feature,{},'basin') 40 | map2 41 | 42 | collection = ee.ImageCollection("projects/sat-io/open-datasets/VODCA/L_BAND_V2").filterDate('2015','2020') 43 | collection 44 | 45 | ds = xr.open_dataset(collection, engine = 'ee', scale = 0.25, crs = 'EPSG:4326', geometry = feature) 46 | 47 | ds 48 | 49 | annual = ds.resample(time = 'YE').mean('time') 50 | 51 | annual.VOD.plot(x = 'lon', y = 'lat', col = 'time', robust = True, col_wrap = 3) 52 | 53 | month = ds.groupby('time.month').mean('time') 54 | 55 | import matplotlib.pyplot as plt 56 | 57 | month.VOD.plot(x = 'lon', y = 'lat', col = 'month', col_wrap = 4, robust = True) 58 | plt.savefig('VOD.png', dpi = 360, bbox_inches = 'tight') 59 | 60 | ds_sub = ds.sel(lat = 59.530075111125456 , lon =31.23284642583383, method = 'nearest') 61 | ds_sub 62 | 63 | ds_sub.VOD.plot() 64 | 65 | !pip install netCDF4 66 | import netCDF4 67 | 68 | annual.to_netcdf('annual.nc') 69 | -------------------------------------------------------------------------------- /00052_landsat_vegetation_moisture_index: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | 13 | var cor1 = [ 14 | [-113.80502319704019,42.704955393175936], 15 | [-113.56057739625894,42.704955393175936], 16 | [-113.56057739625894,42.862689736716995], 17 | [-113.80502319704019,42.862689736716995], 18 | [-113.80502319704019,42.704955393175936] 19 | ] 20 | 21 | var geometry = ee.Geometry.Polygon(cor1) 22 | 23 | Map.centerObject(geometry) 24 | 25 | var time_start = '2023', time_end = '2024' 26 | 27 | var landsat8 = ee.ImageCollection("LANDSAT/LC08/C02/T1_L2") 28 | .filterDate(time_start, time_end) 29 | .filterBounds(geometry) 30 | 31 | var landsat9 = ee.ImageCollection("LANDSAT/LC09/C02/T1_L2") 32 | .filterDate(time_start, time_end) 33 | .filterBounds(geometry) 34 | 35 | var landsat = landsat8.merge(landsat9).sort('system:time_start') 36 | .filter(ee.Filter.calendarRange(5,9,'month')) 37 | .filter(ee.Filter.lt('CLOUD_COVER', 45)) 38 | 39 | var ndmi = landsat.map(function(img){ 40 | var bands = img.select('SR_B.*') 41 | var gain = ee.Number(img.get('REFLECTANCE_MULT_BAND_1')) 42 | var offset = ee.Number(img.get('REFLECTANCE_ADD_BAND_1')) 43 | var ms = bands.multiply(gain).add(gain) 44 | var ndmi = ms.normalizedDifference(['SR_B5','SR_B6']).rename('NDMI') 45 | var mask = ndmi.gt(0) 46 | return ndmi.updateMask(mask).rename('ndmi') 47 | .copyProperties(img, img.propertyNames()) 48 | }) 49 | 50 | 51 | Map.addLayer(ndmi.toBands().clip(geometry), {},'ndmi',false) 52 | 53 | 54 | 55 | var cor2 = [-113.77680574839223,42.76979339207935] 56 | 57 | var geometry = ee.Geometry.Point(cor2) 58 | 59 | 60 | print( 61 | ui.Chart.image.series(ndmi, geometry, ee.Reducer.first(), 30, 'system:time_start') 62 | ) 63 | -------------------------------------------------------------------------------- /0139_xee_ndvi_phenology: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0053_ndvi_phenology.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-144: NDVI Phenology Analysis, in Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | 14 | 15 | """ 16 | 17 | import ee 18 | import geemap 19 | !pip install xee 20 | import xee 21 | import xarray as xr 22 | 23 | ee.Authenticate() 24 | ee.Initialize( 25 | project = 'ee-amirhosseinahrari', 26 | opt_url = 'https://earthengine-highvolume.googleapis.com' 27 | ) 28 | 29 | map = geemap.Map(basemap = 'SATELLITE') 30 | map 31 | 32 | roi = map.draw_last_feature.geometry() 33 | 34 | roi 35 | 36 | collection = ( 37 | ee.ImageCollection("NOAA/CDR/AVHRR/NDVI/V5") 38 | .filterDate('2016','2017') 39 | .select('NDVI') 40 | .map(lambda img: img.multiply(0.0001).copyProperties(img, img.propertyNames())) 41 | ) 42 | 43 | collection 44 | 45 | ds = xr.open_dataset( 46 | collection, 47 | engine = 'ee', 48 | crs = 'EPSG:4326', 49 | scale = 0.05, 50 | geometry = roi 51 | ) 52 | 53 | ds 54 | 55 | df = ds.to_dataframe().reset_index()[['time','NDVI']].set_index('time').interpolate(method = 'linear') 56 | 57 | from scipy.signal import savgol_filter 58 | 59 | df['NDVI_smoothed'] = savgol_filter( 60 | df['NDVI'], 61 | window_length = 30, 62 | polyorder = 2 63 | ) 64 | 65 | df['NDVI_smoothed'].plot() 66 | 67 | df.plot() 68 | 69 | thresh = 0.35 70 | sos = df['NDVI_smoothed'][df['NDVI_smoothed'] > thresh].index[0].date() 71 | print(f'start of growing season (sos): {sos}') 72 | eos = df['NDVI_smoothed'][df['NDVI_smoothed'] > thresh].index[-1].date() 73 | print(f'end of growing season (eos): {eos}') 74 | los = (eos - sos).days + 1 75 | print(f'length of growing season (los): {los}') 76 | -------------------------------------------------------------------------------- /00009_ndvi_trend_analysis: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | var cor = [ 13 | [44.12939360774617,24.119400388422655], 14 | [64.87158110774617,24.119400388422655], 15 | [64.87158110774617,39.70103164846671], 16 | [44.12939360774617,39.70103164846671], 17 | [44.12939360774617,24.119400388422655] 18 | ] 19 | 20 | var roi = ee.Geometry.Polygon(cor) 21 | 22 | Map.centerObject(roi); 23 | 24 | var modis = ee.ImageCollection("MODIS/061/MOD13A2") 25 | .select('NDVI') 26 | .filterDate('2001','2021'); 27 | 28 | function ndvi_time(img){ 29 | var time = img.metadata('system:time_start').divide(1e9); 30 | return img.addBands(time) 31 | .copyProperties(img, img.propertyNames()) 32 | } 33 | 34 | var modis_time = modis.map(ndvi_time); 35 | 36 | var linear_reg = modis_time.select('system:time_start','NDVI') 37 | .reduce(ee.Reducer.linearFit()).select('scale'); 38 | 39 | Map.addLayer(linear_reg.clip(roi),{palette:['red','black','green']},'linear_reg',false) 40 | 41 | 42 | var sen_slope = modis_time.select('system:time_start','NDVI') 43 | .reduce(ee.Reducer.sensSlope()).select('slope'); 44 | 45 | Map.addLayer(sen_slope.clip(roi),{palette:['red','black','green']},'sens_slope',false) 46 | 47 | Export.image.toDrive({ 48 | image: sen_slope.clip(roi), 49 | description: 'sen_slope', 50 | scale: 1000, 51 | region: roi, 52 | maxPixels: 1e13, 53 | crs: 'EPSG:4326' 54 | }) 55 | 56 | var mannkendall = modis_time.select('NDVI') 57 | .reduce(ee.Reducer.kendallsCorrelation()); 58 | 59 | Map.addLayer(mannkendall.select('NDVI_tau').clip(roi),{palette:['red','black','green']},'mannkendall',false) 60 | 61 | var forma = modis_time.select('NDVI') 62 | .formaTrend() 63 | 64 | Map.addLayer(forma.clip(roi),[],'forma',false) 65 | 66 | 67 | -------------------------------------------------------------------------------- /0109_xee_dry_spell: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0017_dry_spell.ipynb 3 | 4 | utorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-114: Precipitation Dry Spell Analysis, using Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | 14 | """ 15 | 16 | import ee 17 | import geemap as gee 18 | import xarray as xr 19 | 20 | !pip install xee 21 | import xee 22 | 23 | ee.Authenticate() 24 | ee.Initialize(project = 'ee-amirhosseinahrari', opt_url = 'https://earthengine-highvolume.googleapis.com') 25 | 26 | map = gee.Map(basemap = 'SATELLITE') 27 | map 28 | 29 | roi = map.draw_last_feature.geometry() 30 | 31 | collection = ee.ImageCollection("NOAA/PERSIANN-CDR").filterDate('2020','2022') 32 | 33 | ds = xr.open_dataset(collection, engine = 'ee', crs = 'EPSG:4326', geometry = roi, scale = 0.27) 34 | 35 | ds 36 | 37 | seasonal = ds.resample(time = 'Q').sum('time') 38 | 39 | seasonal 40 | 41 | seasonal.precipitation.plot(x = 'lon', y = 'lat', col = 'time', robust = True, col_wrap = 4, cmap = 'Spectral') 42 | 43 | point = ds.sel(lon = 52.6632665918151, lat = 36.54071077336493, method = 'nearest') 44 | 45 | point 46 | 47 | pr = point.precipitation.values 48 | time =point.time.values 49 | 50 | import pandas as pd 51 | 52 | df = pd.DataFrame({'time': time, 'pr': pr}) 53 | 54 | df 55 | 56 | df['dry'] = df['pr'] == 0 57 | 58 | df 59 | 60 | df['group'] = (df['dry'] != df['dry'].shift()).cumsum() 61 | 62 | df 63 | 64 | dry_spell = df[df['dry']].groupby('group').agg( 65 | start_date = ('time', 'first'), 66 | end_date = ('time', 'last'), 67 | duration = ('time', 'count'), 68 | intensity = ('pr', 'sum') 69 | ) 70 | 71 | dry_spell[dry_spell['duration'] > 10] 72 | 73 | result = dry_spell[dry_spell['duration'] > 10] 74 | result.to_csv('dry_spell.csv') 75 | -------------------------------------------------------------------------------- /0140_xee_trend_seasonal: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0057_trend_monitoring_seasonal_decomposition.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-145: Trend Analysis without Seasonal Impact, in Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | 14 | """ 15 | 16 | import ee 17 | import geemap 18 | !pip install xee 19 | import xee 20 | import xarray as xr 21 | import matplotlib.pyplot as plt 22 | 23 | ee.Authenticate() 24 | ee.Initialize( 25 | project = 'ee-amirhosseinahrari', 26 | opt_url = 'https://earthengine-highvolume.googleapis.com' 27 | ) 28 | 29 | map = geemap.Map(basemap = 'SATELLITE') 30 | map 31 | 32 | roi = map.draw_last_feature.geometry() 33 | 34 | roi 35 | 36 | collection = ( 37 | ee.ImageCollection("IDAHO_EPSCOR/TERRACLIMATE") 38 | .filterDate('1980','2025') 39 | .select('def') 40 | .map(lambda img: img.multiply(0.1).copyProperties(img, img.propertyNames())) 41 | ) 42 | 43 | collection 44 | 45 | ds = xr.open_dataset( 46 | collection, 47 | engine = 'ee', 48 | crs = 'EPSG:4326', 49 | geometry = roi, 50 | scale = 0.05 51 | ) 52 | 53 | ds 54 | 55 | ds_mean = ds.mean(dim = ['lon', 'lat']) 56 | 57 | df = ds_mean.to_dataframe() 58 | 59 | df.plot() 60 | 61 | from statsmodels.tsa.seasonal import seasonal_decompose 62 | 63 | model = seasonal_decompose( 64 | df['def'], 65 | model = 'additive', 66 | period = 12 67 | ) 68 | 69 | model.plot() 70 | plt.plot() 71 | 72 | df_trend = model.trend 73 | 74 | df_trend.plot() 75 | 76 | !pip install pymannkendall 77 | import pymannkendall as mk 78 | !pip install pyhomogeneity 79 | import pyhomogeneity as hg 80 | 81 | mk_test = mk.original_test(df_trend) 82 | hg_test = hg.pettitt_test(df_trend) 83 | print(f'mk_test: {mk_test}') 84 | print(f'hg_test: {hg_test}') 85 | -------------------------------------------------------------------------------- /00027_dust_clustering: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | var cor = [20.991406249999986,25.507712481650202] 13 | 14 | var cor_algeria = [0.2309396803809749,26.77681610326222] 15 | var point_algeria = ee.Geometry.Point(cor_algeria) 16 | 17 | var cor_iran = [57.53562718038097,34.0452055133763] 18 | var point_iran = ee.Geometry.Point(cor_iran) 19 | 20 | var iran_algeria = ee.FeatureCollection([ 21 | ee.Feature(point_algeria), ee.Feature(point_iran) 22 | ]) 23 | 24 | var roi = ee.Geometry.Point(cor) 25 | 26 | var training_cor = [ 27 | [-150.30742187500002,-52.9982763366959], 28 | [159.77070312499998,-52.9982763366959], 29 | [159.77070312499998,72.87600964247707], 30 | [-150.30742187500002,72.87600964247707], 31 | [-150.30742187500002,-52.9982763366959] 32 | ] 33 | 34 | var training_border = ee.Geometry.Polygon(training_cor) 35 | 36 | 37 | var aot = ee.ImageCollection("NASA/GSFC/MERRA/aer/2") 38 | .select('DUSCATAU') 39 | .filterDate('2023','2024') 40 | .filter(ee.Filter.calendarRange(12, 12, 'hour')); 41 | 42 | var aot_stack = aot.toBands(); 43 | 44 | Map.addLayer(aot_stack,[],'aot_stack',false) 45 | 46 | print( 47 | ui.Chart.image.series(aot, roi, ee.Reducer.first(), 50000, 'system:time_start') 48 | ) 49 | 50 | print( 51 | ui.Chart.image.seriesByRegion(aot, iran_algeria, ee.Reducer.first(), 52 | 'DUSCATAU', 50000, 'system:time_start', 'system:index') 53 | ) 54 | 55 | // clustering 56 | 57 | var samples = aot_stack.sample({ 58 | region: training_border, scale: 50000, numPixels: 5000 59 | }); 60 | 61 | var kmeans = ee.Clusterer.wekaKMeans(5).train(samples); 62 | 63 | var aot_map = aot_stack.cluster(kmeans); 64 | 65 | Map.addLayer(aot_map,{min: 0, max: 4, palette: ['white','yellow','orange','red','brown']},'aot_map',false) 66 | 67 | 68 | -------------------------------------------------------------------------------- /00028_dust_change_detection: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | 7 | This code is part of a tutorial series on Earth Engine programming techniques 8 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 9 | this code for academic and non-academic purposes. Don't forget to subscribe to 10 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 11 | */ 12 | 13 | var cor = [ 14 | [-18.177742170599114,-42.52013444761732], 15 | [55.65038282940088,-42.52013444761732], 16 | [55.65038282940088,41.278382650539754], 17 | [-18.177742170599114,41.278382650539754], 18 | [-18.177742170599114,-42.52013444761732] 19 | ] 20 | 21 | var roi = ee.Geometry.Polygon(cor) 22 | 23 | var aot = ee.ImageCollection("NASA/GSFC/MERRA/aer/2") 24 | .select('DUSCATAU') 25 | .filterDate('2020','2021') 26 | .filter(ee.Filter.calendarRange(12,12,'hour')); 27 | 28 | var aot_max = aot.max(); 29 | 30 | Map.addLayer(aot_max,{palette:['black','red']},'aot_max',false) 31 | 32 | var cons = ee.Image.constant(0); 33 | 34 | var clear = cons.where(aot_max.lt(0.15),10) 35 | var moderate = clear.where(aot_max.gt(0.15).and((aot_max).lt(0.3)),20); 36 | var hazy = moderate.where(aot_max.gt(0.3).and(aot_max.lt(0.5)), 30) 37 | var very_hazy = hazy.where(aot_max.gt(0.5).and(aot_max.lt(8)), 40) 38 | 39 | Map.addLayer(very_hazy,{min: 10, max:40, palette:['black','yellow','orange','red']},'very_hazy',false) 40 | 41 | 42 | // frequency of dust events 43 | 44 | var freq = aot.map(function(img){ 45 | var thr = img.gt(0.5) 46 | return thr 47 | }).sum().divide(aot.size()).multiply(100); 48 | 49 | Map.addLayer(freq,{palette:['black','yellow','orange','red']},'aot_freq',false) 50 | 51 | 52 | 53 | // trend analysis 54 | 55 | var aot_trend = aot.reduce(ee.Reducer.kendallsCorrelation()); 56 | 57 | Map.addLayer(aot_trend.select('DUSCATAU_tau'),{palette:['black','yellow','orange','red']},'aot_trend',false) 58 | 59 | 60 | Export.image.toDrive({ 61 | image: aot_trend.select('DUSCATAU_tau'), 62 | description: 'aot_kendall', 63 | scale: 50000, 64 | region: roi, 65 | crs: aot_trend.getInfo().crs, 66 | maxPixels: 1e13, 67 | }) 68 | -------------------------------------------------------------------------------- /00097_flood_depth: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-102: Flood Depth Mapping 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 12 | */ 13 | 14 | var cor = [ 15 | [52.3061190642205,28.827145835706336], 16 | [54.3825350798455,28.827145835706336], 17 | [54.3825350798455,30.227545129963662], 18 | [52.3061190642205,30.227545129963662], 19 | [52.3061190642205,28.827145835706336] 20 | ] 21 | 22 | var geometry = ee.Geometry.Polygon(cor) 23 | 24 | 25 | var jrc = ee.ImageCollection("JRC/CEMS_GLOFAS/FloodHazard/v1") 26 | .filterBounds(geometry) 27 | 28 | print(jrc.aggregate_array('return_period')) 29 | 30 | var flood_10 = jrc 31 | .filterBounds(geometry) 32 | .filter(ee.Filter.eq('return_period', 10)).mosaic() 33 | 34 | print(flood_10) 35 | 36 | Map.addLayer(flood_10.clip(geometry),{palette:['skyblue', 'blue', 'darkblue']}, 'flood10', false) 37 | 38 | print( 39 | ui.Chart.image.histogram(flood_10, geometry, 1000) 40 | ) 41 | 42 | 43 | var flood_20 = jrc 44 | .filterBounds(geometry) 45 | .filter(ee.Filter.eq('return_period', 20)).mosaic() 46 | 47 | Map.addLayer(flood_20.clip(geometry), {palette:['skyblue', 'blue', 'darkblue']}, 'flood20', false) 48 | 49 | 50 | var flood_100 = jrc 51 | .filterBounds(geometry) 52 | .filter(ee.Filter.eq('return_period', 100)).mosaic() 53 | 54 | Map.addLayer(flood_100.clip(geometry), {palette:['skyblue', 'blue', 'darkblue']}, 'flood100', false) 55 | 56 | Export.image.toDrive({ 57 | image: flood_10.clip(geometry), 58 | description: 'flood10_iran', 59 | region: geometry, 60 | scale: 1000, 61 | crs: 'EPSG:4326', 62 | folder: 'test', 63 | maxPixels: 1e13 64 | }) 65 | 66 | 67 | 68 | 69 | // var depthVis = { 70 | // min: 0, 71 | // max: 1, 72 | // palette: ['ffffff','0000ff'], 73 | // }; 74 | 75 | // Map.addLayer(jrc,depthVis, 'flood_depth',true) 76 | -------------------------------------------------------------------------------- /0116_xee_heatwave: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0024_heatwave_index.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-121: Heat Wave Index, in Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | """ 14 | 15 | import ee 16 | import geemap 17 | import xarray as xr 18 | 19 | !pip install xee 20 | import xee 21 | 22 | ee.Authenticate() 23 | ee.Initialize(project ='ee-amirhosseinahrari', opt_url = 'https://earthengine-highvolume.googleapis.com') 24 | 25 | map = geemap.Map(basemap = 'SATELLITE') 26 | map 27 | 28 | roi = map.draw_last_feature.geometry() 29 | 30 | roi 31 | 32 | collection = ee.ImageCollection("ECMWF/ERA5/DAILY").select('maximum_2m_air_temperature').filterDate('2000','2020').map( 33 | lambda img: img.subtract(273.15).copyProperties(img, img.propertyNames()) 34 | ) 35 | 36 | ds = xr.open_dataset( 37 | collection, 38 | engine = 'ee', 39 | crs = 'EPSG:4326', 40 | scale = 0.27, 41 | geometry = roi 42 | ) 43 | 44 | ds 45 | 46 | ds.maximum_2m_air_temperature.attrs['units'] = 'degC' 47 | 48 | ds 49 | 50 | !pip install xclim 51 | import xclim 52 | 53 | help(xclim.indices.heat_wave_index) 54 | 55 | index = xclim.indices.heat_wave_index( 56 | ds.maximum_2m_air_temperature, 57 | thresh = '25.0 degC', 58 | window = 5, 59 | freq = 'YS' 60 | ) 61 | 62 | index 63 | 64 | index.plot(x = 'lon', y = 'lat', col = 'time', robust = True, col_wrap = 5) 65 | 66 | index5 = index.resample(time = '5Y').max('time').rename('Heat Wave') 67 | 68 | index5.plot(x = 'lon', y = 'lat', col = 'time', col_wrap = 3, robust =True) 69 | 70 | sub = index.sel(lon = 24.767281538125793, lat = 60.278314064805166, method = 'nearest' ) 71 | 72 | sub 73 | 74 | df = sub.to_dataframe()['maximum_2m_air_temperature'] 75 | 76 | import pandas as pd 77 | 78 | df.to_csv('heat_wave.csv') 79 | 80 | df 81 | 82 | df.plot() 83 | -------------------------------------------------------------------------------- /00078_zonal_stat: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | var cor = [46.118633714162954,37.28721066932214] 13 | 14 | var geometry = ee.Geometry.Point(cor) 15 | 16 | 17 | var roi = ee.FeatureCollection("WWF/HydroSHEDS/v1/Basins/hybas_5") 18 | .filterBounds(geometry).map(function(feature){ 19 | return feature.simplify(1000) 20 | }) 21 | 22 | Map.centerObject(roi) 23 | Map.addLayer(roi) 24 | 25 | var landcover = ee.ImageCollection("MODIS/061/MCD12Q1") 26 | .mode().select('LC_Type1') 27 | 28 | var vis = { 29 | min: 1.0, 30 | max: 17.0, 31 | palette: [ 32 | '05450a', '086a10', '54a708', '78d203', '009900', 'c6b044', 'dcd159', 33 | 'dade48', 'fbff13', 'b6ff05', '27ff87', 'c24f44', 'a5a5a5', 'ff6d4c', 34 | '69fff8', 'f9ffa4', '1c0dff' 35 | ], 36 | }; 37 | 38 | Map.addLayer(landcover.clip(roi), vis, 'landcover', false) 39 | 40 | 41 | 42 | var ndvi = ee.ImageCollection("MODIS/061/MOD13Q1") 43 | .select('NDVI') 44 | .filterDate('2020','2021').median().multiply(0.0001) 45 | 46 | 47 | Map.addLayer(ndvi.clip(roi), [], 'ndvi', false) 48 | 49 | 50 | 51 | var dataset1 = ee.Image.cat([ndvi, landcover]) 52 | 53 | var zonal_stat1 = dataset1.reduceRegion({ 54 | reducer: ee.Reducer.minMax().combine(ee.Reducer.mean(), null, true).group(1, 'Landcover') 55 | , geometry: roi, scale: 250 56 | }) 57 | 58 | print(zonal_stat1) 59 | 60 | 61 | var lst = ee.ImageCollection("MODIS/061/MOD11A2") 62 | .select('LST_Day_1km') 63 | .filterDate('2020','2021').median().multiply(0.02).subtract(273.15) 64 | 65 | Map.addLayer(lst.clip(roi), [], 'lst', false) 66 | 67 | var dataset2 = ee.Image.cat([lst, landcover]) 68 | 69 | var zonal_stat2 = dataset2.reduceRegion({ 70 | reducer: ee.Reducer.minMax().combine(ee.Reducer.mean(), null, true).group(1, 'Landcover') 71 | , geometry: roi, scale: 250 72 | }) 73 | 74 | print(zonal_stat2) 75 | 76 | 77 | -------------------------------------------------------------------------------- /00025_coastline_change: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | 13 | var cor = [ 14 | [44.9080614872616,37.10065044621631], 15 | [46.1220507450741,37.10065044621631], 16 | [46.1220507450741,38.343276286611825], 17 | [44.9080614872616,38.343276286611825], 18 | [44.9080614872616,37.10065044621631] 19 | ] 20 | 21 | var roi = ee.Geometry.Polygon(cor) 22 | 23 | 24 | Map.centerObject(roi); 25 | 26 | // call modis surface reflectance 27 | // calculate ndwi median for each date 28 | 29 | var mod2001 = ee.ImageCollection("MODIS/061/MOD09Q1") 30 | .filterDate('2001','2002') 31 | .map(function(img){ 32 | var bands = img.select('sur.*').multiply(0.0001); 33 | var ndwi = bands.normalizedDifference(['sur_refl_b01','sur_refl_b02']).rename('ndwi'); 34 | return ndwi 35 | }).median().gt(0.1); 36 | 37 | Map.addLayer(mod2001.clip(roi),[],'mod2001',false); 38 | 39 | var mod2023 = ee.ImageCollection("MODIS/061/MOD09Q1") 40 | .filterDate('2023','2024') 41 | .map(function(img){ 42 | var bands = img.select('sur.*').multiply(0.0001); 43 | var ndwi = bands.normalizedDifference(['sur_refl_b01','sur_refl_b02']).rename('ndwi'); 44 | return ndwi 45 | }).median().gt(0.1); 46 | 47 | Map.addLayer(mod2023.clip(roi),[],'mod2023',false); 48 | 49 | // change detection using subtraction 50 | 51 | var change = mod2001.subtract(mod2023); 52 | 53 | Map.addLayer(change.clip(roi),[],'coastline_change',false) 54 | 55 | // conversion from raster to layer 56 | 57 | var mask = change.updateMask(change); 58 | 59 | Map.addLayer(mask.clip(roi),[],'coastline_change_mask',false) 60 | 61 | var vector = mask.reduceToVectors({ 62 | geometry: roi, scale: 250 63 | }).union(1); 64 | 65 | Map.addLayer(vector) 66 | 67 | // export 68 | 69 | Export.table.toDrive({ 70 | collection: vector, description: 'coastline', fileFormat: 'SHP', folder: 'coastline_mapping' 71 | }) 72 | -------------------------------------------------------------------------------- /0150_xee_landsat_cloud_masking: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0070_landsat_cloud_mask.ipynb 3 | 4 | utorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-155: Landsat Cloud Masking using Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | """ 14 | 15 | import ee 16 | import geemap 17 | import xarray as xr 18 | !pip install xee 19 | import xee 20 | 21 | ee.Authenticate() 22 | ee.Initialize( 23 | project = 'ee-amirhosseinahrari', 24 | opt_url = 'https://earthengine-highvolume.googleapis.com' 25 | ) 26 | 27 | map = geemap.Map(basemap = 'SATELLITE') 28 | map 29 | 30 | roi = map.draw_last_feature.geometry() 31 | 32 | roi 33 | 34 | def cloud_mask(img): 35 | qa = img.select('QA_PIXEL') 36 | dilated = qa.bitwiseAnd(1 << 1).neq(0) 37 | cirrus = qa.bitwiseAnd(2 << 1).neq(0) 38 | cloud = qa.bitwiseAnd(3 << 1).neq(0) 39 | shadow = qa.bitwiseAnd(4 << 1).neq(0) 40 | mask = dilated.Or(cirrus).Or(cloud).Or(shadow) 41 | ms = img.select('SR_B.*').multiply(2.75e-05).add(-0.2) 42 | ndvi = ms.normalizedDifference(['SR_B5', 'SR_B4']).rename('ndvi') 43 | return ndvi.updateMask(mask.Not()).copyProperties(img, ['system:time_start']) 44 | 45 | 46 | landsat = ( 47 | ee.ImageCollection("LANDSAT/LC09/C02/T1_L2") 48 | .filterDate('2024','2025') 49 | .filterBounds(roi) 50 | .map(cloud_mask) 51 | ) 52 | 53 | landsat 54 | 55 | ds = xr.open_dataset( 56 | landsat, 57 | engine = 'ee', 58 | crs = 'EPSG:4326', 59 | geometry = roi, 60 | scale = 0.001 61 | ) 62 | 63 | ds = ds.sortby('time') * 1 64 | 65 | ds.ndvi.plot( 66 | x = 'lon', 67 | y = 'lat', 68 | col = 'time', 69 | col_wrap = 6, 70 | robust = True 71 | ) 72 | 73 | ds_rol = ds.rolling(time = 7, center = True, min_periods = 1).mean('time') 74 | 75 | ds_rol.ndvi.plot( 76 | x = 'lon', 77 | y = 'lat', 78 | col = 'time', 79 | robust = True, 80 | col_wrap = 6 81 | ) 82 | -------------------------------------------------------------------------------- /00043_sen3_ndvi: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | var table = ee.FeatureCollection("WWF/HydroSHEDS/v1/Basins/hybas_5") 13 | 14 | var cor = [45.97338733591252,36.985496895804545] 15 | 16 | var geometry = ee.Geometry.Point(cor) 17 | 18 | var roi = table.filterBounds(geometry).map(function(feature){ 19 | return feature.simplify(1000) 20 | }); 21 | 22 | Map.centerObject(roi) 23 | Map.addLayer(roi) 24 | 25 | var time_start = '2020', time_end = '2024' 26 | 27 | var sen3 = ee.ImageCollection("COPERNICUS/S3/OLCI") 28 | .filterDate(time_start, time_end) 29 | .filterBounds(roi) 30 | .map(function(img){ 31 | var ndvi = img.normalizedDifference(['Oa17_radiance','Oa08_radiance']).rename('ndvi') 32 | return ndvi 33 | .copyProperties(img,['system:time_start','system:time_end']) 34 | }); 35 | 36 | Map.addLayer(sen3.median().clip(roi),[],'sen3_preview',false) 37 | 38 | Export.image.toDrive({ 39 | image: sen3.median().clip(roi), 40 | description: 'sen3_output', 41 | scale: 1000, 42 | region: roi, 43 | maxPixels: 1e13, 44 | crs: 'EPSG:4326' 45 | }) 46 | 47 | 48 | var months = ee.List.sequence(1, 12) 49 | var years = ee.List.sequence(ee.Number.parse(time_start), ee.Number.parse(time_end).subtract(1)); 50 | 51 | 52 | var monthly_ndvi = ee.ImageCollection(years.map(function(year){ 53 | return months.map(function(month){ 54 | var monthly_max = sen3 55 | .filter(ee.Filter.calendarRange(year, year,'year')) 56 | .filter(ee.Filter.calendarRange(month, month, 'month')).max() 57 | var time = ee.Date.fromYMD(year, month, 1); 58 | return monthly_max 59 | .set('system:time_start', time.millis()) 60 | }) 61 | }).flatten()) 62 | 63 | print( 64 | ui.Chart.image.series(monthly_ndvi, geometry, ee.Reducer.first(), 300, 'system:time_start') 65 | ) 66 | 67 | Map.addLayer(monthly_ndvi.toBands().clip(roi),[],'sen3_monthly',false) 68 | 69 | -------------------------------------------------------------------------------- /0138_xee_snow_season: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0054_snow_start_end.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-143: Snow Cover, Start Day and End Day, in Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | 14 | """ 15 | 16 | import ee 17 | import geemap 18 | !pip install xee 19 | import xee 20 | import xarray as xr 21 | 22 | ee.Authenticate() 23 | ee.Initialize( 24 | project = 'ee-amirhosseinahrari', 25 | opt_url = 'https://earthengine-highvolume.googleapis.com' 26 | ) 27 | 28 | map = geemap.Map(basemap = 'TERRAIN') 29 | map 30 | 31 | roi = map.draw_last_feature.geometry() 32 | 33 | roi 34 | 35 | collection = ( 36 | ee.ImageCollection("ECMWF/ERA5_LAND/DAILY_AGGR") 37 | .filterDate('2010','2020') 38 | .select('snow_cover') 39 | 40 | ) 41 | 42 | collection.limit(10) 43 | 44 | ds = xr.open_dataset( 45 | collection, 46 | engine = 'ee', 47 | crs = 'EPSG:4326', 48 | scale = 0.11, 49 | geometry = roi 50 | ) 51 | 52 | ds.snow_cover.attrs['units'] = 'kg m-2' 53 | 54 | ds 55 | 56 | !pip install xclim 57 | 58 | from xclim.indicators.land import snw_season_start, snw_season_end 59 | 60 | snow_start = snw_season_start( 61 | snw = ds.snow_cover, 62 | thresh = '4 kg m-2', 63 | window = 14, 64 | freq = 'YS-JAN' 65 | ) 66 | 67 | snow_start.plot( 68 | x = 'lon', 69 | y = 'lat', 70 | col = 'time', 71 | col_wrap = 5, 72 | cmap = 'Spectral', 73 | robust = True 74 | ) 75 | 76 | snow_end = snw_season_end( 77 | snw = ds.snow_cover, 78 | thresh = '4 kg m-2', 79 | window = 14, 80 | freq = 'YS-JAN' 81 | ) 82 | 83 | import matplotlib.pyplot as plt 84 | 85 | snow_end.plot( 86 | x = 'lon', 87 | y = 'lat', 88 | col = 'time', 89 | col_wrap = 5, 90 | cmap = 'Spectral', 91 | robust = True 92 | ) 93 | 94 | plt.savefig('snow_end.png', dpi = 360, bbox_inches = 'tight') 95 | -------------------------------------------------------------------------------- /0145_xee_embedding_kmeans: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0063_embedding_unsupervised_learning.ipynb 3 | 4 | utorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-150: Satellite Embedding Mapping using KMeans Clustering, in Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | 14 | """ 15 | 16 | import ee 17 | import geemap 18 | import xarray as xr 19 | !pip install xee 20 | import xee 21 | !pip install rioxarray 22 | import rioxarray 23 | 24 | ee.Authenticate() 25 | ee.Initialize( 26 | project = 'ee-amirhosseinahrari', 27 | opt_url = 'https://earthengine-highvolume.googleapis.com' 28 | ) 29 | 30 | map = geemap.Map(basemap = 'SATELLITE') 31 | map 32 | 33 | roi = map.draw_last_feature.geometry() 34 | 35 | roi 36 | 37 | image = ( 38 | ee.ImageCollection("GOOGLE/SATELLITE_EMBEDDING/V1/ANNUAL") 39 | .filterDate('2021','2022') 40 | .filterBounds(roi) 41 | .mosaic() 42 | ) 43 | 44 | image 45 | 46 | ds = xr.open_dataset( 47 | image, 48 | engine = 'ee', 49 | crs = 'EPSG:4326', 50 | scale = 0.001, 51 | geometry = roi 52 | ) 53 | 54 | ds.A01.plot( 55 | x = 'lon', 56 | y = 'lat', 57 | robust = True 58 | ) 59 | 60 | df = ds.to_dataframe() 61 | 62 | df 63 | 64 | from sklearn.cluster import KMeans 65 | 66 | model = KMeans(n_clusters = 7, random_state = 42) 67 | model.fit(df) 68 | 69 | df['cluster'] = model.predict(df) 70 | 71 | dx = df.to_xarray().sortby(['lat','lon']) 72 | 73 | dx.cluster.plot( 74 | x = 'lon', 75 | y = 'lat', 76 | vmin = 0, 77 | vmax = 6 78 | ) 79 | 80 | output = dx.cluster.isel(time = 0).drop_vars('time') 81 | output = output.rio.write_crs('EPSG:4326', inplace = True) 82 | output = output.rio.set_spatial_dims(x_dim = 'lon', y_dim = 'lat', inplace = True) 83 | output = output.rio.write_coordinate_system(inplace = True) 84 | output = output.transpose('lat', 'lon') 85 | output.rio.to_raster('embedding_cluster.tif') 86 | -------------------------------------------------------------------------------- /0135_xee_esi: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0050_Evaporative_Stress_Index.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-140: Evaporative Stress Index in Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | 14 | 15 | """ 16 | 17 | import ee 18 | import geemap 19 | import xarray as xr 20 | !pip install xee 21 | import xee 22 | import numpy as np 23 | import pandas as pd 24 | import matplotlib.pyplot as plt 25 | 26 | ee.Authenticate() 27 | ee.Initialize( 28 | project = 'ee-amirhosseinahrari', 29 | opt_url='https://earthengine-highvolume.googleapis.com' 30 | ) 31 | 32 | map = geemap.Map(basemap = 'SATELLITE') 33 | map 34 | 35 | roi = map.draw_last_feature.geometry() 36 | 37 | roi 38 | 39 | iran = ( 40 | ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level0") 41 | .filterBounds(roi) 42 | .geometry() 43 | ) 44 | 45 | map.addLayer(iran, {}, 'Iran') 46 | 47 | collection = ( 48 | ee.ImageCollection('projects/climate-engine/esi/12wk') 49 | .filterDate('2001','2025') 50 | .map(lambda img: img.clip(iran).copyProperties(img, img.propertyNames())) 51 | ) 52 | 53 | collection 54 | 55 | ds = xr.open_dataset( 56 | collection, 57 | engine = 'ee', 58 | crs = 'EPSG:4326', 59 | geometry = iran, 60 | scale = 0.1 61 | ) 62 | 63 | ds 64 | 65 | ds.isel(time = 100).ESI.plot( 66 | x = 'lon', 67 | y = 'lat', 68 | robust = True 69 | ) 70 | 71 | lat = 37.06016443230056 72 | lon = 45.95842739971374 73 | point = ds.sel( 74 | lat = lat, 75 | lon = lon, 76 | method = 'nearest' 77 | ) 78 | 79 | point.ESI.plot() 80 | 81 | df = point.to_dataframe().ESI 82 | 83 | df 84 | 85 | pos = df[df >= 0] 86 | neg = df[df < 0] 87 | 88 | fig, ax = plt.subplots(figsize = (9,3)) 89 | 90 | ax.plot(df.index, df, color = 'black', lw = 0.5) 91 | ax.bar(pos.index, pos, color = 'tab:blue', width = 20) 92 | ax.bar(neg.index, neg, color = 'red', width = 20) 93 | -------------------------------------------------------------------------------- /0121_xee_lake_clustering: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0030_lake_clustering.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-126: Lake Mapping using Clustering Technique, in Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | 14 | """ 15 | 16 | import ee 17 | import geemap 18 | import xarray as xr 19 | 20 | !pip install xee 21 | import xee 22 | 23 | ee.Authenticate() 24 | ee.Initialize(project = 'ee-amirhosseinahrari', opt_url = 'https://earthengine-highvolume.googleapis.com') 25 | 26 | map = geemap.Map(basemap = 'SATELLITE') 27 | map 28 | 29 | roi = map.draw_last_feature.geometry() 30 | 31 | roi 32 | 33 | landsat = ee.ImageCollection("LANDSAT/LC08/C02/T1_L2").filterBounds(roi).filterDate('2021','2025') 34 | 35 | def ndwi(img): 36 | qa = img.select('QA_PIXEL') 37 | cloud = qa.bitwiseAnd(1 << 3).neq(0) 38 | cirrus = qa.bitwiseAnd(1 << 2).neq(0) 39 | shadow = qa.bitwiseAnd(1 << 4).neq(0) 40 | mask = cloud.Or(cirrus).Or(shadow) 41 | bands = img.select('SR.*').multiply(2.75e-05).add(-0.2) 42 | index = bands.normalizedDifference(['SR_B3','SR_B5']).rename('ndwi') 43 | return index.updateMask(mask.Not()).copyProperties(img, img.propertyNames()) 44 | 45 | landsat_ndwi = landsat.map(ndwi) 46 | 47 | ds = xr.open_dataset(landsat_ndwi, engine = 'ee', crs = 'EPSG:4326', scale = 0.003, geometry = roi) 48 | 49 | ds 50 | 51 | ds_mean = ds.mean('time') 52 | 53 | ds_mean.ndwi.plot(x = 'lon', y = 'lat', robust = True) 54 | 55 | from sklearn.cluster import KMeans 56 | 57 | model = KMeans(n_clusters = 2, random_state = 42) 58 | 59 | df = ds_mean.to_dataframe() 60 | 61 | df['clustering'] = model.fit_predict(df[['ndwi']]) 62 | 63 | xarr = df.to_xarray().sortby('lon').sortby('lat') 64 | xarr 65 | 66 | xarr.clustering.plot(x = 'lon', y = 'lat', cmap = 'Blues') 67 | 68 | lake_pixels = (xarr.clustering == 0).sum(dim = ['lon','lat']) 69 | lake_area = (lake_pixels * 300 * 300) / 1e6 70 | lake_area 71 | -------------------------------------------------------------------------------- /0159_xee_sen2_turbidity: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0082_sen2_turbidity.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-164: Sentinel-2 Water Turbidity Mapping and Monitoring using Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | 14 | """ 15 | 16 | import ee 17 | import geemap 18 | import xarray as xr 19 | !pip install xee 20 | import xee 21 | 22 | ee.Authenticate() 23 | ee.Initialize( 24 | project = 'ee-amirhosseinahrari', 25 | opt_url = 'https://earthengine-highvolume.googleapis.com' 26 | ) 27 | 28 | map = geemap.Map(basemap = 'SATELLITE') 29 | map 30 | 31 | roi = map.draw_last_feature.geometry() 32 | roi 33 | 34 | def turbidity(img): 35 | cloud = img.select('probability') 36 | cloud_free = cloud.lt(20) 37 | sr = img.select('B.*').multiply(0.0001) 38 | ndwi = sr.normalizedDifference(['B3','B8']).rename('ndwi') 39 | water_body = ndwi.gt(0.1) 40 | ndti = sr.normalizedDifference(['B4','B3']).rename('ndti') 41 | return ndti.updateMask(cloud_free).updateMask(water_body).copyProperties(img, ['system:time_start']) 42 | 43 | 44 | sen2 = ( 45 | ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED") 46 | .linkCollection(ee.ImageCollection("COPERNICUS/S2_CLOUD_PROBABILITY"), 'probability') 47 | .filterBounds(roi) 48 | .filterDate('2024','2025') 49 | .map(turbidity) 50 | 51 | ) 52 | 53 | sen2 54 | 55 | ds = xr.open_dataset( 56 | sen2, 57 | engine = 'ee', 58 | crs = 'EPSG:4326', 59 | scale = 0.001, 60 | geometry =roi 61 | ) 62 | 63 | ds = ds.sortby('time') * 1 64 | 65 | ds_monthly = ds.resample(time = 'M').max('time') 66 | ds_monthly 67 | 68 | ds_monthly.ndti.plot( 69 | x = 'lon', 70 | y = 'lat', 71 | col = 'time', 72 | robust = True, 73 | col_wrap = 6, 74 | cmap = 'coolwarm', 75 | vmax = 0.2 76 | ) 77 | 78 | ds_mean = ds_monthly.mean(dim = ['lat','lon']).to_dataframe() 79 | ds_mean.to_csv('turbidity_map.csv') 80 | -------------------------------------------------------------------------------- /00085_heavy_pr_valencia: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-90: Heavy Precipitation Before Valencia Flood 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 12 | */ 13 | 14 | var cor = [-0.5798481276712097,39.351468153296324] 15 | 16 | var geometry = ee.Geometry.Point(cor) 17 | 18 | 19 | var roi = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level0") 20 | .filterBounds(geometry) 21 | 22 | Map.centerObject(roi) 23 | Map.addLayer(roi) 24 | 25 | var time_start = ee.Date('2024') 26 | var time_end = ee.Date('2025') 27 | 28 | var pr = ee.ImageCollection("NASA/GPM_L3/IMERG_V07") 29 | .select('precipitation') 30 | .filterDate(time_start, time_end) 31 | 32 | var time_dif = time_end.difference(time_start, 'days') 33 | 34 | var list = ee.List.sequence(0, time_dif.subtract(1), 1).map(function(number){ 35 | return time_start.advance(number, 'days') 36 | }) 37 | 38 | var pr_daily = ee.ImageCollection(list.map(function(date){ 39 | var start_date = ee.Date(date) 40 | var end_date = start_date.advance(1, 'days') 41 | var daily = pr.filterDate(start_date, end_date).sum() 42 | return daily 43 | .set('system:time_start', start_date.millis()) 44 | .set('system:time_end', end_date.millis()) 45 | .set('system:index', start_date.format('YYYY-MM-dd')) 46 | })) 47 | 48 | Map.addLayer(pr_daily.filter(ee.Filter.calendarRange(10, 10, 'month')).toBands().clip(roi), [], 'pr_daily', false) 49 | 50 | 51 | print( 52 | ui.Chart.image.series(pr_daily, geometry, ee.Reducer.first(), 10000, 'system:time_start') 53 | 54 | ) 55 | 56 | Export.image.toDrive({ 57 | image: pr_daily.filter(ee.Filter.calendarRange(10, 10, 'month')).toBands().clip(roi).float(), 58 | description: 'heavy_pr', 59 | scale: 10000, 60 | region: roi, 61 | crs: 'EPSG:4326', 62 | folder: 'test' 63 | }) 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /0131_xee_sg_filter: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0046_ndvi_daily.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-136: Savitsky Golay Filter, in Python API 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | 14 | """ 15 | 16 | import ee 17 | import geemap 18 | import xarray as xr 19 | !pip install xee 20 | import xee 21 | import numpy as np 22 | !pip install xrscipy 23 | import xrscipy.signal as xrs 24 | 25 | ee.Authenticate() 26 | ee.Initialize( 27 | project = 'ee-amirhosseinahrari', 28 | opt_url = 'https://earthengine-highvolume.googleapis.com' 29 | ) 30 | 31 | map = geemap.Map(basemap = 'SATELLITE') 32 | map 33 | 34 | roi = map.draw_last_feature.geometry() 35 | 36 | roi 37 | 38 | ndvi_collection = ( 39 | ee.ImageCollection("MODIS/MOD09GA_006_NDVI") 40 | .filterDate('2020','2021') 41 | ) 42 | 43 | ndvi_collection 44 | 45 | ndvi_ds = xr.open_dataset( 46 | ndvi_collection, 47 | engine = 'ee', 48 | crs = 'EPSG:4326', 49 | geometry = roi, 50 | scale = 0.005 51 | ) 52 | 53 | ndvi_ds 54 | 55 | ndvi_ds.sel(time = ndvi_ds.time.dt.month == 5).NDVI.plot( 56 | x = 'lon', 57 | y = 'lat', 58 | col = 'time', 59 | col_wrap = 7, 60 | robust = True, 61 | cmap = 'RdYlGn' 62 | ) 63 | 64 | ndvi_ds.mean(dim = ['lon', 'lat']).NDVI.plot() 65 | 66 | ndvi_ds2 = ndvi_ds.copy() 67 | 68 | ndvi_time = ndvi_ds2.time.values.copy() 69 | 70 | ndvi_ds2 71 | 72 | ndvi_ds2.coords['time'] = np.arange(len(ndvi_ds2.time)) 73 | 74 | ndvi_ds2 75 | 76 | ndvi_smooth = xrs.savgol_filter( 77 | ndvi_ds2.NDVI, 78 | window_length = 30, 79 | polyorder = 2, 80 | dim = 'time' 81 | ) 82 | 83 | ndvi_smooth.coords['time'] = ndvi_time 84 | 85 | ndvi_smooth.sel(time = ndvi_smooth.time.dt.month == 5).plot( 86 | x = 'lon', 87 | y = 'lat', 88 | col = 'time', 89 | col_wrap = 7, 90 | robust = True, 91 | cmap = 'RdYlGn' 92 | ) 93 | 94 | ndvi_smooth.mean(dim = ['lon', 'lat']).plot() 95 | -------------------------------------------------------------------------------- /0136_xee_interp: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0051_interpolation.ipynb 3 | 4 | 5 | Tutorial Code by Amirhossein Ahrari 6 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 7 | Tutorial Video: Google Earth Engine Tutorial-141: Temporal Interpolation for EO Products, in Python API (Xee) 8 | 9 | This code is part of a tutorial series on Earth Engine programming techniques 10 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 11 | this code for academic and non-academic purposes. Don't forget to subscribe to 12 | the Amirhossein Ahrari channel and follow the videos to support the instructor 13 | 14 | 15 | 16 | """ 17 | 18 | import ee 19 | import geemap 20 | !pip install xee 21 | import xee 22 | import xarray as xr 23 | import pandas as pd 24 | 25 | ee.Authenticate() 26 | ee.Initialize( 27 | project = 'ee-amirhosseinahrari', 28 | opt_url = 'https://earthengine-highvolume.googleapis.com' 29 | ) 30 | 31 | map = geemap.Map(basemap = 'SATELLITE') 32 | map 33 | 34 | roi = map.draw_last_feature.geometry() 35 | 36 | roi 37 | 38 | collection = ( 39 | ee.ImageCollection("JRC/GHSL/P2023A/GHS_BUILT_S") 40 | .filterBounds(roi) 41 | .select('built_surface') 42 | ) 43 | 44 | collection 45 | 46 | ds = xr.open_dataset( 47 | collection, 48 | engine = 'ee', 49 | crs = 'EPSG:4326', 50 | geometry = roi, 51 | scale = 0.001 52 | ) 53 | 54 | ds 55 | 56 | ds.sel(time = slice('2010','2020')).built_surface.plot( 57 | x = 'lon', 58 | y = 'lat', 59 | col = 'time', 60 | robust = True 61 | ) 62 | 63 | time_start = ds.time.values[0] 64 | time_end = ds.time.values[-1] 65 | time_list = pd.date_range(time_start, time_end, freq = 'YE') 66 | 67 | time_list 68 | 69 | ds_annual = ds.interp(time = time_list) 70 | 71 | ds_annual 72 | 73 | ds_annual.sel(time = slice('2010', '2020')).built_surface.plot( 74 | x = 'lon', 75 | y = 'lat', 76 | col = 'time', 77 | col_wrap = 5, 78 | robust =True 79 | ) 80 | 81 | ds_area = ds.sum(dim = ['lat','lon']) 82 | annual_area = ds_annual.sum(dim = ['lat', 'lon']) 83 | 84 | import matplotlib.pyplot as plt 85 | 86 | fig, ax = plt.subplots(figsize = (7,3)) 87 | 88 | ax.plot(ds_area.time, ds_area.built_surface, marker = 'o') 89 | ax.plot(annual_area.time, annual_area.built_surface, marker = 'o', color = 'tab:red', alpha = 0.4) 90 | -------------------------------------------------------------------------------- /00031_canopy_height_1m: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | 7 | This code is part of a tutorial series on Earth Engine programming techniques 8 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 9 | this code for academic and non-academic purposes. Don't forget to subscribe to 10 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 11 | */ 12 | 13 | var basin = ee.FeatureCollection("WWF/HydroSHEDS/v1/Basins/hybas_6") 14 | 15 | var cor = [28.577460872036138,64.5593101743747] 16 | 17 | var point = ee.Geometry.Point(cor) 18 | 19 | 20 | var roi = basin.filterBounds(point) 21 | 22 | Map.centerObject(roi) 23 | Map.addLayer(roi) 24 | 25 | var canopy = ee.ImageCollection("projects/meta-forest-monitoring-okw37/assets/CanopyHeight").mosaic() 26 | 27 | 28 | Map.addLayer(canopy.clip(roi),[],'canopy_height',false) 29 | 30 | 31 | 32 | var forest_thr = canopy.gt(0); 33 | var forest = canopy.updateMask(forest_thr); 34 | 35 | Map.addLayer(forest.clip(roi),[],'forest',false) 36 | 37 | print( 38 | ui.Chart.image.histogram(forest,roi,100) 39 | ) 40 | 41 | var canopy_mean = forest.reduceRegion({ 42 | reducer: ee.Reducer.mean(), geometry: roi, scale: 100 43 | }).values().get(0); 44 | 45 | print('canopy_mean', canopy_mean) 46 | 47 | var canopy_max = forest.reduceRegion({ 48 | reducer: ee.Reducer.max(), geometry: roi, scale: 100 49 | }).values().get(0); 50 | 51 | print('canopy_max', canopy_max) 52 | 53 | var canopy_per99 = forest.reduceRegion({ 54 | reducer: ee.Reducer.percentile([99]), geometry: roi, scale: 100 55 | }).values().get(0); 56 | 57 | print('canopy_per99', canopy_per99) 58 | 59 | 60 | var cons = ee.Image.constant(0); 61 | 62 | var class1 = cons.where(forest.lt(5), 1); 63 | var class2 = class1.where(forest.gte(5).and(forest.lt(10)),2) 64 | var class3 = class2.where(forest.gte(10), 3) 65 | 66 | Map.addLayer(class3.clip(roi),{min: 0, max : 3, 67 | palette:['black','red','orange','green']},'class3',false) 68 | 69 | 70 | Export.image.toDrive({ 71 | image: class3.clip(roi), 72 | description: 'canopy_hieght_classified', 73 | scale: 30, 74 | region: roi, 75 | maxPixels: 1e13, 76 | crs: class3.getInfo().crs, 77 | folder: 'test' 78 | }) 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /00089_snowmelt_temp: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-94: Snow Melt Monitoring using Temperature Data 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 12 | */ 13 | 14 | 15 | 16 | var cor = [26.665149368751752,65.00395626348661] 17 | 18 | var geometry = ee.Geometry.Point(cor) 19 | 20 | var roi = ee.FeatureCollection("WWF/HydroSHEDS/v1/Basins/hybas_5") 21 | .filterBounds(geometry).map(function(feature){ 22 | return feature.simplify(1000) 23 | }) 24 | 25 | Map.centerObject(roi) 26 | Map.addLayer(roi) 27 | 28 | 29 | var temp = ee.ImageCollection("ECMWF/ERA5_LAND/DAILY_AGGR") 30 | .select('temperature_2m') 31 | .filterDate('2015', '2018') 32 | .filter(ee.Filter.calendarRange(3,6,'month')) 33 | .map(function(img){ 34 | var date = img.date() 35 | var acqu = date.format('YYYY-MM-dd') 36 | var doy = date.getRelative('day', 'year').add(1) 37 | return img.subtract(273.15) 38 | .copyProperties(img, img.propertyNames()) 39 | .set('date', acqu) 40 | .set('doy', doy) 41 | }) 42 | 43 | print(temp.filter(ee.Filter.calendarRange(2016, 2016, 'year')) 44 | .filter(ee.Filter.eq('doy',118))) 45 | 46 | print( 47 | ui.Chart.image.doySeriesByYear(temp, 'temperature_2m', roi, 48 | ee.Reducer.mean(), 10000, ee.Reducer.mean(), 1, 365) 49 | ) 50 | 51 | 52 | var snowmelt = ee.ImageCollection("ECMWF/ERA5_LAND/DAILY_AGGR") 53 | .select('snowmelt_sum') 54 | .filterDate('2015','2018') 55 | .filter(ee.Filter.calendarRange(3, 6, 'month')) 56 | .map(function(img){ 57 | var date = img.date() 58 | var acqu = date.format('YYYY-MM-dd') 59 | var doy = date.getRelative('day', 'year').add(1) 60 | return img 61 | .copyProperties(img, img.propertyNames()) 62 | .set('date', acqu) 63 | .set('doy', doy) 64 | }) 65 | 66 | 67 | print( 68 | ui.Chart.image.doySeriesByYear(snowmelt, 'snowmelt_sum', roi, ee.Reducer.mean(), 69 | 10000, ee.Reducer.mean(), 1, 365) 70 | ) 71 | 72 | 73 | print(snowmelt) 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /00032_oil_spill_sentinel1: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | 13 | var cor = [ 14 | [32.33741352024498,31.356500050396157], 15 | [32.59559223118248,31.356500050396157], 16 | [32.59559223118248,31.58490130730319], 17 | [32.33741352024498,31.58490130730319], 18 | [32.33741352024498,31.356500050396157] 19 | ] 20 | 21 | var roi = ee.Geometry.Polygon(cor) 22 | 23 | 24 | 25 | Map.centerObject(roi); 26 | 27 | var sen1 = ee.ImageCollection("COPERNICUS/S1_GRD") 28 | .select('VV') 29 | .filterDate('2014','2015') 30 | .filterBounds(roi) 31 | .filter(ee.Filter.calendarRange(10, 10, 'month')) 32 | .filter(ee.Filter.calendarRange(4, 4, 'day_of_month')) 33 | .filter(ee.Filter.listContains('transmitterReceiverPolarisation','VV')) 34 | .filter(ee.Filter.eq('instrumentMode','IW')).mosaic() 35 | 36 | //print(sen1.aggregate_array('orbitProperties_pass')) 37 | 38 | Map.addLayer(sen1.clip(roi),[],'sen1',false) 39 | 40 | print( 41 | ui.Chart.image.histogram(sen1,roi,10) 42 | ) 43 | 44 | var despeckel = sen1.focalMean(100, 'square', 'meters'); 45 | 46 | Map.addLayer(despeckel.clip(roi),[],'sen_despeckel',false); 47 | 48 | print( 49 | ui.Chart.image.histogram(despeckel,roi,30) 50 | ) 51 | 52 | var thr = despeckel.lt(-22); 53 | 54 | Map.addLayer(thr.clip(roi),[],'oil_spill',false); 55 | 56 | 57 | var mask = thr.updateMask(thr); 58 | 59 | Map.addLayer(mask.clip(roi),[],'mask',false) 60 | 61 | var area = mask.multiply(ee.Image.pixelArea().divide(1e6)); 62 | 63 | var oil_spill_area = ee.Number(area.reduceRegion({ 64 | reducer: ee.Reducer.sum(), geometry: roi, scale: 100 65 | }).values().get(0)); 66 | 67 | print(oil_spill_area) 68 | 69 | var oil_spill_vector = mask.reduceToVectors({ 70 | geometry: roi, scale: 100 71 | }); 72 | 73 | Map.addLayer(oil_spill_vector) 74 | 75 | Export.table.toDrive({ 76 | collection: oil_spill_vector, description: 'oil_spill', fileFormat: 'SHP', folder: 'oil_spill2' 77 | }) 78 | 79 | -------------------------------------------------------------------------------- /00018_et_cwsi_mapping: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | var cor = [46.00719637247596,37.199483887704204] 13 | 14 | var loc = ee.Geometry.Point(cor) 15 | 16 | 17 | var roi = ee.FeatureCollection("WWF/HydroSHEDS/v1/Basins/hybas_5") 18 | .filterBounds(loc); 19 | 20 | Map.centerObject(roi) 21 | Map.addLayer(roi) 22 | 23 | // call modis et product 24 | 25 | var time_start = '2001', time_end = '2024' 26 | 27 | var modis = ee.ImageCollection("MODIS/061/MOD16A2GF") 28 | .select('ET','PET') 29 | .filterDate(time_start, time_end); 30 | 31 | // et mapping 32 | 33 | var et_mean = modis.select('ET').mean().multiply(0.1); 34 | 35 | Map.addLayer(et_mean.clip(roi),[],'et_mean',false) 36 | 37 | var et_mean_summer = modis.select('ET') 38 | .filter(ee.Filter.calendarRange(6, 8, 'month')).mean().multiply(0.1); 39 | 40 | Map.addLayer(et_mean_summer.clip(roi),[],'et_summer',false) 41 | 42 | // get export 43 | 44 | Export.image.toDrive({ 45 | image: et_mean.clip(roi), 46 | description: 'et_mean', 47 | region: roi, 48 | scale: 500, 49 | crs: et_mean.getInfo().crs, 50 | maxPixels: 1e13, 51 | folder: 'evapotranspiration' 52 | 53 | }) 54 | 55 | // crop water stress index eq = 1 - (et/pet) 56 | 57 | 58 | var cwsi = modis.map(function(img){ 59 | var eq = img.expression('1 - (et/pet)',{'et': img.select('ET').multiply(0.1), 'pet': img.select('PET').multiply(0.1)}); 60 | return eq.rename('cwsi') 61 | .copyProperties(img, ['system:time_start', 'system:time_end']) 62 | }); 63 | 64 | 65 | var cwsi_mean = cwsi.mean(); 66 | 67 | Map.addLayer(cwsi_mean.clip(roi),[],'cwsi_mean',false) 68 | 69 | 70 | // masking process 71 | 72 | var lc = ee.ImageCollection("MODIS/061/MCD12Q1") 73 | .select('LC_Type1').mode(); 74 | 75 | var crop = lc.eq(12); 76 | 77 | Map.addLayer(crop.clip(roi),[],'crop',false) 78 | 79 | var cwsi_crop = cwsi_mean.updateMask(crop); 80 | 81 | Map.addLayer(cwsi_crop.clip(roi),[],'cwsi_mean_crop',false) 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /0112_xee_wildefire: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """Untitled30.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-117: WildeFire Monitoring (Los Angles), using Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | """ 14 | 15 | import ee 16 | import geemap as gee 17 | import xarray as xr 18 | 19 | !pip install xee 20 | import xee 21 | 22 | ee.Authenticate() 23 | ee.Initialize(project = 'ee-amirhosseinahrari', opt_url='https://earthengine-highvolume.googleapis.com') 24 | 25 | map = gee.Map(basemap = 'TERRAIN') 26 | map 27 | 28 | roi = map.draw_last_feature.geometry() 29 | 30 | time_start = ee.Date('2025-01-01') 31 | time_end = ee.Date('2025-02-01') 32 | 33 | sr = ee.ImageCollection("NASA/VIIRS/002/VNP09GA").filterDate(time_start, time_end).select('I1','I2') 34 | 35 | def ndvi(img): 36 | index = img.normalizedDifference(['I2','I1']).rename('ndvi') 37 | return index.copyProperties(img, img.propertyNames()) 38 | 39 | viirs_ndvi = sr.map(ndvi) 40 | 41 | ds_ndvi = xr.open_dataset(viirs_ndvi, engine = 'ee', crs = 'EPSG:4326', scale = 0.001, geometry = roi) 42 | 43 | ds_ndvi 44 | 45 | import matplotlib.pyplot as plt 46 | 47 | ds_ndvi.ndvi.plot(x = 'lon', y ='lat', col = 'time', col_wrap = 5, robust =True, cmap = 'jet') 48 | plt.savefig('ndvi_fire.png', dpi = 360, bbox_inches = 'tight') 49 | 50 | temp = ee.ImageCollection("NASA/VIIRS/002/VNP14A1").select('MaxFRP').filterDate(time_start, time_end) 51 | 52 | ds_temp = xr.open_dataset(temp, engine = 'ee', crs = 'EPSG:4326', scale = 0.005, geometry = roi) 53 | 54 | ds_temp 55 | 56 | ds_temp.MaxFRP.plot(x = 'lon', y = 'lat', cmap = 'Reds', col = 'time', col_wrap = 5, robust = True) 57 | 58 | lst = ee.ImageCollection("NASA/VIIRS/002/VNP21A1D").select('LST_1KM').filterDate(time_start, time_end) 59 | 60 | ds_lst = xr.open_dataset(lst, engine = 'ee', crs = 'EPSG:4326', scale = 0.005, geometry = roi) 61 | 62 | ds_lst 63 | 64 | ds_lst.LST_1KM.plot(x = 'lon', y = 'lat', cmap = 'hot_r', col = 'time', col_wrap = 5, robust = True) 65 | -------------------------------------------------------------------------------- /0155_evaporation_viirs: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0078_water_evaporation.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-160: Water Evaporation Mapping and Monitoring using VIIRS Mission 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | """ 14 | 15 | import ee 16 | import geemap 17 | import xarray as xr 18 | !pip install xee 19 | import xee 20 | 21 | ee.Authenticate() 22 | ee.Initialize( 23 | project = 'ee-amirhosseinahrari', 24 | opt_url = 'https://earthengine-highvolume.googleapis.com' 25 | ) 26 | 27 | map = geemap.Map(basemap = 'SATELLITE') 28 | map 29 | 30 | roi = map.draw_last_feature.geometry() 31 | roi 32 | 33 | lc = ( 34 | ee.ImageCollection("MODIS/061/MCD12Q1") 35 | .select('LC_Type1') 36 | .mode() 37 | .eq(17) 38 | ) 39 | 40 | map.addLayer(lc.clip(roi), {}, 'lc') 41 | 42 | viirs = ( 43 | ee.ImageCollection('projects/usgs-ssebop/viirs_et_v6_monthly') 44 | .filterDate('2015','2025') 45 | .map(lambda x: x.updateMask(lc).copyProperties(x, x.propertyNames())) 46 | ) 47 | 48 | ds = xr.open_dataset( 49 | viirs, 50 | engine = 'ee', 51 | crs = 'EPSG:4326', 52 | geometry = roi, 53 | scale = 0.01 54 | ) 55 | 56 | ds = ds.sortby('time') * 1 57 | 58 | ds.isel(time = 10).et.plot( 59 | x = 'lon', 60 | y = 'lat', 61 | robust = True, 62 | vmin = 35, 63 | ) 64 | 65 | import numpy as np 66 | 67 | ds_annual = ds.resample(time = 'Y').sum('time') 68 | ds_annual = xr.where(ds_annual == 0, np.nan, ds_annual) 69 | 70 | import matplotlib.pyplot as plt 71 | 72 | ds_annual.et.plot.contourf( 73 | x = 'lon', 74 | y = 'lat', 75 | col = 'time', 76 | col_wrap = 5, 77 | robust = True, 78 | cmap = 'rainbow', 79 | vmin = 1000, 80 | levels = 20 81 | ) 82 | 83 | plt.savefig('annual_evaporation.png', dpi = 360, bbox_inches = 'tight') 84 | 85 | ds_annual.mean(dim = ['lat', 'lon']).to_dataframe().to_csv('lake_evaporation.csv') 86 | 87 | ds_annual.mean(dim = ['lat', 'lon']).to_dataframe().plot() 88 | -------------------------------------------------------------------------------- /0134_xee_dem_clustering: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0049_elevation_mapping.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-139: Elevation (DEM) Mapping in Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | 14 | """ 15 | 16 | import ee 17 | import geemap 18 | import xarray as xr 19 | !pip install xee 20 | import xee 21 | import numpy as np 22 | import pandas as pd 23 | 24 | ee.Authenticate() 25 | ee.Initialize( 26 | project = 'ee-amirhosseinahrari', 27 | opt_url = 'https://earthengine-highvolume.googleapis.com' 28 | ) 29 | 30 | map = geemap.Map(basemap = 'SATELLITE') 31 | map 32 | 33 | roi = map.draw_last_feature.geometry() 34 | 35 | roi 36 | 37 | dem = ( 38 | ee.Image("NASA/NASADEM_HGT/001") 39 | .select([0],['elevation']) 40 | ) 41 | 42 | dem 43 | 44 | xdem = xr.open_dataset( 45 | dem, 46 | engine = 'ee', 47 | crs = 'EPSG:4326', 48 | geometry = roi, 49 | scale = 0.001 50 | ) 51 | 52 | xdem 53 | 54 | xdem.elevation.plot( 55 | x = 'lon', 56 | y = 'lat', 57 | robust = True 58 | ) 59 | 60 | df = xdem.to_dataframe() 61 | 62 | df 63 | 64 | from sklearn.cluster import KMeans 65 | 66 | model = KMeans(n_clusters = 5) 67 | 68 | model.fit(df) 69 | 70 | df['classes'] = model.predict(df) 71 | 72 | df 73 | 74 | xarr = df.to_xarray().sortby(['lon','lat']) 75 | 76 | xarr 77 | 78 | xarr.classes.plot( 79 | x = 'lon', 80 | y = 'lat' 81 | ) 82 | 83 | class_num = np.unique(xarr.classes.values) 84 | class_num 85 | 86 | xarr.elevation.where(xarr.classes == 1).mean().values 87 | 88 | for i in class_num: 89 | class_mean = xarr.elevation.where(xarr.classes == i).mean().values.round(2) 90 | print(f'class {i} average: {class_mean}') 91 | class_max = xarr.elevation.where(xarr.classes == i).max().values.round(2) 92 | print(f'class {i} maximum: {class_max}') 93 | class_min = xarr.elevation.where(xarr.classes == i).min().values.round(2) 94 | print(f'class {i} minimum: {class_min}') 95 | print('-----------------------------------') 96 | -------------------------------------------------------------------------------- /0156_xee_sen2_chl_water: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0079_sen2_chl.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-161: Sentinel-2 Water Chlorophyll_a Index using Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | """ 14 | 15 | import ee 16 | import geemap 17 | import xarray as xr 18 | !pip install xee 19 | import xee 20 | 21 | ee.Authenticate() 22 | ee.Initialize( 23 | project = 'ee-amirhosseinahrari', 24 | opt_url = 'https://earthengine-highvolume.googleapis.com' 25 | ) 26 | 27 | map = geemap.Map(basemap= 'TERRAIN') 28 | map 29 | 30 | roi = map.draw_last_feature.geometry() 31 | 32 | roi 33 | 34 | def sen2q(img): 35 | cloud = img.select('probability') 36 | clear_pixels = cloud.lt(20) 37 | bands = img.select('B.*').multiply(0.0001) 38 | ndwi = bands.normalizedDifference(['B3','B8']).rename('ndwi') 39 | water_body = ndwi.gt(0.1) 40 | chl = bands.expression('4.26 * ((b3 / b1) ** 3.94)', { 41 | 'b1': bands.select('B1'), 42 | 'b3': bands.select('B3') 43 | }).rename('chl') 44 | return chl.updateMask(clear_pixels).updateMask(water_body).copyProperties(img, ['system:time_start']) 45 | 46 | 47 | sen2 = ( 48 | ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED") 49 | .linkCollection(ee.ImageCollection("COPERNICUS/S2_CLOUD_PROBABILITY"),'probability') 50 | .filterDate('2024', '2025') 51 | .filterBounds(roi) 52 | .map(sen2q) 53 | ) 54 | 55 | sen2 56 | 57 | ds = xr.open_dataset( 58 | sen2, 59 | engine = 'ee', 60 | crs = 'EPSG:4326', 61 | scale = 0.001, 62 | geometry = roi 63 | ) 64 | 65 | ds = ds.sortby('time') * 1 66 | 67 | ds_monthly = ds.resample(time = 'M').median('time') 68 | 69 | import matplotlib.pyplot as plt 70 | 71 | ds_monthly.chl.plot( 72 | x = 'lon', 73 | y = 'lat', 74 | col = 'time', 75 | col_wrap = 6, 76 | robust = True, 77 | vmin = 2, 78 | vmax = 30, 79 | cmap = 'rainbow', 80 | levels = 20 81 | ) 82 | 83 | plt.savefig('sen2_chl.png', dpi = 360, bbox_inches = 'tight') 84 | 85 | -------------------------------------------------------------------------------- /00075_charts: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | 13 | 14 | var cor1 = [-114.11365750553733,42.559084813300494] 15 | 16 | var geometry = ee.Geometry.Point(cor1) 17 | 18 | 19 | 20 | var et = ee.ImageCollection("MODIS/061/MOD16A2GF") 21 | .filterDate('2023', '2024') 22 | .map(function(img){ 23 | var bands = img.select('ET').multiply(0.1) 24 | return bands.rename('MODIS_ET') 25 | .copyProperties(img, img.propertyNames()) 26 | }) 27 | 28 | 29 | print( 30 | ui.Chart.image.series(et, geometry, ee.Reducer.first(), 500, 'system:time_start') 31 | .setChartType('AreaChart') 32 | .setOptions({ 33 | title: 'Evapotranspiration Chart', 34 | vAxis: {title: 'ET (mm)'}, hAxis: {title: 'Date'}, 35 | series: {0:{color: 'red', lineWidth: 4, pointSize: 5}} 36 | 37 | }) 38 | ) 39 | 40 | 41 | var cor2 = [ 42 | [-114.26883939030296,42.52569509607107], 43 | [-114.26094296696311,42.52569509607107], 44 | [-114.26094296696311,42.53100829096698], 45 | [-114.26883939030296,42.53100829096698], 46 | [-114.26883939030296,42.52569509607107] 47 | ] 48 | 49 | var pol1 = ee.Geometry.Polygon(cor2) 50 | 51 | var cor3 = [ 52 | [-114.22420743229515,42.58360981365639], 53 | [-114.2159676862014,42.58360981365639], 54 | [-114.2159676862014,42.58942360551128], 55 | [-114.22420743229515,42.58942360551128], 56 | [-114.22420743229515,42.58360981365639] 57 | ] 58 | 59 | var pol2 = ee.Geometry.Polygon(cor3) 60 | 61 | var geometry2 = ee.FeatureCollection([ee.Feature(pol1), ee.Feature(pol2)]) 62 | 63 | 64 | 65 | 66 | print( 67 | ui.Chart.image.seriesByRegion(et, geometry2, ee.Reducer.mean(), 68 | 'MODIS_ET', 500, 'system:time_start', 'system:index') 69 | .setChartType('AreaChart') 70 | .setOptions({ 71 | title: 'Evapotranspiration Comparison', 72 | vAxis: {title: 'ET (mm)'}, hAxis: {title: 'Date'}, 73 | series: {0:{color: 'orange', lineWidth: 4, pointSize: 5}, 74 | 1:{color: 'green', lineWidth: 4, pointSize: 5}} 75 | 76 | 77 | }) 78 | ) 79 | 80 | 81 | -------------------------------------------------------------------------------- /0151_xee_sen2_cloud_masking: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0071_sen2_cloud_mask.ipynb 3 | 4 | utorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-156: Sentienl-2 Cloud Masking using Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | 14 | """ 15 | 16 | import ee 17 | import geemap 18 | import xarray as xr 19 | !pip install xee 20 | import xee 21 | 22 | ee.Authenticate() 23 | ee.Initialize( 24 | project = 'ee-amirhosseinahrari', 25 | opt_url = 'https://earthengine-highvolume.googleapis.com' 26 | ) 27 | 28 | map = geemap.Map(basemap = 'SATELLITE') 29 | map 30 | 31 | roi = map.draw_last_feature.geometry() 32 | 33 | roi 34 | 35 | def cloud_mask(img): 36 | qa = img.select('probability') 37 | cloud_mask = qa.lt(20) 38 | ms = img.select('B.*').multiply(0.0001) 39 | ndvi = ms.normalizedDifference(['B8', 'B4']).rename('ndvi') 40 | return ndvi.updateMask(cloud_mask).copyProperties(img, ['system:time_start']) 41 | 42 | 43 | sen2 = ( 44 | ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED").linkCollection( 45 | ee.ImageCollection("COPERNICUS/S2_CLOUD_PROBABILITY"), 'probability' 46 | ) 47 | .filterDate('2024','2025') 48 | .filterBounds(roi) 49 | .map(cloud_mask) 50 | ) 51 | 52 | sen2 53 | 54 | ds = xr.open_dataset( 55 | sen2, 56 | engine = 'ee', 57 | crs = 'EPSG:4326', 58 | geometry = roi, 59 | scale = 0.0003 60 | ) 61 | 62 | ds 63 | 64 | ds = ds.sortby('time') * 1 65 | 66 | ds_weekly = ds.resample(time = 'W').max('time') 67 | 68 | ds_weekly.ndvi.plot( 69 | x = 'lon', 70 | y = 'lat', 71 | col = 'time', 72 | col_wrap = 8, 73 | robust = True 74 | ) 75 | 76 | ds_rol = ds_weekly.rolling(time = 15, min_periods = 1, center = True).mean('time') 77 | 78 | ds_rol.ndvi.plot( 79 | x = 'lon', 80 | y = 'lat', 81 | col = 'time', 82 | col_wrap = 8, 83 | robust = True 84 | ) 85 | 86 | ds.sel(time = ds.time.dt.month == 7).ndvi.plot( 87 | x = 'lon', 88 | y = 'lat', 89 | col = 'time', 90 | col_wrap = 6, 91 | robust = True 92 | ) 93 | -------------------------------------------------------------------------------- /00003_precipitation_anomaly: -------------------------------------------------------------------------------- 1 | /* 2 | Tutorial Code by Amirhossein Ahrari 3 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 4 | 5 | This code is part of a tutorial series on Earth Engine programming techniques 6 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 7 | this code for academic and non-academic purposes. Don't forget to subscribe to 8 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 9 | */ 10 | 11 | 12 | var cor = [ 13 | [54.04610024292115,36.26824729036319], 14 | [56.30928383667115,36.26824729036319], 15 | [56.30928383667115,37.7942120428063], 16 | [54.04610024292115,37.7942120428063], 17 | [54.04610024292115,36.26824729036319] 18 | ] 19 | 20 | var roi = ee.Geometry.MultiPolygon(cor); 21 | 22 | Map.addLayer(roi) 23 | 24 | var time_start = '2000', time_end = '2020' 25 | 26 | var chirps = ee.ImageCollection("UCSB-CHG/CHIRPS/DAILY") 27 | .filterDate(time_start, time_end); 28 | 29 | function temporal_collection(collection, start, count, interval, unit){ 30 | var seq = ee.List.sequence(0, ee.Number(count).subtract(1)); 31 | var origin_date = ee.Date(start); 32 | return ee.ImageCollection(seq.map(function(i){ 33 | var start_date = origin_date.advance(ee.Number(interval).multiply(i), unit); 34 | var end_date = origin_date.advance(ee.Number(interval).multiply(ee.Number(i).add(1)), unit); 35 | return collection.filterDate(start_date, end_date).sum() 36 | .set('system:time_start', start_date.millis()) 37 | .set('system:time_end', end_date.millis()) 38 | })) 39 | } 40 | 41 | var monthly = temporal_collection(chirps, time_start, 240, 1, 'month'); 42 | 43 | 44 | var pr_mean = monthly.mean(); 45 | 46 | Map.addLayer(pr_mean.clip(roi),[],'pr_mean', false); 47 | 48 | var anomaly = monthly.map(function(img){ 49 | return img.subtract(pr_mean) 50 | .copyProperties(img, img.propertyNames()) 51 | }); 52 | 53 | 54 | print( 55 | ui.Chart.image.series(anomaly, roi, ee.Reducer.mean(), 56 | 5000, 'system:time_start').setChartType('ColumnChart') 57 | ) 58 | 59 | Map.addLayer(anomaly.filterDate('2010','2011').toBands().clip(roi),[],'anomaly2010', false) 60 | 61 | 62 | Export.image.toDrive({ 63 | image: anomaly.filterDate('2010','2011').toBands().clip(roi).float(), 64 | description: 'pr_anomaly2010', 65 | scale: 5000, 66 | region: roi, 67 | folder: 'precipitatoin', 68 | crs: 'EPSG:4326', 69 | }) 70 | 71 | -------------------------------------------------------------------------------- /00014_daily_wind_speed: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | 7 | This code is part of a tutorial series on Earth Engine programming techniques 8 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 9 | this code for academic and non-academic purposes. Don't forget to subscribe to 10 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 11 | */ 12 | 13 | 14 | 15 | var cor = [ 16 | [52.24091120672926,28.94538993989301], 17 | [59.00848933172926,28.94538993989301], 18 | [59.00848933172926,33.89295282767506], 19 | [52.24091120672926,33.89295282767506], 20 | [52.24091120672926,28.94538993989301] 21 | ] 22 | 23 | var roi = ee.Geometry.Polygon(cor) 24 | 25 | var era5 = ee.ImageCollection("ECMWF/ERA5/DAILY") 26 | .select('u_.*','v_.*') 27 | .filterDate('2010','2024'); 28 | 29 | var windspeed = era5.map(function(img){ 30 | var eq = img.expression('sqrt((u**2)+(v**2))',{ 31 | 'u': img.select('u_.*'), 'v': img.select('v_.*') 32 | }).rename('wind_speed'); 33 | return eq 34 | .copyProperties(img, img.propertyNames()) 35 | }); 36 | 37 | print( 38 | ui.Chart.image.series(windspeed, roi, ee.Reducer.mean(), 39 | 27000, 'system:time_start') 40 | ) 41 | 42 | 43 | 44 | var wind40 = ee.ImageCollection("ECMWF/ERA5/DAILY") 45 | .filterDate('1980','2020'); 46 | 47 | var windspeed40 = wind40.map(function(img){ 48 | var eq = img.expression('sqrt((u**2)+(v**2))',{ 49 | 'u': img.select('u_.*'), 'v': img.select('v_.*') 50 | }).rename('wind_speed'); 51 | return eq 52 | .copyProperties(img, img.propertyNames()) 53 | }); 54 | 55 | function get_value(img){ 56 | var date = ee.Date(ee.Image(img).get('system:time_start')).format().slice(0,10); 57 | var value = ee.Number(ee.Image(img).reduceRegion({ 58 | reducer: ee.Reducer.mean(), geometry: roi, scale: 27000 59 | }).values().get(0)) 60 | return [date, value] 61 | } 62 | 63 | var size = windspeed40.size(); 64 | var windlist = windspeed40.toList(size).map(get_value); 65 | 66 | var wind_feature = ee.FeatureCollection(windlist.map(function(el){ 67 | el = ee.List(el); 68 | return ee.Feature(null, {'date': ee.String(el.get(0)), 'windspeed': ee.String(el.get(1))}) 69 | })); 70 | 71 | Export.table.toDrive({ 72 | collection: wind_feature, description: 'windspeed40', fileFormat: 'CSV' 73 | }) 74 | 75 | -------------------------------------------------------------------------------- /00007_sen1_flood: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | var cor = [ 13 | [54.07394733345745,36.81321992370517], 14 | [54.79904498970745,36.81321992370517], 15 | [54.79904498970745,37.45259869689526], 16 | [54.07394733345745,37.45259869689526], 17 | [54.07394733345745,36.81321992370517] 18 | ] 19 | 20 | var roi = ee.Geometry.Polygon(cor) 21 | 22 | Map.centerObject(roi); 23 | 24 | var year_start = '2019', year_end = '2020' 25 | 26 | function speckel(img){ 27 | return img.focalMedian(100, 'square', 'meters') 28 | .copyProperties(img, img.propertyNames()) 29 | } 30 | 31 | var after = ee.ImageCollection("COPERNICUS/S1_GRD") 32 | .filterBounds(roi) 33 | .filterDate(year_start, year_end) 34 | .filter(ee.Filter.calendarRange(3, 3, 'month')) 35 | .filter(ee.Filter.listContains('transmitterReceiverPolarisation', 'VV')) 36 | .filter(ee.Filter.eq('instrumentMode', 'IW')) 37 | .select('VV') 38 | .map(speckel) 39 | .min(); 40 | 41 | Map.addLayer(after.clip(roi),[],'after', false); 42 | 43 | 44 | var before = ee.ImageCollection("COPERNICUS/S1_GRD") 45 | .filterBounds(roi) 46 | .filterDate(year_start, year_end) 47 | .filter(ee.Filter.calendarRange(2,2,'month')) 48 | .filter(ee.Filter.listContains('transmitterReceiverPolarisation', 'VV')) 49 | .filter(ee.Filter.eq('instrumentMode', 'IW')) 50 | .select('VV') 51 | .map(speckel) 52 | .min(); 53 | 54 | Map.addLayer(before.clip(roi),[],'before', false) 55 | 56 | 57 | var change = before.subtract(after).rename('flood') 58 | 59 | Map.addLayer(change.clip(roi),[],'flood', false) 60 | 61 | 62 | print( 63 | ui.Chart.image.histogram(change, roi, 30) 64 | ) 65 | 66 | Map.addLayer(change.gt(7).clip(roi),[],'flood_thr', false) 67 | 68 | 69 | var flood_thr = change.gt(7); 70 | var flood_mask = flood_thr.updateMask(flood_thr); 71 | var flood_area = flood_mask.multiply(ee.Image.pixelArea().divide(1e6)); 72 | var area_sum = flood_area.reduceRegion({ 73 | reducer: ee.Reducer.sum(), geometry: roi, scale: 100 74 | }).values().get(0); 75 | 76 | print(ee.Number(area_sum).round()) 77 | -------------------------------------------------------------------------------- /00022_urban_built_up: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | 13 | var cor = [ 14 | [50.87050198728251,35.44558510822678], 15 | [51.70546292478251,35.44558510822678], 16 | [51.70546292478251,35.98746896328614], 17 | [50.87050198728251,35.98746896328614], 18 | [50.87050198728251,35.44558510822678] 19 | ] 20 | 21 | var roi = ee.Geometry.MultiPolygon(cor) 22 | 23 | 24 | Map.centerObject(roi); 25 | 26 | // call the gshl product 27 | 28 | var ghsl = ee.ImageCollection("JRC/GHSL/P2023A/GHS_BUILT_S") 29 | .select(['built_surface']) 30 | .filterBounds(roi); 31 | 32 | // visualization 33 | 34 | Map.addLayer(ghsl.toBands().clip(roi),[],'ghsl',false) 35 | 36 | // make a single layer for bands 37 | 38 | var stack = ghsl.toBands(); 39 | 40 | // export the stack layer 41 | 42 | Export.image.toDrive({ 43 | image: stack.clip(roi).float(), 44 | description: 'urban_stack', 45 | region: roi, 46 | scale: 100, 47 | maxPixels: 1e13, 48 | folder: 'test', 49 | crs: stack.getInfo().crs 50 | }) 51 | 52 | // calculate the area of residential pixels 53 | 54 | 55 | var urban1975 = ghsl.filter(ee.Filter.eq('system:index', '1975')).toBands(); 56 | 57 | var area1975 = ee.Number(urban1975.reduceRegion({ 58 | reducer: ee.Reducer.sum(), geometry: roi, scale: 100 59 | }).values().get(0)); 60 | 61 | print('residential area 1975 (km2):', ee.Number(area1975).divide(1e6)) 62 | 63 | 64 | var urban2020 = ghsl.filter(ee.Filter.eq('system:index', '2020')).toBands(); 65 | 66 | var area2020 = ee.Number(urban2020.reduceRegion({ 67 | reducer: ee.Reducer.sum(), geometry: roi, scale: 100 68 | }).values().get(0)); 69 | 70 | print('residential area 2020 (km2):', ee.Number(area2020).divide(1e6)) 71 | 72 | 73 | // calculate the are for all years 74 | 75 | var ghsl2 = ghsl.map(function(img){ 76 | return img.divide(1e6) 77 | .copyProperties(img, img.propertyNames()) 78 | }) 79 | 80 | print( 81 | ui.Chart.image.series(ghsl2, roi, ee.Reducer.sum(), 100, 'system:time_start') 82 | .setChartType('ColumnChart') 83 | ) 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /00091_python_mann_kendall: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # -*- coding: utf-8 -*- 5 | """GEE_0006_mannkendall_trend_analysis.ipynb 6 | 7 | Tutorial Code by Amirhossein Ahrari 8 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 9 | Tutorial Video: Google Earth Engine Tutorial-96: Mann-Kendall Trend in GEE 10 | 11 | This code is part of a tutorial series on Earth Engine programming techniques 12 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 13 | this code for academic and non-academic purposes. Don't forget to subscribe to 14 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 15 | 16 | """ 17 | 18 | import ee 19 | import geemap as gee 20 | 21 | ee.Authenticate() 22 | ee.Initialize(project = 'ee-amirhosseinahrari') 23 | 24 | cor = [24.163332459274812,62.95500172226916] 25 | roi = ee.Geometry.Point(cor) 26 | 27 | roi 28 | 29 | era = ee.ImageCollection("ECMWF/ERA5_LAND/MONTHLY_AGGR").select('temperature_2m').filterDate('1970','2024') 30 | 31 | era 32 | 33 | temp = era.map(lambda img: img.subtract(273.15).copyProperties(img,['system:time_start'])) 34 | 35 | temp 36 | 37 | def ext_val(img): 38 | temp_val = img.reduceRegion(reducer = ee.Reducer.first(), geometry = roi, scale = 10000).values().get(0) 39 | date_val = img.date().format('YYYY-MM-dd') 40 | return ee.Feature(None, {'date': date_val, 'temp': temp_val}) 41 | 42 | temp_date_val = temp.map(ext_val) 43 | 44 | temp_date_val 45 | 46 | data_list = temp_date_val.toList(temp_date_val.size()).getInfo() 47 | data_list 48 | 49 | temp_list = [item['properties']['temp'] for item in data_list] 50 | date_list = [item['properties']['date'] for item in data_list] 51 | 52 | date_list 53 | 54 | import pandas as pd 55 | 56 | df = pd.DataFrame({'date': date_list, 'temp': temp_list}).round(2) 57 | 58 | df 59 | 60 | df.to_csv('temp_dataset.csv') 61 | 62 | df['date'] = pd.to_datetime(df['date']) 63 | 64 | df_annual = df.resample('YE', on = 'date').mean().round(2) 65 | 66 | df_annual 67 | 68 | # @title temp 69 | 70 | from matplotlib import pyplot as plt 71 | df_annual['temp'].plot(kind='line', figsize=(8, 4), title='temp') 72 | plt.gca().spines[['top', 'right']].set_visible(False) 73 | 74 | !pip install pymannkendall 75 | 76 | import pymannkendall as mk 77 | 78 | mk_test = mk.original_test(df_annual) 79 | 80 | mk_test 81 | 82 | !pip install pyhomogeneity 83 | 84 | import pyhomogeneity as ph 85 | 86 | pet_test = ph.pettitt_test(df_annual) 87 | pet_test 88 | -------------------------------------------------------------------------------- /00004_temp_per_change: -------------------------------------------------------------------------------- 1 | /* 2 | Tutorial Code by Amirhossein Ahrari 3 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 4 | 5 | This code is part of a tutorial series on Earth Engine programming techniques 6 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 7 | this code for academic and non-academic purposes. Don't forget to subscribe to 8 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 9 | */ 10 | 11 | 12 | var cor = [ 13 | [-106.362109375,36.957529497279594], 14 | [-101.528125,36.957529497279594], 15 | [-101.528125,40.5210649481601], 16 | [-106.362109375,40.5210649481601], 17 | [-106.362109375,36.957529497279594] 18 | ] 19 | 20 | var roi = ee.Geometry.Polygon(cor) 21 | 22 | Map.centerObject(roi) 23 | 24 | 25 | var time_start = '1950', time_end = '2020' 26 | 27 | var era5 = ee.ImageCollection("ECMWF/ERA5_LAND/MONTHLY_AGGR") 28 | .select('temperature_2m') 29 | .filterDate(time_start, time_end); 30 | 31 | function temporal_collection(collection, start, count, interval, unit){ 32 | var seq = ee.List.sequence(0, ee.Number(count).subtract(1)); 33 | var origin_date = ee.Date(start); 34 | return ee.ImageCollection(seq.map(function(i){ 35 | var start_date = origin_date.advance(ee.Number(interval).multiply(i), unit); 36 | var end_date = origin_date.advance(ee.Number(interval).multiply(ee.Number(i).add(1)), unit); 37 | return collection.filterDate(start_date, end_date).mean() 38 | .set('system:time_start', start_date.millis()) 39 | .set('system:time_end', end_date.millis()) 40 | })) 41 | } 42 | 43 | var annual = temporal_collection(era5, time_start, 70, 1, 'year') 44 | .map(function(img){ 45 | return img.subtract(273.15) 46 | .copyProperties(img, img.propertyNames()) 47 | }); 48 | 49 | print( 50 | ui.Chart.image.series(annual, roi, ee.Reducer.mean(), 10000, 'system:time_start') 51 | ) 52 | 53 | // get the percent of changes 54 | 55 | var temp_mean = annual.mean(); 56 | 57 | // eq = ((temp - mean)/(mean)) * 100 58 | 59 | 60 | var change = annual.map(function(img){ 61 | var eq = img.expression('((temp - mean)/(mean)) * 100',{ 62 | 'temp': img, 'mean': temp_mean 63 | }).rename('temp_change'); 64 | return eq 65 | .copyProperties(img, img.propertyNames()) 66 | }) 67 | 68 | print( 69 | ui.Chart.image.series(change, roi, ee.Reducer.mean(), 70 | 10000, 'system:time_start').setChartType('ColumnChart') 71 | 72 | ) 73 | 74 | 75 | -------------------------------------------------------------------------------- /0160_xee_sen2_cdom: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0083_sen2_cdom.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-165: Sentinel-2 Colored Dissolved Organic Matter for Water Bodies 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | 14 | """ 15 | 16 | import ee 17 | 18 | ee.Authenticate() 19 | ee.Initialize( 20 | project = 'ee-amirhosseinahrari', 21 | opt_url = 'https://earthengine-highvolume.googleapis.com' 22 | ) 23 | 24 | import geemap 25 | 26 | map = geemap.Map(basemap = 'SATELLITE') 27 | map 28 | 29 | roi = map.draw_last_feature.geometry() 30 | roi 31 | 32 | def index(img): 33 | cloud_band = img.select('probability') 34 | clear_pixel = cloud_band.lt(20) 35 | ms_bands = img.select('B.*').multiply(0.0001) 36 | ndwi = ms_bands.normalizedDifference(['B3', 'B8']).rename('ndwi') 37 | water_body = ndwi.gt(0.1) 38 | cdom = ms_bands.expression( 39 | '537 * exp(-2.93 * (B03/B04))',{ 40 | 'B03': ms_bands.select('B3'), 41 | 'B04': ms_bands.select('B4') 42 | } 43 | ).rename('cdom') 44 | return cdom.updateMask(clear_pixel).updateMask(water_body).copyProperties(img, ['system:time_start']) 45 | 46 | 47 | 48 | sen2 = ( 49 | ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED") 50 | .linkCollection( 51 | ee.ImageCollection("COPERNICUS/S2_CLOUD_PROBABILITY"), 'probability' 52 | ) 53 | .filterDate('2024','2025') 54 | .filterBounds(roi) 55 | .map(index) 56 | 57 | ) 58 | 59 | 60 | sen2 61 | 62 | !pip install --upgrade xee 63 | 64 | import xarray as xr 65 | 66 | ds = xr.open_dataset( 67 | sen2, 68 | engine ='ee', 69 | crs = 'EPSG:4326', 70 | scale = 0.001, 71 | geometry = roi 72 | ) 73 | 74 | ds 75 | 76 | ds = ds.sortby('time') * 1 77 | 78 | ds_monthly = ds.resample(time = 'M').median('time') 79 | 80 | import matplotlib.pyplot as plt 81 | 82 | ds_monthly.cdom.plot( 83 | x = 'lon', 84 | y = 'lat', 85 | col = 'time', 86 | col_wrap = 6, 87 | robust = True, 88 | cmap = 'turbo' 89 | ) 90 | 91 | plt.savefig('cdom.png', dpi = 360, bbox_inches = 'tight') 92 | -------------------------------------------------------------------------------- /0119_xee_gap_filling: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | 4 | 5 | Tutorial Code by Amirhossein Ahrari 6 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 7 | Tutorial Video: Google Earth Engine Tutorial-124: Cloud Gap Filling, in Python API (Xee) 8 | 9 | This code is part of a tutorial series on Earth Engine programming techniques 10 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 11 | this code for academic and non-academic purposes. Don't forget to subscribe to 12 | the Amirhossein Ahrari channel and follow the videos to support the instructor 13 | 14 | 15 | """ 16 | 17 | 18 | 19 | 20 | import ee 21 | import geemap 22 | import xarray as xr 23 | 24 | !pip install xee 25 | import xee 26 | 27 | ee.Authenticate() 28 | ee.Initialize(project = 'ee-amirhosseinahrari', opt_url = 'https://earthengine-highvolume.googleapis.com') 29 | 30 | map = geemap.Map(basemap = 'SATELLITE') 31 | map 32 | 33 | roi = map.draw_last_feature.geometry() 34 | roi 35 | 36 | ndvi = ee.ImageCollection("NOAA/CDR/VIIRS/NDVI/V1").select('NDVI', 'QA').filterDate('2020','2021') 37 | ndvi 38 | 39 | def cloud_mask(img): 40 | index = img.select('NDVI').multiply(0.0001) 41 | qa = img.select('QA') 42 | cloud = qa.bitwiseAnd(1 << 1).neq(0) 43 | shadow = qa.bitwiseAnd(1 << 2).neq(0) 44 | mask = cloud.Or(shadow).Not() 45 | return index.updateMask(mask).copyProperties(img, img.propertyNames()) 46 | 47 | ndvi_masked = ndvi.map(cloud_mask) 48 | ndvi_masked 49 | 50 | ds = xr.open_dataset(ndvi_masked, engine = 'ee', crs = 'EPSG:4326', scale = 0.05, geometry = roi ) 51 | 52 | ds 53 | 54 | sub = ds.sel(time = ds.time.dt.month == 1) 55 | sub 56 | 57 | sub.NDVI.plot(x = 'lon', y = 'lat', col = 'time', col_wrap = 8, robust =True, cmap = 'RdYlGn') 58 | 59 | point = ds.sel(lon = 49.398480435524995 , lat = 37.26737308003883, time = ds.time.dt.month == 1, method ='nearest') 60 | 61 | point.NDVI.plot() 62 | 63 | rolling = ds.rolling(time = 10, min_periods = 1, center = True).mean() 64 | 65 | ds_filled = ds.fillna(rolling) 66 | 67 | sub2 = ds_filled.sel(time = ds_filled.time.dt.month == 1) 68 | 69 | import matplotlib.pyplot as plt 70 | 71 | sub2.NDVI.plot(x = 'lon', y = 'lat', col = 'time', col_wrap = 8, robust = True, cmap = 'RdYlGn') 72 | plt.savefig('ndvi_filled.png', dpi = 360, bbox_inches = 'tight') 73 | 74 | point2 = ds_filled.sel(lon = 49.398480435524995 , lat = 37.26737308003883, time = ds.time.dt.month == 1, method ='nearest') 75 | 76 | point2.NDVI.plot() 77 | -------------------------------------------------------------------------------- /00013_landcover_temperature: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | 13 | var cor = [ 14 | [51.72646131195613,35.78622502387334], 15 | [54.07753553070613,35.78622502387334], 16 | [54.07753553070613,36.97144246810686], 17 | [51.72646131195613,36.97144246810686], 18 | [51.72646131195613,35.78622502387334] 19 | ] 20 | 21 | var roi = ee.Geometry.Polygon(cor) 22 | 23 | Map.centerObject(roi); 24 | 25 | var lc = ee.ImageCollection("MODIS/061/MCD12Q1") 26 | .mode().select('LC_Type1'); 27 | 28 | var vis = { 29 | min: 1.0, 30 | max: 17.0, 31 | palette: [ 32 | '05450a', '086a10', '54a708', '78d203', '009900', 'c6b044', 'dcd159', 33 | 'dade48', 'fbff13', 'b6ff05', '27ff87', 'c24f44', 'a5a5a5', 'ff6d4c', 34 | '69fff8', 'f9ffa4', '1c0dff' 35 | ], 36 | }; 37 | 38 | Map.addLayer(lc.clip(roi),vis,'map',false) 39 | 40 | var water_thr = lc.eq(17); 41 | 42 | Map.addLayer(water_thr.clip(roi),[],'water_thr',false) 43 | 44 | var water_mask = water_thr.updateMask(water_thr) 45 | 46 | Map.addLayer(water_mask.clip(roi),[],'water_mask', false) 47 | 48 | var water_vector = water_mask.reduceToVectors({ 49 | geometry: roi, scale: 500 50 | }).union(1) 51 | 52 | Map.addLayer(water_vector,[],'water_vector',false) 53 | 54 | var temp = ee.ImageCollection("MODIS/061/MOD11A2") 55 | .select('LST_Day_1km') 56 | .filterDate('2001','2024') 57 | .map(function(img){ 58 | return img.multiply(0.02).subtract(273.15) 59 | .copyProperties(img, img.propertyNames()) 60 | }) 61 | 62 | print( 63 | ui.Chart.image.series(temp, water_vector, 64 | ee.Reducer.mean(), 500, 'system:time_start') 65 | ) 66 | 67 | 68 | 69 | function urban_layer(img){ 70 | var urban_thr = img.eq(13); 71 | var urban_mask = urban_thr.updateMask(urban_thr); 72 | var urban_vector = urban_mask.reduceToVectors({ 73 | geometry: roi, scale: 500 74 | }).union(1); 75 | return urban_vector 76 | } 77 | 78 | var urban_class = urban_layer(lc); 79 | 80 | print( 81 | ui.Chart.image.series(temp, urban_class, 82 | ee.Reducer.mean(), 500, 'system:time_start') 83 | ) 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /0099_built_percentage_api: -------------------------------------------------------------------------------- 1 | /* 2 | Tutorial Code by Amirhossein Ahrari 3 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 4 | Tutorial Video: Google Earth Engine Tutorial-104: Built-up Change Percentage, using Python API 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | import ee 13 | import geemap as gee 14 | 15 | ee.Authenticate() 16 | ee.Initialize(project = 'ee-amirhosseinahrari') 17 | 18 | cor = [[51.08709442761703,35.52787565438577],\ 19 | [51.67348969128891,35.52787565438577],\ 20 | [51.67348969128891,35.88138095518934],\ 21 | [51.08709442761703,35.88138095518934],\ 22 | [51.08709442761703,35.52787565438577]] 23 | 24 | cor 25 | 26 | roi = ee.Geometry.Polygon(cor) 27 | roi 28 | 29 | map = gee.Map(basemap = 'SATELLITE') 30 | map.centerObject(roi) 31 | map.addLayer(roi,{} ,'roi') 32 | map 33 | 34 | built = ee.ImageCollection("JRC/GHSL/P2023A/GHS_BUILT_S").select('built_surface') 35 | built 36 | 37 | stack = built.toBands().clip(roi) 38 | stack 39 | 40 | map.addLayer(stack, {},'stack') 41 | 42 | def ext_area(img): 43 | thr = img.gt(0) 44 | mask = thr.updateMask(thr) 45 | area = mask.multiply(ee.Image.pixelArea()) 46 | val = area.reduceRegion(reducer = ee.Reducer.sum(), geometry = roi, scale = 100).values().get(0) 47 | date = img.date().format('YYYY-MM-dd') 48 | return ee.Feature(None, {'date': date, 'area': val}) 49 | 50 | built_area = built.map(ext_area) 51 | built_area 52 | 53 | area_list = built_area.toList(built_area.size()).getInfo() 54 | area_list 55 | 56 | date = [item['properties']['date'] for item in area_list] 57 | date 58 | 59 | area = [item['properties']['area'] for item in area_list] 60 | area 61 | 62 | import pandas as pd 63 | import numpy as np 64 | 65 | df = pd.DataFrame({'date': date, 'area': area}) 66 | df['date'] = pd.to_datetime(df['date']) 67 | df_index = df.set_index('date').divide(1e6).round(2) 68 | df_index 69 | 70 | df_index.to_csv('built_area_tehran.csv') 71 | 72 | df_index.plot() 73 | 74 | """change_perce = ((current - previous)/ previous) * 100""" 75 | 76 | current = df_index.copy() 77 | previous = df_index.shift(1) 78 | previous 79 | 80 | change = ((current - previous)/previous) * 100 81 | change 82 | 83 | change.plot() 84 | -------------------------------------------------------------------------------- /0141_xee_dust_wind: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0058_dust_wind.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-146: Dust and Wind Association Analysis, in Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | 14 | """ 15 | 16 | import ee 17 | import geemap 18 | !pip install xee 19 | import xee 20 | import xarray as xr 21 | import matplotlib.pyplot as plt 22 | 23 | ee.Authenticate() 24 | ee.Initialize( 25 | project = 'ee-amirhosseinahrari', opt_url = 'https://earthengine-highvolume.googleapis.com' 26 | ) 27 | 28 | map = geemap.Map(basemap = 'SATELLITE') 29 | map 30 | 31 | roi = map.draw_last_feature.geometry() 32 | 33 | roi 34 | 35 | pm = ( 36 | ee.ImageCollection("projects/sat-io/open-datasets/GLOBAL-SATELLITE-PM25/MONTHLY") 37 | .select([0],['pm']) 38 | .filterDate('2010','2015') 39 | 40 | ) 41 | 42 | vs = ( 43 | ee.ImageCollection("IDAHO_EPSCOR/TERRACLIMATE") 44 | .select('vs') 45 | .filterDate('2010','2015') 46 | .map(lambda img: img.multiply(0.01).copyProperties(img, ['system:time_start'])) 47 | ) 48 | 49 | join = ee.Join.inner() 50 | filter = ee.Filter.equals( 51 | leftField = 'system:time_start', 52 | rightField = 'system:time_start' 53 | ) 54 | join_col = ee.ImageCollection( 55 | join.apply(pm, vs, filter) 56 | ) 57 | 58 | collection = join_col.map( 59 | lambda el: ee.Image.cat(el.get('primary'), el.get('secondary')) 60 | ) 61 | 62 | collection 63 | 64 | ds = xr.open_dataset( 65 | collection, 66 | engine = 'ee', 67 | crs = 'EPSG:4326', 68 | scale = 0.1, 69 | geometry = roi 70 | ) 71 | 72 | ds 73 | 74 | ds_mean = ds.mean(dim = ['lat','lon']) 75 | 76 | ds_mean 77 | 78 | df = ds_mean.to_dataframe() 79 | 80 | fig, ax = plt.subplots(figsize = (8, 3)) 81 | 82 | ax.plot(df.index, df.pm) 83 | ax1 = ax.twinx() 84 | ax1.bar(df.index, df.vs, color = 'red', width = 10, alpha = 0.2) 85 | 86 | df.corr() 87 | 88 | plt.scatter(df.pm, df.vs) 89 | 90 | import statsmodels.api as sm 91 | 92 | x = df.vs.values 93 | y = df.pm.values 94 | x = sm.add_constant(x) 95 | 96 | model = sm.OLS(y, x).fit() 97 | 98 | print(model.summary()) 99 | -------------------------------------------------------------------------------- /0152_xee_svi_viirs: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0072_svi.ipynb 3 | 4 | 5 | Tutorial Code by Amirhossein Ahrari 6 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 7 | Tutorial Video: Google Earth Engine Tutorial-157: Standardized Vegetation Index (SVI) using Python API (Xee) 8 | 9 | This code is part of a tutorial series on Earth Engine programming techniques 10 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 11 | this code for academic and non-academic purposes. Don't forget to subscribe to 12 | the Amirhossein Ahrari channel and follow the videos to support the instructor 13 | 14 | 15 | 16 | """ 17 | 18 | import ee 19 | import geemap 20 | !pip install xee 21 | import xee 22 | import xarray as xr 23 | 24 | ee.Authenticate() 25 | ee.Initialize( 26 | project = 'ee-amirhosseinahrari', 27 | opt_url = 'https://earthengine-highvolume.googleapis.com' 28 | ) 29 | 30 | map = geemap.Map(basemap = 'SATELLITE') 31 | map 32 | 33 | point = map.draw_last_feature.geometry() 34 | point 35 | 36 | roi = ee.FeatureCollection("FAO/GAUL/2015/level1").filterBounds(point).geometry().simplify(1000) 37 | map.addLayer(roi, {}, 'roi') 38 | 39 | evi = ( 40 | ee.ImageCollection("NASA/VIIRS/002/VNP13A1") 41 | .filterDate('2015','2025') 42 | .select('EVI') 43 | .map(lambda x: x.clip(roi).copyProperties(x, ['system:time_start'])) 44 | ) 45 | 46 | evi 47 | 48 | ds = xr.open_dataset( 49 | evi, 50 | engine = 'ee', 51 | crs = 'EPSG:4326', 52 | geometry = roi, 53 | scale = 0.01 54 | ) 55 | 56 | ds = ds.sortby('time') * 1 57 | 58 | ds_mean = ds.mean(dim = 'time') 59 | ds_std = ds.std(dim = 'time') 60 | svi = (ds - ds_mean) / ds_std 61 | 62 | svi_annual = svi.resample(time = 'Y').mean('time') 63 | 64 | import matplotlib.pyplot as plt 65 | 66 | svi_annual.EVI.plot( 67 | x = 'lon', 68 | y = 'lat', 69 | col = 'time', 70 | col_wrap = 5, 71 | cmap = 'turbo_r', 72 | robust = True 73 | ) 74 | 75 | plt.savefig('svi_annual.png', dpi = 360, bbox_inches = 'tight') 76 | 77 | !pip install netCDF4 78 | import netCDF4 79 | 80 | svi_annual.to_netcdf('svi_annual_array.nc') 81 | 82 | svi_annual_mean = svi_annual.mean(dim = ['lon', 'lat']) 83 | svi_annual_df = svi_annual_mean.to_dataframe().dropna() 84 | svi_annual_df.to_csv('svi_annual.csv') 85 | 86 | svi_annual_df.plot() 87 | 88 | svi_mean = svi.mean(dim = ['lon', 'lat']) 89 | svi_mean_df = svi_mean.to_dataframe().dropna() 90 | svi_mean_df.to_csv('svi_16days.csv') 91 | 92 | svi_mean_df.plot() 93 | -------------------------------------------------------------------------------- /0164_xee_utci: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0088_utci.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-169: Universal Thermal Climate Index using FLDAS 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | 14 | 15 | """ 16 | 17 | !pip install --upgrade xee 18 | 19 | !pip install -U geemap 20 | 21 | import ee 22 | 23 | ee.Authenticate() 24 | ee.Initialize( 25 | project = 'ee-amirhosseinahrari', 26 | opt_url = 'https://earthengine-highvolume.googleapis.com' 27 | ) 28 | 29 | import geemap 30 | 31 | map = geemap.Map() 32 | map 33 | 34 | roi = map.draw_last_feature.geometry() 35 | roi 36 | 37 | fldas = ( 38 | ee.ImageCollection("NASA/FLDAS/NOAH01/C/GL/M/V001") 39 | .filterDate('2020','2021') 40 | .select(['Tair_f_tavg','Wind_f_tavg','Qair_f_tavg','RadT_tavg'], 41 | ['tas','sfcWind','hurs','mrt']) 42 | .map( 43 | lambda img: img.select('sfcWind','hurs').addBands( 44 | img.select('tas', 'mrt').subtract(273.15) 45 | ) 46 | ) 47 | ) 48 | 49 | fldas 50 | 51 | import xarray as xr 52 | 53 | ds = xr.open_dataset( 54 | fldas, 55 | engine = 'ee', 56 | crs = 'EPSG:4326', 57 | scale = 0.11, 58 | geometry = roi 59 | ) 60 | 61 | ds = ds.sortby('time') * 1 62 | 63 | ds.tas.plot( 64 | x = 'lon', 65 | y = 'lat', 66 | col = 'time', 67 | col_wrap = 6, 68 | robust = True 69 | ) 70 | 71 | !pip install xclim 72 | 73 | from xclim.indicators.convert import universal_thermal_climate_index 74 | 75 | tas = ds.tas 76 | tas.attrs['units'] = 'degC' 77 | hurs = ds.hurs 78 | hurs.attrs['units'] = '' 79 | sfcWind = ds.sfcWind 80 | sfcWind.attrs['units'] = 'm s-1' 81 | mrt = ds.mrt 82 | mrt.attrs['units'] = 'degC' 83 | 84 | utci = universal_thermal_climate_index( 85 | tas = tas, 86 | hurs = hurs, 87 | sfcWind = sfcWind, 88 | mrt = mrt 89 | ) 90 | 91 | utci_cel = utci - 273.15 92 | 93 | utci_cel.plot( 94 | x = 'lon', 95 | y = 'lat', 96 | robust = True, 97 | col = 'time', 98 | col_wrap = 6 99 | ) 100 | 101 | -------------------------------------------------------------------------------- /0167_xee_lake_ice_cover: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0090_ice_lake.ipynb 3 | 4 | 5 | Tutorial Code by Amirhossein Ahrari 6 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 7 | Tutorial Video: Google Earth Engine Tutorial-172: Lake Ice Cover Monitoring using Sentinel-1 8 | 9 | This code is part of a tutorial series on Earth Engine programming techniques 10 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 11 | this code for academic and non-academic purposes. Don't forget to subscribe to 12 | the Amirhossein Ahrari channel and follow the videos to support the instructor 13 | 14 | """ 15 | 16 | !pip install --upgrade xee 17 | 18 | !pip install -U geemap 19 | 20 | import ee 21 | 22 | ee.Authenticate() 23 | ee.Initialize( 24 | project ='ee-amirhosseinahrari', 25 | opt_url = 'https://earthengine-highvolume.googleapis.com' 26 | ) 27 | 28 | import geemap 29 | 30 | map = geemap.Map(basemap = 'SATELLITE') 31 | map 32 | 33 | roi = map.draw_last_feature.geometry() 34 | roi 35 | 36 | lake = ( 37 | ee.ImageCollection("GOOGLE/DYNAMICWORLD/V1") 38 | .filterDate('2024','2025') 39 | .filterBounds(roi) 40 | .filter(ee.Filter.calendarRange(6,9,'month')) 41 | .select('label') 42 | .mode().eq(0).selfMask() 43 | ) 44 | 45 | 46 | sen1 = ( 47 | ee.ImageCollection("COPERNICUS/S1_GRD") 48 | .filterDate('2022','2024') 49 | .filterBounds(roi) 50 | .filter(ee.Filter.listContains('transmitterReceiverPolarisation', 'VV')) 51 | .filter(ee.Filter.eq('instrumentMode', 'IW')) 52 | .select('VV') 53 | .filter(ee.Filter.eq('orbitProperties_pass', 'DESCENDING')) 54 | .map( 55 | lambda img: img.updateMask(lake).copyProperties(img,['system:time_start']) 56 | ) 57 | ) 58 | 59 | sen1 60 | 61 | map.addLayer(lake.clip(roi), {},'lake') 62 | 63 | import xarray as xr 64 | 65 | ds = xr.open_dataset( 66 | sen1, 67 | engine = 'ee', 68 | crs = 'EPSG:4326', 69 | scale = 0.001, 70 | geometry = roi 71 | ) 72 | 73 | ds = ds.sortby('time') * 1 74 | 75 | ds_roll = ds.rolling(time = 10, center = True, min_periods = 1).mean('time') 76 | 77 | ds_weekly = ds_roll.resample(time = 'W').mean('time') 78 | 79 | ds_weekly.mean(dim = ['lat', 'lon']).to_dataframe().plot() 80 | 81 | plot = ds_weekly.VV.plot( 82 | x = 'lon', 83 | y = 'lat', 84 | col = 'time', 85 | col_wrap = 10, 86 | cmap = 'turbo', 87 | robust = True 88 | ) 89 | 90 | for x in plot.axes.flat: 91 | x.set_title(x.get_title(), fontsize = 15) 92 | 93 | -------------------------------------------------------------------------------- /00064_climate_classification: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | 7 | This code is part of a tutorial series on Earth Engine programming techniques 8 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 9 | this code for academic and non-academic purposes. Don't forget to subscribe to 10 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 11 | */ 12 | 13 | var cor = [ 14 | [43.35677604381791,23.674610360519907], 15 | [63.30794791881791,23.674610360519907], 16 | [63.30794791881791,40.069578895767485], 17 | [43.35677604381791,40.069578895767485], 18 | [43.35677604381791,23.674610360519907] 19 | ] 20 | 21 | var geometry = ee.Geometry.Polygon(cor) 22 | 23 | Map.centerObject(geometry) 24 | 25 | var era = ee.ImageCollection("ECMWF/ERA5_LAND/MONTHLY_AGGR") 26 | .filterDate('2000','2020') 27 | 28 | var climate = era.select('temperature_2m','total_precipitation_sum') 29 | 30 | var climate_stack = climate.toBands() 31 | 32 | var sample = climate_stack.sample({ 33 | region: geometry, scale: 10000, numPixels: 100 34 | }); 35 | 36 | var model = ee.Clusterer.wekaKMeans(4).train(sample) 37 | 38 | var climate_map = climate_stack.cluster(model).rename('climate_map'); 39 | 40 | Map.addLayer(climate_map.clip(geometry), {min:0, max:3}, 'climate map', false) 41 | 42 | 43 | Export.image.toDrive({ 44 | image: climate_map, 45 | description: 'climate_map', 46 | scale: 10000, 47 | region: geometry, 48 | crs: 'EPSG:4326', 49 | folder: 'test' 50 | }) 51 | 52 | var area_img = ee.Image.pixelArea().divide(1e6).addBands(climate_map); 53 | 54 | print( 55 | ui.Chart.image.byClass(area_img, 'climate_map', geometry, ee.Reducer.sum(), 56 | 10000) 57 | ) 58 | 59 | var temp = era.select('temperature_2m').mean().subtract(273.15) 60 | 61 | var temp_map = temp.addBands(climate_map) 62 | 63 | var temp_stat = temp_map.reduceRegion({ 64 | reducer: ee.Reducer.minMax().group(1), geometry: geometry, scale: 10000 65 | }); 66 | 67 | var class3 = climate_map.eq(3) 68 | 69 | var ndvi = ee.ImageCollection("MODIS/061/MOD13A1") 70 | .filterDate('2002','2020') 71 | .map(function(img){ 72 | var band = img.select('NDVI').multiply(0.0001); 73 | return band.updateMask(class3) 74 | .copyProperties(img, img.propertyNames()) 75 | }); 76 | 77 | print( 78 | ui.Chart.image.series(ndvi, geometry, ee.Reducer.mean(), 10000, 'system:time_start') 79 | ) 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /00012_snow_area: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | var cor = [ 13 | [44.44379054392027,34.879626513916506], 14 | [49.27777491892027,34.879626513916506], 15 | [49.27777491892027,38.95343252297563], 16 | [44.44379054392027,38.95343252297563], 17 | [44.44379054392027,34.879626513916506] 18 | ] 19 | 20 | var roi = ee.Geometry.Polygon(cor) 21 | 22 | Map.centerObject(roi); 23 | 24 | var time_start = '2010', time_end = '2015' 25 | 26 | var modis = ee.ImageCollection("MODIS/061/MOD10A1") 27 | .select('NDSI_Snow_Cover') 28 | .filterDate(time_start, time_end); 29 | 30 | var lc = ee.ImageCollection("MODIS/061/MCD12Q1").select('LC_Type1').mode() 31 | var wb = lc.eq(17).not(); 32 | 33 | Map.addLayer(wb.clip(roi),[],'water_body',false) 34 | 35 | var ndsi_max = modis.max().updateMask(wb); 36 | 37 | Map.addLayer(ndsi_max.clip(roi),[],'ndsi_2010', false) 38 | 39 | var thr = ndsi_max.gt(50); 40 | 41 | Map.addLayer(thr.clip(roi),[],'thr50',false); 42 | 43 | var mask = thr.updateMask(thr); 44 | 45 | Map.addLayer(mask.clip(roi),[],'mask50',false); 46 | 47 | var area = mask.multiply(ee.Image.pixelArea().divide(1e6)); 48 | 49 | Map.addLayer(area.clip(roi),[],'area',false); 50 | 51 | var snow_area = ee.Number(area.reduceRegion({ 52 | reducer: ee.Reducer.sum(), 53 | geometry: roi, 54 | scale: 500, 55 | maxPixels: 1e13 56 | }).values().get(0)) 57 | 58 | print('snow cover area km2', snow_area) 59 | 60 | var ndsi = modis.map(function(img){ 61 | var mask_water = img.updateMask(wb) 62 | var ndsi_thr = mask_water.gt(20); 63 | var ndsi_mask = ndsi_thr.updateMask(ndsi_thr); 64 | var ndsi_area = ndsi_mask.multiply(ee.Image.pixelArea().divide(1e6)); 65 | return ndsi_area 66 | .copyProperties(img, img.propertyNames()) 67 | }); 68 | 69 | print( 70 | ui.Chart.image.series(ndsi, roi, ee.Reducer.sum(), 71 | 500, 'system:time_start') 72 | ) 73 | 74 | Export.image.toDrive({ 75 | image: ndsi.filterDate('2011','2012') 76 | .filter(ee.Filter.calendarRange(1,1,'month')).toBands().clip(roi), 77 | description: 'modis_ndsi', 78 | scale: 500, 79 | region: roi, 80 | crs: 'EPSG:4326' 81 | }) 82 | -------------------------------------------------------------------------------- /00059_spei_classification: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | 7 | This code is part of a tutorial series on Earth Engine programming techniques 8 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 9 | this code for academic and non-academic purposes. Don't forget to subscribe to 10 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 11 | */ 12 | 13 | 14 | 15 | var cor = [ 16 | [43.72779439368948,24.384894113007075], 17 | [63.50318501868948,24.384894113007075], 18 | [63.50318501868948,39.992077187814196], 19 | [43.72779439368948,39.992077187814196], 20 | [43.72779439368948,24.384894113007075] 21 | ] 22 | 23 | var geometry = ee.Geometry.Polygon(cor) 24 | 25 | var spei = ee.ImageCollection("CSIC/SPEI/2_9") 26 | .select('SPEI_12_month') 27 | .filterDate('1980','2023') 28 | 29 | print( 30 | ui.Chart.image.series(spei, geometry, ee.Reducer.mean(), 55000, 'system:time_start') 31 | ) 32 | 33 | var spei_mean = spei.map(function(img){ 34 | 35 | var mean = ee.Number(img.reduceRegion({ 36 | reducer: ee.Reducer.mean(), geometry: geometry, scale: 55000 37 | }).values().get(0)) 38 | 39 | return img 40 | .copyProperties(img, img.propertyNames()) 41 | .set('spei', mean) 42 | 43 | }) 44 | 45 | 46 | var spei_class = spei_mean.map(function(img){ 47 | var spei_ave = ee.Number(img.get('spei')) 48 | 49 | 50 | var classes = ee.Algorithms.If(spei_ave.lte(-2.0), 'Severe Drought', 51 | ee.Algorithms.If(spei_ave.gt(-2.0).and(spei_ave.lte(-1)), 'Moderate Drought', 52 | ee.Algorithms.If(spei_ave.gt(-1).and(spei_ave.lte(0)), 'Mild Drought', 53 | ee.Algorithms.If(spei_ave.gt(0).and(spei_ave.lte(1)), 'Normal Drought', 54 | ee.Algorithms.If(spei_ave.gt(1), 'No Drought'))))) 55 | 56 | return img 57 | .copyProperties(img, img.propertyNames()) 58 | .set('spei_class', ee.String(classes)) 59 | 60 | }) 61 | 62 | var drought = spei_class.map(function(img){ 63 | var class_name = ee.String(img.get('spei_class')) 64 | return img.rename(class_name) 65 | .copyProperties(img, img.propertyNames()) 66 | }); 67 | 68 | 69 | print( 70 | ui.Chart.image.series(drought, geometry, ee.Reducer.mean(), 55000, 'system:time_start') 71 | .setChartType('ScatterChart') 72 | .setOptions({ 73 | title: 'Drought Monitoring', 74 | pointSize: 3 75 | }) 76 | ) 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /00083_pr_intensity: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-88: Precipitation Intensity Index 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 12 | */ 13 | 14 | var cor = [ 15 | [-18.943910440675328,-37.08330302145323], 16 | [47.85296455932467,-37.08330302145323], 17 | [47.85296455932467,42.3649692346185], 18 | [-18.943910440675328,42.3649692346185], 19 | [-18.943910440675328,-37.08330302145323] 20 | ] 21 | 22 | var geometry = ee.Geometry.Polygon(cor) 23 | 24 | 25 | 26 | 27 | var pr = ee.ImageCollection("NOAA/PERSIANN-CDR") 28 | .filterDate('2023','2024') 29 | 30 | var w = pr.map(function(img){ 31 | return img.gte(1) 32 | }).sum() 33 | 34 | Map.addLayer(w,[],'wet_days',false) 35 | 36 | var rr = pr.map(function(img){ 37 | var thr = img.gte(1) 38 | return img.updateMask(thr) 39 | }).sum(); 40 | 41 | Map.addLayer(rr,[],'sum_pr',false) 42 | 43 | var intensity = rr.divide(w).rename('pr_intensity') 44 | 45 | Map.addLayer(intensity,{palette:['red','white','blue']}, 'pr_intensity',false, 0.5) 46 | 47 | Export.image.toDrive({ 48 | image: intensity, 49 | description: 'pr_intensity', 50 | scale: 27000, 51 | crs: 'EPSG:4326', 52 | region: geometry, 53 | folder: 'test' 54 | }) 55 | 56 | function pr_intensity(collection, date, thr){ 57 | var year = ee.Date(date) 58 | var filter = collection.filterDate(year, year.advance(1, 'year')) 59 | var num_wet = filter.map(function(img){ 60 | return img.gte(1) 61 | }).sum(); 62 | var pr_total = filter.map(function(img){ 63 | return img.updateMask(img.gte(1)) 64 | }).sum(); 65 | var index = pr_total.divide(num_wet).rename('pr_intensity'+date) 66 | Map.addLayer(index,{palette:['red','white','blue']}, 'pr_intensity_'+date,false, 0.5) 67 | Export.image.toDrive({ 68 | image: index, 69 | description: 'pr_intensity'+date, 70 | scale: 27000, 71 | crs: 'EPSG:4326', 72 | region: geometry, 73 | folder: 'test' 74 | }) 75 | return index 76 | } 77 | 78 | var sdii2010 = pr_intensity(ee.ImageCollection("NOAA/PERSIANN-CDR"), '2010', 1) 79 | var sdii2015 = pr_intensity(ee.ImageCollection("NOAA/PERSIANN-CDR"), '2015', 1) 80 | 81 | -------------------------------------------------------------------------------- /0104_xee_pm25: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0012_PM25.ipynb 3 | 4 | utorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-109: PM25 Mapping, using Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 12 | 13 | """ 14 | 15 | import ee 16 | import xarray as xr 17 | 18 | !pip install xee 19 | import xee 20 | 21 | ee.Authenticate() 22 | ee.Initialize(project = '*****', opt_url='https://earthengine-highvolume.googleapis.com') 23 | 24 | col = ee.ImageCollection("NASA/GSFC/MERRA/aer/2").select('DUSCAT25') 25 | 26 | time_start = ee.Date('2008') 27 | time_end = ee.Date('2009') 28 | time_dif = time_end.difference(time_start, 'days').round() 29 | time_list = ee.List.sequence(0, ee.Number(time_dif).subtract(1)).map(lambda interval: time_start.advance(interval, 'days')) 30 | 31 | def daily_agg(date): 32 | start_date = ee.Date(date) 33 | end_date = start_date.advance(1, 'days') 34 | image = col.filterDate(start_date, end_date).mean() 35 | return image.set('system:time_start', start_date.millis()) 36 | 37 | col_daily = ee.ImageCollection(time_list.map(daily_agg)) 38 | 39 | loc = [42.537376918517644, 24.73555588205892, 65.91628316851765, 40.01810716361305] 40 | 41 | ds = xr.open_dataset(col_daily, engine = 'ee', crs = 'EPSG:4326', scale = 0.5, geometry = loc) 42 | 43 | ds 44 | 45 | point = ds.sel(lon = 49.217064418517644, lat = 31.173987446501265, method = 'nearest') 46 | 47 | point 48 | 49 | import matplotlib.pyplot as plt 50 | 51 | fig, ax = plt.subplots(figsize = (7, 3)) 52 | ax.plot(point.time, point.DUSCAT25, ls = ':', marker = 'o', ms = 3, color = 'red') 53 | ax.set_xlabel('date') 54 | ax.set_ylabel('DUSCAT25') 55 | ax.set_title('PM25 Variation') 56 | plt.savefig('pm25.png', dpi = 360, bbox_inches = 'tight') 57 | 58 | ds_mean = ds.mean('time') 59 | 60 | ds_mean.DUSCAT25.plot(x = 'lon', y = 'lat', cmap = 'coolwarm', robust = True) 61 | 62 | ds_mean.DUSCAT25.to_dataframe().describe() 63 | 64 | monthly = ds.resample(time = 'M').mean('time') 65 | 66 | monthly 67 | 68 | monthly.DUSCAT25.plot(x = 'lon', y = 'lat', col ='time', col_wrap = 4, cmap = 'coolwarm', robust = True) 69 | plt.savefig('pm25_monthly.png', dpi = 360, bbox_inches = 'tight') 70 | -------------------------------------------------------------------------------- /00081_lc8_tree_cover: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | 7 | This code is part of a tutorial series on Earth Engine programming techniques 8 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 9 | this code for academic and non-academic purposes. Don't forget to subscribe to 10 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 11 | */ 12 | 13 | var cor = [49.46607928539905,37.23498585398302] 14 | 15 | var geometry = ee.Geometry.Point(cor) 16 | 17 | 18 | var roi = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level1") 19 | .filterBounds(geometry) 20 | 21 | Map.centerObject(roi) 22 | Map.addLayer(roi) 23 | 24 | var mod = ee.ImageCollection("MODIS/006/MOD44B") 25 | .select('Percent_Tree_Cover') 26 | .filterDate('2020','2021').first() 27 | 28 | Map.addLayer(mod.clip(roi),[],'mod_tree_cover',false) 29 | 30 | var lc8 = ee.ImageCollection("LANDSAT/LC08/C02/T1_L2") 31 | .select('SR_B.*') 32 | .filterDate('2020', '2021') 33 | .filterBounds(roi) 34 | .filter(ee.Filter.lt('CLOUD_COVER_LAND',10)) 35 | .median() 36 | 37 | var lc8_sr = lc8.multiply(0.0000275).add(-0.2) 38 | 39 | var lc8_ndvi = lc8_sr.normalizedDifference(['SR_B5','SR_B4']).rename('ndvi') 40 | 41 | Map.addLayer(lc8_ndvi.clip(roi),[],'ndvi',false) 42 | 43 | var training_data = lc8_ndvi.addBands(mod) 44 | 45 | var linear_fit = training_data.reduceRegion({ 46 | reducer: ee.Reducer.linearFit(), geometry: roi, scale: 100 47 | }) 48 | 49 | print(linear_fit) 50 | 51 | var scale = ee.Number(linear_fit.values().get(1)) 52 | var offset = ee.Number(linear_fit.values().get(0)) 53 | 54 | print('scale', scale) 55 | print('offset', offset) 56 | 57 | var lc8_tree = lc8_ndvi.multiply(scale).add(offset).round().rename('lc8_tree_cover') 58 | 59 | var thr = lc8_tree.lt(0).not() 60 | 61 | Map.addLayer(thr.clip(roi),[],'thr',false) 62 | 63 | var lc8_tree_cover = lc8_tree.updateMask(thr) 64 | 65 | Map.addLayer(lc8_tree_cover.clip(roi),[],'lc8_tree_cover',false) 66 | 67 | 68 | var dif = mod.subtract(lc8_tree_cover) 69 | var dif_pow = dif.pow(2) 70 | var dif_mean = ee.Number(dif_pow.reduceRegion({ 71 | reducer: ee.Reducer.mean(), scale: 100, geometry: roi 72 | }).values().get(0)).sqrt() 73 | 74 | print(dif_mean) 75 | 76 | Export.image.toDrive({ 77 | image: lc8_tree_cover.clip(roi), 78 | description: 'lc8_tree', 79 | scale: 30, 80 | region: roi, 81 | maxPixels: 1e13, 82 | folder: 'test', 83 | crs: 'EPSG:4326' 84 | }) 85 | 86 | 87 | -------------------------------------------------------------------------------- /00094_sen1_speckel_filtering: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-99: Radar Speckel Filtering, using Time Series Analysis 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 12 | */ 13 | 14 | var cor = [ 15 | [48.56781318506075,30.975811844597906], 16 | [48.65948036035372,30.975811844597906], 17 | [48.65948036035372,31.051138156917705], 18 | [48.56781318506075,31.051138156917705], 19 | [48.56781318506075,30.975811844597906] 20 | ] 21 | 22 | var geometry = ee.Geometry.Polygon(cor) 23 | 24 | 25 | Map.setOptions('SATELLITE') 26 | Map.centerObject(geometry) 27 | 28 | 29 | var sen1 = ee.ImageCollection("COPERNICUS/S1_GRD") 30 | .filterDate('2023', '2024') 31 | .filterBounds(geometry) 32 | .filter(ee.Filter.listContains('transmitterReceiverPolarisation', 'VV')) 33 | .filter(ee.Filter.listContains('transmitterReceiverPolarisation', 'VH')) 34 | .filter(ee.Filter.eq('instrumentMode', 'IW')) 35 | .filter(ee.Filter.eq('orbitProperties_pass', 'ASCENDING')) 36 | 37 | 38 | var rvi = sen1.map(function(img){ 39 | var bands = img.select('VV', 'VH') 40 | var sigma = ee.Image(10).pow(img.divide(10)) 41 | var index = sigma.expression('(4 * vh) / (vh + vv)', { 42 | 'vh': sigma.select('VH'), 'vv': sigma.select('VV') 43 | }).rename('RVI') 44 | return index 45 | .copyProperties(img, ['system:time_start', 'system:time_end']) 46 | }) 47 | 48 | 49 | var day = 15 50 | var mills = ee.Number(day).multiply(1000 * 24 * 3600) 51 | var filter = ee.Filter.maxDifference({ 52 | difference: mills, leftField: 'system:time_start' , rightField: 'system:time_start' 53 | }) 54 | var join = ee.Join.saveAll('image') 55 | var join_collection = ee.ImageCollection(join.apply(rvi, rvi, filter)) 56 | .map(function(img){ 57 | var images = ee.ImageCollection.fromImages(img.get('image')).mean().rename('corrected') 58 | return img.addBands(images) 59 | .copyProperties(img, ['system:time_start', 'system:time_end']) 60 | }) 61 | 62 | print(join_collection) 63 | 64 | Map.addLayer(join_collection.select('RVI').toBands().clip(geometry),[],'RVI', false) 65 | Map.addLayer(join_collection.select('corrected').toBands().clip(geometry),[],'corrected',false) 66 | 67 | -------------------------------------------------------------------------------- /00048_sen2_green_space: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | 13 | var cor = [ 14 | [51.40150195835105,35.680686269764024], 15 | [51.41738063571921,35.67796719930233], 16 | [51.41841060398093,35.68584527697069], 17 | [51.420813863258275,35.68584527697069], 18 | [51.41944057224265,35.70145969785625], 19 | [51.40536433933249,35.70118089572008], 20 | [51.40150195835105,35.680686269764024] 21 | ] 22 | 23 | var geometry = ee.Geometry.Polygon(cor) 24 | 25 | Map.centerObject(geometry) 26 | 27 | var sen2 = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED") 28 | .filterBounds(geometry) 29 | .filterDate('2018','2024') 30 | .filter(ee.Filter.calendarRange(6,8,'month')) 31 | .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',10)) 32 | .map(function(img){ 33 | var bands = img.select('B.*').multiply(0.0001); 34 | var ndvi = bands.normalizedDifference(['B8','B4']).rename('ndvi') 35 | return ndvi 36 | .copyProperties(img, ['system:time_start', 'system:time_end']) 37 | }) 38 | 39 | var ndvi_mean = sen2.median(); 40 | 41 | Map.addLayer(ndvi_mean.clip(geometry),[],'ndvi_mean',false) 42 | 43 | print( 44 | ui.Chart.image.histogram(ndvi_mean, geometry, 10) 45 | ) 46 | 47 | var ndvi_thr = ndvi_mean.gt(0.25); 48 | 49 | Map.addLayer(ndvi_thr.clip(geometry),[],'ndvi_thr', false) 50 | 51 | var ndvi_mask = ndvi_thr.updateMask(ndvi_thr); 52 | 53 | Map.addLayer(ndvi_mask.clip(geometry),[],'ndvi_mask', false) 54 | 55 | var ndvi_area = ndvi_mask.multiply(ee.Image.pixelArea()) 56 | 57 | Map.addLayer(ndvi_area.clip(geometry),[],'ndvi_area', false) 58 | 59 | var area_val = ndvi_area.reduceRegion({ 60 | reducer: ee.Reducer.sum(), geometry: geometry, scale: 10 61 | }).values().get(0) 62 | 63 | print(area_val) 64 | 65 | var tree_area = sen2.map(function(img){ 66 | var ndvi_thr = img.gt(0.25); 67 | var ndvi_mask = ndvi_thr.updateMask(ndvi_thr); 68 | var ndvi_area = ndvi_mask.multiply(ee.Image.pixelArea()) 69 | return ndvi_area 70 | .copyProperties(img, img.propertyNames()) 71 | }) 72 | 73 | print( 74 | ui.Chart.image.series(tree_area, geometry, ee.Reducer.sum(), 10, 'system:time_start') 75 | .setChartType('ColumnChart') 76 | ) 77 | 78 | -------------------------------------------------------------------------------- /0127_xee_wetland_detection: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0039_wetland_mapping.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-132: Wetland Detection and Mapping, in Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | """ 14 | 15 | import ee 16 | import geemap 17 | import xarray as xr 18 | 19 | !pip install xee 20 | import xee 21 | 22 | ee.Authenticate() 23 | ee.Initialize( 24 | project = 'ee-amirhosseinahrari', 25 | opt_url = 'https://earthengine-highvolume.googleapis.com' 26 | ) 27 | 28 | map = geemap.Map(basemap = 'SATELLITE') 29 | map 30 | 31 | roi = map.draw_last_feature.geometry() 32 | 33 | roi 34 | 35 | landsat = ( 36 | ee.ImageCollection("LANDSAT/LC08/C02/T1_L2") 37 | .filterDate('2020', '2024') 38 | .filterBounds(roi) 39 | .filter(ee.Filter.lt('CLOUD_COVER',45)) 40 | ) 41 | 42 | landsat 43 | 44 | landsat_mean = landsat.select('SR_B.*').mean() 45 | landsat_mean 46 | 47 | ds = xr.open_dataset( 48 | landsat_mean, 49 | engine = 'ee', 50 | crs = 'EPSG:4326', 51 | scale = 0.003, 52 | geometry = roi 53 | ) 54 | 55 | ds = ds * 2.75e-05 + (-0.2) 56 | 57 | nir = ds.SR_B5 58 | red = ds.SR_B4 59 | swir2 = ds.SR_B7 60 | 61 | import matplotlib.pyplot as plt 62 | 63 | fig, ax = plt.subplots(1,2, figsize = (10,5)) 64 | plt.tight_layout(w_pad = 4) 65 | 66 | nir.plot( 67 | x = 'lon', 68 | y = 'lat', 69 | robust = True, 70 | ax = ax[0] 71 | ) 72 | 73 | swir2.plot( 74 | x = 'lon', 75 | y = 'lat', 76 | robust = True, 77 | ax = ax[1] 78 | ) 79 | 80 | ndvi = (nir - red) / (nir + red) 81 | 82 | ndvi.plot( 83 | x = 'lon', 84 | y = 'lat', 85 | robust = True 86 | ) 87 | 88 | green = ds.SR_B3 89 | 90 | ndwi = (green - nir) / (green + nir) 91 | 92 | ndwi.plot( 93 | x = 'lon', 94 | y = 'lat', 95 | robust = True 96 | ) 97 | 98 | wiw = (nir <= 0.1735) & (swir2 <= 0.1035) 99 | 100 | wiw.plot( 101 | x = 'lon', 102 | y = 'lat' 103 | ) 104 | 105 | wiw = (nir <= 0.1735) | (swir2 <= 0.1035) 106 | 107 | wiw.plot( 108 | x = 'lon', 109 | y = 'lat' 110 | ) 111 | -------------------------------------------------------------------------------- /00049_sen2_deforestation: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | var cor = [ 13 | [24.664959178687543,64.99123253965863], 14 | [24.66427253317973,64.99087875350403], 15 | [24.66504500937602,64.98997612402353], 16 | [24.664948449851483,64.98982643880142], 17 | [24.665688739539593,64.98954974572945], 18 | [24.666203723670453,64.98957242559722], 19 | [24.666203723670453,64.98957242559722], 20 | [24.66606424880168,64.99008498547678], 21 | [24.664959178687543,64.99123253965863] 22 | ] 23 | 24 | var geometry = ee.Geometry.Polygon(cor) 25 | 26 | Map.centerObject(geometry) 27 | 28 | var sen = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED") 29 | .filterBounds(geometry) 30 | .filterDate('2017','2024') 31 | .filter(ee.Filter.calendarRange(6,9,'month')) 32 | .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',10)) 33 | .map(function(img){ 34 | var bands = img.select('B.*').multiply(0.0001) 35 | var ndvi = bands.normalizedDifference(['B8','B4']).rename('ndvi') 36 | return ndvi 37 | .copyProperties(img, ['system:time_start', 'system:time_end']) 38 | }); 39 | 40 | print( 41 | ui.Chart.image.series(sen, geometry, ee.Reducer.median(), 10, 'system:time_start') 42 | .setChartType('ColumnChart') 43 | ) 44 | 45 | var before = sen.filterDate('2018','2019').median().rename('before') 46 | var after = sen.filterDate('2023', '2024').median().rename('after') 47 | 48 | Map.addLayer(before.clip(geometry),[],'before',false) 49 | Map.addLayer(after.clip(geometry),[],'after',false) 50 | 51 | print( 52 | ui.Chart.image.histogram(before, geometry, 10) 53 | .setOptions({ 54 | title: 'before' 55 | }) 56 | ) 57 | 58 | print( 59 | ui.Chart.image.histogram(after, geometry, 10) 60 | .setOptions({ 61 | title: 'after' 62 | }) 63 | ) 64 | 65 | 66 | var tree_area = sen.map(function(img){ 67 | var thr = img.gt(0.5); 68 | var mask = thr.updateMask(thr); 69 | var area = mask.multiply(ee.Image.pixelArea()) 70 | return area 71 | .copyProperties(img, img.propertyNames()) 72 | }); 73 | 74 | print( 75 | ui.Chart.image.series(tree_area, geometry, ee.Reducer.sum(), 76 | 10, 'system:time_start').setChartType('ColumnChart') 77 | ) 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /0133_xee_temp_anomaly: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """0048_temp_anomaly_detection.ipynb 3 | 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-138: Temeprature Anomaly and Extreme Detection in Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | 14 | """ 15 | 16 | import ee 17 | import geemap 18 | !pip install xee 19 | import xee 20 | import xarray as xr 21 | import numpy as np 22 | import pandas as pd 23 | import matplotlib.pyplot as plt 24 | 25 | ee.Authenticate() 26 | ee.Initialize( 27 | project = 'ee-amirhosseinahrari', 28 | opt_url = 'https://earthengine-highvolume.googleapis.com' 29 | ) 30 | 31 | map = geemap.Map(basemap = 'SATELLITE') 32 | map 33 | 34 | roi = map.draw_last_feature.geometry() 35 | 36 | roi 37 | 38 | temp = ( 39 | ee.ImageCollection("MODIS/061/MOD11A2") 40 | .filterDate('2001','2025') 41 | .select('LST_Day_1km') 42 | .map(lambda img: img.multiply(0.02).subtract(273.15).copyProperties(img, img.propertyNames())) 43 | ) 44 | 45 | temp 46 | 47 | xtemp = xr.open_dataset( 48 | temp, 49 | engine = 'ee', 50 | crs = 'EPSG:4326', 51 | scale = 0.01, 52 | geometry = roi 53 | ) 54 | 55 | xtemp 56 | 57 | xtemp_mean = xtemp.mean(dim = ['lon', 'lat']) 58 | 59 | xtemp_mean.LST_Day_1km.plot() 60 | 61 | xtemp_inte = xtemp_mean.interpolate_na(dim = 'time') 62 | 63 | xtemp_df = xtemp_inte.to_dataframe() 64 | 65 | xtemp_df.to_csv('temp_df.csv') 66 | 67 | from statsmodels.tsa.seasonal import seasonal_decompose 68 | 69 | model = seasonal_decompose( 70 | xtemp_df, 71 | model = 'additive', 72 | period = 46 73 | ) 74 | 75 | model.plot() 76 | plt.show() 77 | 78 | final_df = pd.DataFrame({ 79 | 'time': model.observed.index, 80 | 'observations': model.observed.values, 81 | 'trend': model.trend.values, 82 | 'seasonal': model.seasonal.values, 83 | 'residuals': model.resid.values 84 | }) 85 | 86 | final_df = final_df.set_index('time') 87 | 88 | final_df.residuals.plot() 89 | 90 | final_df.to_csv('temp_anomaly.csv') 91 | 92 | pos = final_df[final_df['residuals'] >= 0] 93 | neg = final_df[final_df['residuals'] < 0] 94 | 95 | plt.bar(pos.index, pos.residuals, width = 10) 96 | plt.bar(neg.index, neg.residuals, width = 10) 97 | -------------------------------------------------------------------------------- /107_xee_water_consumption: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """GEE_0015_water_consumption.ipynb 3 | 4 | utorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | Tutorial Video: Google Earth Engine Tutorial-112: Vegetation Water Consumption, using Python API (Xee) 7 | 8 | This code is part of a tutorial series on Earth Engine programming techniques 9 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 10 | this code for academic and non-academic purposes. Don't forget to subscribe to 11 | the Amirhossein Ahrari channel and follow the videos to support the instructor 12 | 13 | """ 14 | 15 | import ee 16 | import geemap as gee 17 | import xarray as xr 18 | 19 | !pip install xee 20 | import xee 21 | 22 | ee.Authenticate() 23 | ee.Initialize( project = 'ee-amirhosseinahrari', opt_url = 'https://earthengine-highvolume.googleapis.com') 24 | 25 | ndvi = ee.ImageCollection("MODIS/061/MOD13A2").select('NDVI').filterDate('2019', '2020') 26 | 27 | ndvi_max = ndvi.max().multiply(0.0001) 28 | ndvi_thr = ndvi_max.gt(0.5).selfMask() 29 | ndvi_pix_area = ndvi_thr.multiply(ee.Image.pixelArea()) 30 | veg_area = ndvi_pix_area.reduceRegion(reducer = ee.Reducer.sum(), geometry =geometry, scale = 1000).values().get(0) 31 | veg_area.getInfo() 32 | 33 | map = gee.Map(basemap = 'HYBRID') 34 | map 35 | 36 | geometry = map.draw_last_feature.geometry() 37 | 38 | ds_ndvi = xr.open_dataset(ndvi, engine = 'ee', crs = 'EPSG:4326', scale = 0.01, geometry = geometry) 39 | 40 | ds_ndvi 41 | 42 | ds_ndvi_max = ds_ndvi.max(dim = 'time') * 0.0001 43 | 44 | ds_ndvi_max.NDVI.plot( x = 'lon', y = 'lat', cmap = 'Greens', robust = True) 45 | 46 | ds_ndvi_thr = ds_ndvi_max.NDVI > 0.5 47 | 48 | ds_ndvi_thr.plot(x = 'lon', y = 'lat') 49 | 50 | """https://gee-community-catalog.org/projects/usgs_modis_et/""" 51 | 52 | et = ee.ImageCollection('projects/earthengine-legacy/assets/projects/usgs-ssebop/modis_et_v5_monthly').filterDate('2019','2020') 53 | 54 | ds_et = xr.open_dataset(et, engine = 'ee', scale = 0.01, crs = 'EPSG:4326', geometry = geometry) 55 | 56 | ds_et 57 | 58 | ds_et.et.plot(x = 'lon', y ='lat', cmap = 'gist_earth_r', col = 'time', col_wrap = 4, robust = True) 59 | 60 | et_mask = ds_et * ds_ndvi_thr 61 | 62 | et_mask.et.plot(x = 'lon', y = 'lat', cmap = 'gist_earth_r', col = 'time', col_wrap = 4, robust = True) 63 | 64 | et_mean = et_mask.mean(dim = ['lon', 'lat']) 65 | et_mean 66 | 67 | et_mean_val = et_mean.et.values 68 | et_mean_val 69 | 70 | # water consumption (m3) = aet (mm) * veg_area (m2) 71 | wat_cons = 7834196440.9002495 * et_mean_val 72 | wat_cons 73 | -------------------------------------------------------------------------------- /0118_xee_ndvi_phenology: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | # -*- coding: utf-8 -*- 6 | """ 7 | 8 | 9 | Tutorial Code by Amirhossein Ahrari 10 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 11 | Tutorial Video: Google Earth Engine Tutorial-123: Vegetation Phenological Aanalysis using NDVI, in Python API (Xee) 12 | 13 | This code is part of a tutorial series on Earth Engine programming techniques 14 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 15 | this code for academic and non-academic purposes. Don't forget to subscribe to 16 | the Amirhossein Ahrari channel and follow the videos to support the instructor 17 | 18 | 19 | """ 20 | 21 | import ee 22 | import geemap 23 | import xarray as xr 24 | 25 | !pip install xee 26 | import xee 27 | 28 | ee.Authenticate() 29 | ee.Initialize(project = 'ee-amirhosseinahrari', opt_url = 'https://earthengine-highvolume.googleapis.com') 30 | 31 | map = geemap.Map(basemap = 'SATELLITE') 32 | map 33 | 34 | roi = map.draw_last_feature.geometry() 35 | roi 36 | 37 | ndvi = ee.ImageCollection("NOAA/CDR/VIIRS/NDVI/V1").select('NDVI','QA').filterDate('2021','2022') 38 | ndvi 39 | 40 | def cloud_mask(img): 41 | ndvi_img = img.select('NDVI').multiply(0.0001) 42 | qa_img = img.select('QA') 43 | cloud = qa_img.bitwiseAnd(1 << 1).neq(0) 44 | shadow = qa_img.bitwiseAnd(1 << 2).neq(0) 45 | mask = cloud.Or(shadow).Not() 46 | return ndvi_img.updateMask(mask).copyProperties(img, img.propertyNames()) 47 | 48 | ndvi_mask = ndvi.map(cloud_mask) 49 | ndvi_mask 50 | 51 | ds = xr.open_dataset(ndvi_mask, engine = 'ee', crs = 'EPSG:4326', scale = 0.1, geometry = roi) 52 | 53 | ds 54 | 55 | monthly = ds.resample(time = 'M').mean('time') 56 | 57 | monthly 58 | 59 | monthly.NDVI.plot(x = 'lon', y = 'lat', col = 'time', col_wrap =4, robust =True) 60 | 61 | !pip install netCDF4 62 | import netCDF4 63 | 64 | ds.to_netcdf('ndvi_daily.nc') 65 | 66 | !pip install dea_tools 67 | 68 | import dea_tools.temporal 69 | 70 | !pip install netCDF4 71 | import netCDF4 72 | 73 | import xarray as xr 74 | 75 | ds = xr.open_dataset('ndvi_daily.nc') 76 | 77 | ds 78 | 79 | phenology = dea_tools.temporal.xr_phenology( 80 | ds.NDVI, 81 | stats=['SOS', 'POS', 'EOS', 'Trough', 'vSOS', 'vPOS', 'vEOS', 'LOS', 'AOS', 'ROG', 'ROS'], method_sos='first', method_eos='last', verbose=True 82 | ) 83 | 84 | phenology 85 | 86 | phenology.SOS.plot(x = 'lon', y = 'lat', robust = True) 87 | 88 | phenology.POS.plot(x = 'lon', y = 'lat', robust = True) 89 | 90 | phenology.vPOS.plot(x = 'lon', y = 'lat', robust = True) 91 | 92 | phenology.LOS.plot(x = 'lon', y = 'lat', robust = True) 93 | -------------------------------------------------------------------------------- /0100_pop_growth_rate: -------------------------------------------------------------------------------- 1 | /* 2 | Tutorial Code by Amirhossein Ahrari 3 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 4 | Tutorial Video: Google Earth Engine Tutorial-105: Population Growth Rate, using Python API 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | 13 | 14 | import ee 15 | import geemap as gee 16 | 17 | ee.Authenticate() 18 | ee.Initialize(project = 'ee-amirhosseinahrari') 19 | 20 | cor = [[51.10201209984305,35.558966802445994],\ 21 | [51.6266092678118,35.558966802445994],\ 22 | [51.6266092678118,35.87005772093195],\ 23 | [51.10201209984305,35.87005772093195],\ 24 | [51.10201209984305,35.558966802445994]] 25 | 26 | cor 27 | 28 | roi = ee.Geometry.Polygon(cor) 29 | roi 30 | 31 | map = gee.Map(basemap = 'SATELLITE') 32 | map.centerObject(roi) 33 | map.addLayer(roi,{},'roi') 34 | map 35 | 36 | pop = ee.ImageCollection("JRC/GHSL/P2023A/GHS_POP") 37 | pop 38 | 39 | pop_stack = pop.toBands().clip(roi) 40 | pop_stack 41 | 42 | map.addLayer(pop_stack,{},'pop_stack') 43 | 44 | def pop_count(img): 45 | pop_sum = img.reduceRegion(reducer = ee.Reducer.sum(), geometry = roi, scale = 100).values().get(0) 46 | date = img.date().format('YYYY-MM-dd') 47 | return ee.Feature(None, {'date': date, 'pop': pop_sum}) 48 | 49 | pop_val = pop.map(pop_count) 50 | pop_val 51 | 52 | feature_list = pop_val.toList(pop_val.size()).getInfo() 53 | feature_list 54 | 55 | date = [items['properties']['date'] for items in feature_list] 56 | date 57 | 58 | pop_sum = [items['properties']['pop'] for items in feature_list] 59 | pop_sum 60 | 61 | import numpy as np 62 | import pandas as pd 63 | 64 | df = pd.DataFrame({'date': date, 'pop': pop_sum}) 65 | df['date'] = pd.to_datetime(df['date']) 66 | df_index = df.set_index('date').round(0) 67 | df_index 68 | 69 | df_index.to_csv('tehran_pop.csv') 70 | 71 | """pop_growth_rate = log(current/previous)/interval 72 | 73 | pop_change_rate = ((current - previous) / previous ) * 100 74 | """ 75 | 76 | current = df_index.copy() 77 | previous = df_index.shift(1) 78 | previous 79 | 80 | df_index['change'] = ((current - previous) / previous) * 100.0 81 | df_index 82 | 83 | df_index['growth_rate'] = np.log(current / previous) / 5.0 84 | df_index 85 | 86 | df_index['pop'].plot() 87 | 88 | df_index['change'].plot() 89 | 90 | df_index['growth_rate'].plot() 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /00070_ground_water_gldas: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | var loc1 = [48.061541161631496,36.70101649662329] 13 | var loc2 = [52.631853661631496,36.453984440880504] 14 | 15 | 16 | var point1 = ee.Feature(ee.Geometry.Point(loc1)) 17 | var point2 = ee.Feature(ee.Geometry.Point(loc2)) 18 | 19 | var geometry2 = ee.FeatureCollection([point1, point2]) 20 | 21 | 22 | 23 | 24 | var cor = [ 25 | [43.667009911631496,24.942959988339428], 26 | [63.090838036631496,24.942959988339428], 27 | [63.090838036631496,39.78889293849504], 28 | [43.667009911631496,39.78889293849504], 29 | [43.667009911631496,24.942959988339428] 30 | ] 31 | 32 | var geometry = ee.Geometry.Polygon(cor) 33 | 34 | var time_start = ee.Date('2003') 35 | var time_end = ee.Date('2024') 36 | var time_dif = time_end.difference(time_start, 'month').round() 37 | 38 | var gldas = ee.ImageCollection("NASA/GLDAS/V022/CLSM/G025/DA1D") 39 | .select('GWS_tavg') 40 | .filterDate(time_start, time_end) 41 | 42 | var list = ee.List.sequence(0, ee.Number(time_dif).subtract(1), 1).map(function(delta){ 43 | return ee.Date(time_start).advance(delta, 'month')}) 44 | 45 | var monthly = ee.ImageCollection(list.map(function(date){ 46 | var start_date = ee.Date(date) 47 | var end_date = start_date.advance(1, 'month') 48 | var month = gldas.filterDate(start_date, end_date).mean().rename('GW') 49 | var bands = month.bandNames().size() 50 | return month 51 | .set('system:time_start', start_date.millis()) 52 | .set('system:time_end', end_date.millis()) 53 | .set('system:index', start_date.format('YYYY-MM-dd')) 54 | .set('bands', ee.Number(bands)) 55 | })).filter(ee.Filter.gt('bands',0)) 56 | 57 | 58 | print( 59 | ui.Chart.image.series(monthly, geometry, ee.Reducer.mean(), 27000, 'system:time_start') 60 | ) 61 | 62 | Map.addLayer(monthly.toBands().clip(geometry),[],'GW',false) 63 | 64 | 65 | print( 66 | ui.Chart.image.seriesByRegion(monthly, geometry2, ee.Reducer.first(), 67 | 'GW', 27000, 'system:time_start', 'system:index') 68 | ) 69 | 70 | Export.image.toDrive({ 71 | image: monthly.toBands().clip(geometry), 72 | description: 'Iran_GW', 73 | scale: 27000, 74 | region: geometry, 75 | crs: 'EPSG:4326', 76 | folder: 'ground_water' 77 | }) 78 | -------------------------------------------------------------------------------- /00082_carbon_stock: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | Tutorial Code by Amirhossein Ahrari 5 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 6 | 7 | This code is part of a tutorial series on Earth Engine programming techniques 8 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 9 | this code for academic and non-academic purposes. Don't forget to subscribe to 10 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 11 | */ 12 | 13 | 14 | var cor = [49.163473931113565,37.295688008078656] 15 | 16 | var geometry = ee.Geometry.Point(cor) 17 | 18 | var roi = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level1") 19 | .filterBounds(geometry) 20 | 21 | Map.centerObject(roi) 22 | Map.addLayer(roi) 23 | 24 | var carbon = ee.ImageCollection("WCMC/biomass_carbon_density/v1_0") 25 | .first() 26 | 27 | Map.addLayer(carbon.clip(roi),[],'carbon',false) 28 | 29 | var sen2 = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED") 30 | .select('B.*') 31 | .filterBounds(roi) 32 | .filterDate('2020','2021') 33 | .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',10)) 34 | .median().multiply(0.0001) 35 | 36 | var ndvi = sen2.normalizedDifference(['B8','B4']).rename('NDVI') 37 | 38 | Map.addLayer(ndvi.clip(roi),[],'ndvi',false) 39 | 40 | var dw = ee.ImageCollection("GOOGLE/DYNAMICWORLD/V1") 41 | .select('label') 42 | .filterDate('2020','2021') 43 | .filterBounds(roi) 44 | .mode().eq(1) 45 | 46 | Map.addLayer(dw.clip(roi),[],'tree',false) 47 | 48 | var predictors = ee.Image.constant(1).addBands(sen2).addBands(ndvi).updateMask(dw) 49 | 50 | Map.addLayer(predictors.clip(roi),[],'predictors',false) 51 | 52 | var dataset = predictors.addBands(carbon) 53 | 54 | var model = dataset.reduceRegion({ 55 | reducer: ee.Reducer.robustLinearRegression(14, 1), geometry: roi, scale: 250, bestEffort:true 56 | }) 57 | 58 | var coef = ee.Array(model.get('coefficients')).project([0]).toList() 59 | 60 | var sen2_carbon = predictors.multiply(ee.Image.constant(coef)).reduce(ee.Reducer.sum()).rename('sen2_carbon') 61 | 62 | Map.addLayer(sen2_carbon.clip(roi),[],'sen2_carbon',false) 63 | 64 | 65 | var dif = carbon.subtract(sen2_carbon) 66 | var pow = dif.pow(2) 67 | var rmse = ee.Number(pow.reduceRegion({ 68 | reducer: ee.Reducer.mean(), geometry: roi, scale: 250 69 | }).values().get(0)).sqrt() 70 | 71 | print('rmse:', rmse) 72 | 73 | 74 | Export.image.toDrive({ 75 | image: sen2_carbon.float().clip(roi), 76 | description: 'sen2_carbon', 77 | scale: 100, 78 | region: roi, 79 | folder: 'test', 80 | crs: 'EPSG:4326', 81 | maxPixels: 1e13 82 | }) 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /00062_sentinel1_croptype: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Tutorial Code by Amirhossein Ahrari 4 | YouTube: https://www.youtube.com/@amirhosseinahrarigee 5 | 6 | This code is part of a tutorial series on Earth Engine programming techniques 7 | presented on the Amirhossein Ahrari YouTube channel. You are free to use and modify 8 | this code for academic and non-academic purposes. Don't forget to subscribe to 9 | the Amirhossein Ahrari channel and follow the videos to support the instructor! 10 | */ 11 | 12 | 13 | var cor = [ 14 | [48.42331357710716,31.94100799817005], 15 | [48.75839658491966,31.94100799817005], 16 | [48.75839658491966,32.18773294099697], 17 | [48.42331357710716,32.18773294099697], 18 | [48.42331357710716,31.94100799817005] 19 | ] 20 | 21 | var geometry = ee.Geometry.Polygon(cor) 22 | 23 | Map.centerObject(geometry) 24 | 25 | var time_start = '2020', time_end = '2021' 26 | 27 | var sen1 = ee.ImageCollection("COPERNICUS/S1_GRD") 28 | .filterDate(time_start, time_end) 29 | .filterBounds(geometry) 30 | .filter(ee.Filter.listContains('transmitterReceiverPolarisation','VV')) 31 | .filter(ee.Filter.eq('instrumentMode','IW')) 32 | .select('VV'); 33 | 34 | var asc = sen1 35 | .filter(ee.Filter.eq('orbitProperties_pass','ASCENDING')); 36 | 37 | var des = sen1 38 | .filter(ee.Filter.eq('orbitProperties_pass', 'DESCENDING')); 39 | 40 | 41 | var sen1_monthly = ee.ImageCollection(ee.List.sequence(1,12).map(function(month){ 42 | var asc_month = asc.filter(ee.Filter.calendarRange(month, month, 'month')).mean().rename('asc') 43 | var des_month = des.filter(ee.Filter.calendarRange(month, month, 'month')).mean().rename('des') 44 | var date = ee.Date.fromYMD(2020, month, 1) 45 | return asc_month.addBands(des_month) 46 | .set('system:time_start', date.millis()) 47 | .set('system:index', date.format('YYYY-MM')) 48 | })) 49 | 50 | 51 | var speckel = sen1_monthly.map(function(img){ 52 | return img.focalMean(30, 'square', 'meters') 53 | .copyProperties(img, img.propertyNames()) 54 | 55 | }) 56 | 57 | 58 | Map.addLayer(speckel.select('asc').toBands().clip(geometry), [], 'asc', false); 59 | Map.addLayer(speckel.select('des').toBands().clip(geometry),[], 'des', false); 60 | 61 | 62 | var cor2 = [48.53237427758136,32.07685060176268] 63 | 64 | var geometry2 = ee.Geometry.Point(cor2) 65 | 66 | print( 67 | ui.Chart.image.series(sen1_monthly, geometry2, ee.Reducer.first(), 10, 'system:time_start') 68 | ) 69 | 70 | Export.image.toDrive({ 71 | image: speckel.select('asc').toBands().clip(geometry), 72 | description: 'sar_asc', 73 | scale: 30, 74 | region: geometry, 75 | maxPixels: 1e13, 76 | crs: 'EPSG:4326', 77 | folder: 'test' 78 | }) 79 | 80 | 81 | 82 | --------------------------------------------------------------------------------