-
Notifications
You must be signed in to change notification settings - Fork 18
/
gee-water-resources-management.Rmd
1457 lines (888 loc) · 102 KB
/
gee-water-resources-management.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
---
title: "Google Earth Engine for Water Resources Management (Full Course)"
author: "Ujaval Gandhi"
subtitle: Application-focused Introduction to Google Earth Engine.
output:
# word_document:
# toc: yes
# toc_depth: '3'
html_document:
df_print: paged
highlight: pygments
includes:
after_body: comment.html
toc: yes
toc_depth: 2
# pdf_document:
# latex_engine: xelatex
# toc: yes
# toc_depth: '3'
fontsize: 12pt
header-includes:
- \usepackage{fancyhdr}
- \pagestyle{fancy}
- \renewcommand{\footrulewidth}{0.4pt}
- \fancyhead[LE,RO]{\thepage}
- \geometry{left=1in,top=0.75in,bottom=0.75in}
- \fancyfoot[CE,CO]{{\includegraphics[height=0.5cm]{images/cc-by-nc.png}} Ujaval Gandhi
http://www.spatialthoughts.com}
---
<!--- Install package vembedr to get YouTube videos rendered -->
```{r echo=FALSE}
suppressWarnings(library("vembedr"))
```
\newpage
***
```{r echo=FALSE, fig.align='center', out.width='100%', out.width='250pt'}
knitr::include_graphics('images/spatial_thoughts_logo.png')
```
***
\newpage
# Introduction
GIS and Remote Sensing plays a critical role in the management of water resources. Many practitioners in this field are constrained by the availability of tools and computing resources to use these techniques effectively. Recent advances in cloud computing technology have given rise to platforms such as Google Earth Engine, which provide free access to a large pool of computational resources and datasets. The course is designed for researchers in the water sector, academicians, water managers, and stakeholders with basic knowledge of Remote Sensing. It will enable them to leverage this platform for water resource management applications.
You will learn Google Earth Engine programming by building the following 5 complete applications:
1. Surface Water Mapping
2. Precipitation Time Series Analysis
3. Land Use Land Cover Classification
4. Flood Mapping
5. Drought Monitoring
> Note: Certification and Support are only available for participants in our paid instructor-led classes.
[![Watch the video](https://img.youtube.com/vi/TcQ60TIqXf0/mqdefault.jpg)](https://www.youtube.com/watch?v=TcQ60TIqXf0&list=PLppGmFLhQ1HI0YeA5zQHxdNlmxihvBawF&index=2){target="_blank"}
[Watch the Video ↗](https://www.youtube.com/watch?v=TcQ60TIqXf0&list=PLppGmFLhQ1HI0YeA5zQHxdNlmxihvBawF&index=2){target="_blank"}
[Access the Presentation ↗](https://docs.google.com/presentation/d/1-PqksKb2QB8YJTQic5M80ZAsKh1Ld6OxOoO6BG77Uhg/edit?usp=sharing){target="_blank"}
# Setting up the Environment
## Sign-up for Google Earth Engine
If you already have a Google Earth Engine account, you can skip this step.
Visit our [GEE Sign-Up Guide](gee-sign-up.html) for step-by-step instructions.
## Get the Course Materials
The course material and exercises are in the form of Earth Engine scripts shared via a code repository.
1. [Click this link](https://code.earthengine.google.co.in/?accept_repo=users/ujavalgandhi/GEE-Water-Resources-Management) to open Google Earth Engine code editor and add the repository to your account.
2. If successful, you will have a new repository named `users/ujavalgandhi/GEE-Water-Resources-Management` in the *Scripts* tab in the *Reader* section.
3. Verify that your code editor looks like below
```{r echo=FALSE, fig.align='center', out.width='75%', fig.cap='Code Editor After Adding the Class Repository'}
knitr::include_graphics('images/gee_water_resources_management/repository.png')
```
If you do not see the repository in the *Reader* section, click *Refresh repository cache* button in your *Scripts* tab and it will show up.
```{r echo=FALSE, fig.align='center', out.width='50%', fig.cap='Refresh repository cache'}
knitr::include_graphics('images/common/repository_cache.png')
```
## Get the Course Videos
The course is accompanied by a set of videos covering the all the modules. These videos are recorded from our live instructor-led classes and are edited to make them easier to consume for self-study. We have 2 versions of the videos
### YouTube
We have created a YouTube Playlist with separate videos for each script and exercise to enable effective online-learning. [Access the YouTube Playlist ↗](https://www.youtube.com/playlist?list=PLppGmFLhQ1HI0YeA5zQHxdNlmxihvBawF){target="_blank"}
### Vimeo
We are also making combined full-length video for each module available on Vimeo. These videos can be downloaded for offline learning. [Access the Vimeo Playlist ↗](https://vimeo.com/showcase/10944117){target="_blank"}
\newpage
# Module 1: Google Earth Engine Fundamentals
In Module 1, you will gain the essential skills to find datasets, filter them to your region, clip them to your boundary, calculate remote sensing indices, extract water-bodies using thresholding techniques and export raster data.
[![Start Module 1 Videos](https://img.youtube.com/vi/jmCFVpYUcno/mqdefault.jpg)](https://www.youtube.com/watch?v=jmCFVpYUcno&list=PLppGmFLhQ1HI0YeA5zQHxdNlmxihvBawF&index=3){target="_blank"}
[Start Module 1 Videos ↗](https://www.youtube.com/watch?v=jmCFVpYUcno&list=PLppGmFLhQ1HI0YeA5zQHxdNlmxihvBawF&index=3){target="_blank"}
## 01. Hello World
This script introduces the basic Javascript syntax and the video covers the programming concepts you need to learn when using Earth Engine. To learn more, visit [Introduction to JavaScript for Earth Engine](https://developers.google.com/earth-engine/tutorials/tutorial_js_01) section of the Earth Engine User Guide.
The *Code Editor* is an Integrated Development Environment (IDE) for Earth Engine Javascript API. It offers an easy way to type, debug, run and manage code. Type the code below and click *Run* to execute it and see the output in the *Console* tab.
> Tip: You can use the keyboard shortcut *Ctrl+Enter* to run the code in the Code Editor
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='Hello World'}
knitr::include_graphics('images/gee_water_resources_management/hello_world.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F01b_Hello_World_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/01-Earth_Engine_Basics/01b_Hello_World_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F01c_Hello_World_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/01-Earth_Engine_Basics/01c_Hello_World_(exercise)')}
```
### Saving Your Work
When you modify any script for the course repository, you may want to save a copy for yourself. If you try to click the *Save* button, you will get an error message like below
```{r echo=FALSE, fig.align='center', out.width='75%'}
knitr::include_graphics('images/gee_water_resources_management/setup1.png')
```
This is because the shared class repository is a *Read-only* repository. You can click *Yes* to save a copy in your repository. If this is the first time you are using Earth Engine, you will be prompted to choose a *Earth Engine username*. Choose the name carefully, as it cannot be changed once created.
```{r echo=FALSE, fig.align='center', out.width='50%'}
knitr::include_graphics('images/gee_water_resources_management/setup2.png')
```
After entering your username, your home folder will be created. After that, you will be prompted to enter a new repository. A repository can help you organize and share code. Your account can have multiple repositories and each repository can have multiple scripts inside it. To get started, you can create a repository named *default*. Finally, you will be able to save the script.
## 02. Working with Image Collections
Most datasets in Earth Engine come as a `ImageCollection`. An ImageCollection is a dataset that consists of images takes at different time and locations - usually from the same satellite or data provider. You can load a collection by searching the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) for the *ImageCollection ID*. Search for the *Sentinel-2 Level 2A* dataset and you will find its id `COPERNICUS/S2_SR`. Visit the [Sentinel-2, Level 2A page](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR) and see *Explore in Earth Engine* section to find the code snippet to load and visualize the collection. This snippet is a great starting point for your work with this dataset. Click the **Copy Code Sample** button and paste the code into the code editor. Click *Run* and you will see the image tiles load in the map.
```{r echo=FALSE, fig.align='center', out.width='100%'}
knitr::include_graphics('images/gee_water_resources_management/image_collection1.png')
```
In the code snippet, You will see a function `Map.setCenter()` which sets the viewport to a specific location and zoom level. The function takes the X coordinate (longitude), Y coordinate (latitude) and Zoom Level parameters ranging from 1 (whole world) to 22 (pixel level). Replace the X and Y coordinates with the coordinates of your city and click *Run* to see the images of your city.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F02b_Image_Collections_(complete)){target="_blank"}
```{r echo=FALSE, fig.align='center', out.width='100%'}
knitr::include_graphics('images/gee_water_resources_management/image_collection2.png')
```
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/01-Earth_Engine_Basics/02b_Image_Collections_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F02c_Image_Collections_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/01-Earth_Engine_Basics/02b_Image_Collections_(complete)')}
```
## 03. Filtering Image Collections
The collection contains all imagery ever collected by the sensor. The entire collections are not very useful. Most applications require a subset of the images. We use **filters** to select the appropriate images. There are many types of filter functions, look at `ee.Filter...` module to see all available filters. Select a filter and then run the `filter()` function with the filter parameters.
We will learn about 3 main types of filtering techniques
* **Filter by metadata**: You can apply a filter on the image metadata using filters such as `ee.Filter.eq()`, `ee.Filter.lt()` etc. You can filter by PATH/ROW values, Orbit number, Cloud cover etc.
* **Filter by date**: You can select images in a particular date range using filters such as `ee.Filter.date()`.
* **Filter by location**: You can select the subset of images with a bounding box, location or geometry using the `ee.Filter.bounds()`. You can also use the drawing tools to draw a geometry for filtering.
After applying the filters, you can use the `.size()` function to check how many images match the filter criteria.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F03b_Filtering_Image_Collection_(complete)){target="_blank"}
```{r echo=FALSE, fig.align='center', out.width='100%'}
knitr::include_graphics('images/gee_water_resources_management/filters.png')
```
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/01-Earth_Engine_Basics/03b_Filtering_Image_Collection_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F03c_Filtering_Image_Collection_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/01-Earth_Engine_Basics/03c_Filtering_Image_Collection_(exercise)')}
```
## 04. Mosaics and Composites
The default order of the collection is by date. So when you display the collection, it implicitly creates a mosaic with the latest pixels on top. You can call `.mosaic()` on a ImageCollection to create a mosaic image from the pixels at the top (i.e) first image in the stack.
We can also create a composite image by applying selection criteria to each pixel from all pixels in the stack. Here we use the `.median()` function to create a composite where each pixel value is the median of all pixels values at each pixel from the stack for all matching bands.
> Tip: If you need to create a mosaic where the images are in a specific order, you can use the `.sort()` function to sort your collection by a property first.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F04b_Mosaics_and_Composites_(complete)){target="_blank"}
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='Mosaic vs. Median Composite'}
knitr::include_graphics('images/gee_water_resources_management/mosaic_median.png')
```
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/01-Earth_Engine_Basics/04b_Mosaics_and_Composites_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F04c_Mosaics_and_Composites_(exercise)){target="_blank"}
```{js eval=FALSE}
// Create a median composite for the year 2020 and load it to the map
// Compare both the composites to see the changes in your city
```
## 05. Feature Collections
Feature Collections are similar to Image Collections - but they contain *Features*, not images. They are equivalent to a Vector Layers in a GIS. We can load, filter and display Feature Collections using similar techniques that we have learned so far.
Search for *GAUL Second Level Administrative Boundaries* and load the collection. This is a global collection that contains all Admin2 boundaries. We can apply a filter using the `ADM1_NAME` property to get all Admin2 boundaries (i.e. Districts) from a state.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F05b_Feature_Collections_(complete)){target="_blank"}
```{r echo=FALSE, fig.align='center', out.width='100%'}
knitr::include_graphics('images/gee_water_resources_management/feature_collection.png')
```
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/01-Earth_Engine_Basics/05b_Feature_Collections_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F05c_Feature_Collections_(exercise)){target="_blank"}
```{js eval=FALSE}
// Add the admin2 layer to the map using Map.addLayer() function
// Go to your home city and inspect the layer to find the name of the region
// Use the ADM2_NAME property and apply a filter
// Display only the selected polygon on the map.
```
## 06. Clipping
It is often desirable to clip the images to your area of interest. You can use the `clip()` function to mask an image using geometry.
> While in Desktop softwares, clipping is used to remove the unnecessary portion of a large image to save computation time, but in the Earth Engine, clipping can *increase* the computation time. As described in the [Earth Engine Coding Best Practices](https://developers.google.com/earth-engine/guides/best_practices?hl=en#if-you-dont-need-to-clip,-dont-use-clip) guide, avoid clipping or do it at the very end of your process.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F06b_Clipping_(complete)){target="_blank"}
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='Full Image vs. Clipped Image'}
knitr::include_graphics('images/gee_water_resources_management/clipping.png')
```
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/01-Earth_Engine_Basics/06b_Clipping_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F06c_Clipping_(exercise)){target="_blank"}
```{js eval=FALSE}
// Add the GAUL admin boundary to the Map
// Search for your city and inspect the ADM2_NAME
// Replace the name with the ADM2_NAME of your selected region
// And display the clipped composite on the map.
```
## 07. Calculating Indices
Spectral Indices are central to many aspects of remote sensing. For almost all research/work, you will need to compute one spectral indices. The most commonly used formula for calculating an index is computing the *Normalized Difference* between 2 bands. Earth Engine provides a helper function `normalizedDifference()` to help calculate normalized indices, such as Normalized Difference Vegetation Index (NDVI) or Modified Normalized Difference Water Index (MNDWI).
Some indices - such as the Automated Water Extraction Index (AWEI) - require calculation using a more complex formula.In such cases, you can use the `expression()` function which allow you to to construct formula with common arithmetic operators. The script below shows how to implement common water-related indices in Earth Engine. Note that the AWEI formula expects the pixel values to be reflectances, so we need to apply a scaling factor of 0.0001 to convert the Sentinel-2 band values to reflectances.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F07b_Calculating_Indices_(complete)){target="_blank"}
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='RGB, MNDWI, NDVI and AWEI images'}
knitr::include_graphics('images/gee_water_resources_management/indices.png')
```
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/01-Earth_Engine_Basics/07b_Calculating_Indices_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F07c_Calculating_Indices_(exercise)){target="_blank"}
There is another version of AWEI called AWEIsh. This index is useful where there are mountain or building shadows. This works best where there are shadows but no bright reflective surfaces (snow, roof). The expression for AWEI (sh) is as follows
```AWEI (sh) = BLUE + 2.5*GREEN - 1.5*(NIR + SWIR1) - 0.25*SWIR2```
We have implemented both versions of AWEI in the script. Add them to the map and visualize both of them.
## 08. Computation on Images
Inspecting the MNDWI or AWEI index images, you will see that water pixels have a higher value than other pixels. If we wanted to extract those pixels, we can apply a threshold value to select all pixels above a certain value. The result will be a binary image with pixel values 1 or 0. For all the pixels that matched the condition, the resulting value will be 1, and for other pixels it will be 0. The conditions can be written using the *conditional operators* like greater than `.gt()`, lesser than `.lt()`, equal to `.eq()`, greater than or equal to `.gte()`, etc. We can also combine multiple layers to create a condition using the *boolean operators* like AND `.and()`, OR `.or()` functions. The script below shows how to implement static thresholding in Earth Engine.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F08b_Computation_on_Images_(complete)){target="_blank"}
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='Extracting Waterbodies using a Simple Threshold'}
knitr::include_graphics('images/gee_water_resources_management/threshold.png')
```
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/01-Earth_Engine_Basics/08b_Computation_on_Images_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F08c_Computation_on_Images_(exercise)){target="_blank"}
Replace the selected region with the region of your choice and and adjust the MNDWI thresholds to extract the waterbodies.
Try different thresholds and add images to the map to compare
- Hint: Try negative thresholds -0.1 and -0.2
- Hint: Try positive thresholds 0.1 and 0.2
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/01-Earth_Engine_Basics/08c_Computation_on_Images_(exercise)')}
```
## 09. Export
Earth Engine allows for exporting both vector and raster data to be used in an external program. Vector data can be exported as a `CSV` or a `Shapefile`, while Rasters can be exported as `GeoTIFF` files. We will now export the Sentinel-2 Composite as a GeoTIFF file.
During the export, we can export either a raw image or visualized image. The raw image will retain the original pixel values and is ideal if the image needs to be used for further analysis. The visualized image will generate an RGB visualization of the image. The visualized image will look exactly like you see it in Earth Engine with the visualization parameters, but original pixel values will be lost. The visualized image should not use it for analysis purposes.
> Tip: Code Editor supports autocompletion of API functions using the combination *Ctrl+Space*. Type a few characters of a function and press *Ctrl+Space* to see autocomplete suggestions. You can also use the same key combination to fill all parameters of the function automatically.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F09b_Export_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/01-Earth_Engine_Basics/09b_Export_(complete)')}
```
Once you run this script, the *Tasks* tab will be highlighted. Switch to the tab and you will see the tasks waiting. Click *Run* next to each task to start the process. On clicking the *Run* button, you will be prompted for a confirmation dialog. Verify the settings and click *Run* to start the export.
```{r echo=FALSE, fig.align='center', out.width='150%', fig.cap='Console, Tasks and Confirmation.'}
knitr::include_graphics('images/gee_water_resources_management/export_task.png')
```
Once the Export finishes, a GeoTiff file for each export task will be added to your Google Drive in the specified folder. You can download them and use it any program that reads GeoTiff files.
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='Visualized vs Raw'}
knitr::include_graphics('images/gee_water_resources_management/export_image.png')
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A01-Earth_Engine_Basics%2F09c_Export_(exercise)){target="_blank"}
Export the ```waterMndwi``` image to your drive.
# Module 2: Surface Water Mapping
In this Module, we will learn how to extract surface water polygons from a chosen watershed. We will be using in [HydroSheds](https://www.hydrosheds.org/page/hydrobasins) and [JRC - Global Surface Water](https://global-surface-water.appspot.com/#features) datasets. We will map the surface water for a chosen year, mask non-water pixels, apply morphological filters to remove fill holes and convert the raster image into polygons.
[![Start Module 2 Videos](https://img.youtube.com/vi/sUzt55WGArc/mqdefault.jpg)](https://www.youtube.com/watch?v=sUzt55WGArc&list=PLppGmFLhQ1HI0YeA5zQHxdNlmxihvBawF&index=21){target="_blank"}
[Start Module 2 Videos ↗](https://www.youtube.com/watch?v=sUzt55WGArc&list=PLppGmFLhQ1HI0YeA5zQHxdNlmxihvBawF&index=21){target="_blank"}
[View the Presentation ↗](https://docs.google.com/presentation/d/15EIaoRWc-obUrl2kqzlw_mYIaSAzYn7aOOE9SyU6XKc/edit?usp=sharing){target="_blank"}
## 01. Load Global Surface Water Data
Lets load the [JRC Global Surface Water Mapping Layers](https://developers.google.com/earth-engine/datasets/catalog/JRC_GSW1_3_GlobalSurfaceWater). This data contains the spatio-temporal distribution of surface water. It is a single image with 7 bands, where each band contains unique information. Let's use the `occurrence` band, which includes information on the frequency of the water present from 1984-2020. The pixel value ranges from 0-100, where 0 represents No trace of water in any year, and 100 represents water present in all 36 years.
Use the Inspector to find the frequency of water present in the location.
[Open in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A02-Surface_Water_Mapping%2F01b_Load_Global_Surface_Water_Data_(complete)){target="_blank"}
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='Frequency of water present over Bellandur lake'}
knitr::include_graphics('images/gee_water_resources_management/Load_Global_Surface_Water_Data_01.png')
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A02-Surface_Water_Mapping%2F01c_Load_Global_Surface_Water_Data_(exercise)){target="_blank"}
The `max_extent` band gives information on whether a pixel ever contained water or not, 0 represents the pixel has no water present in any of the months, and 1 represents the pixel has contained water in it for at least 1 month.
Load the `max_extent` band and visualize it with correct parameters.
```{js eval=FALSE}
// Create a map showing everywhere surface water was present.
// Select the 'max_extent' band and display the results
```
## 02. Create a Water Mask
Earth Engine has a `mask` function to represent the *No Data* values in an Image. Any masked pixel of an image will not be used for analysis or visualization. There are two types of masks `selfMask` and `updateMask.`
The `selfMask` will remove all the pixel values with *zero*. In the `max_extent` band visualization, we saw the pixel value is either 0 or 1, the pixel value with 0 contains no information, but the pixel value with 1 represents the water occurrence. So to remove the No Data pixel within the image, we can use the selfMask function. This will mask all pixel value with 0.
The `updateMask` will mask a *primary image* using a *mask image*. A mask image is an image with 0 1 pixel value. The primary image pixels overlaying with 0-pixel value in mask image will be set as No Data and masked out.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A02-Surface_Water_Mapping%2F02b_Create_a_Water_Mask_(complete)){target="_blank"}
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='Before applying Mask vs After applying Mask'}
knitr::include_graphics('images/gee_water_resources_management/water_mask.png')
```
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/02-Surface_Water_Mapping/02b_Create_a_Water_Mask_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A02-Surface_Water_Mapping%2F02c_Create_a_Water_Mask_(exercise)){target="_blank"}
The `seasonality` band gives information on the number of months water was present in a pixel. Pixel value ranges from 1 to 12, 1 represents water present for 1 month, and 12 represents water present for 12 months in a year.
Select all pixels in which water present for more than 5 months in a year.
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/02-Surface_Water_Mapping/02c_Create_a_Water_Mask_(exercise)')}
```
## 03. Find Lost Waterbodies
The `transition` band has water class changes between 1986 and 2020. It has [10 classes](https://developers.google.com/earth-engine/datasets/catalog/JRC_GSW1_3_GlobalSurfaceWater#bands) representing different changes, in which classes *3* and *6* represent *permanent* and *seasonal water loss*. We can calculate the total area of surface water lost by selecting both classes.
The *binary operator* `eq` is used to select a particular class and create a binary image representing the availability of the class. The *boolean operator* `or` is used to create a binary image where either class value is present.
[Open in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A02-Surface_Water_Mapping%2F03b_Find_Lost_Waterbodies_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/02-Surface_Water_Mapping/03b_Find_Lost_Waterbodies_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A02-Surface_Water_Mapping%2F03c_Find_Lost_Waterbodies_(exercise)){target="_blank"}
Use the `transition` band and find the total surface water gain.
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/02-Surface_Water_Mapping/03c_Find_Lost_Waterbodies_(exercise)')}
```
## 04. Get Yearly Water History
The [JRC Yearly Water Classification History](https://developers.google.com/earth-engine/datasets/catalog/JRC_GSW1_3_YearlyHistory) image collection contains the spatiotemporal map of surface water from 1984 to 2020. A total of 37 images represent 1 image for each year.
Let us filter this collection to visualize the surface water map of the year *2020*. This data contains 4 bands, where bands 2 and 3 indicate water presence.
> After filtering the Image Collection, the resultant would be a collection even if it contains just 1 image. We can use the function `.first()` to extract the particular image.
[Open in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A02-Surface_Water_Mapping%2F04b_Get_Yearly_Water_History_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/02-Surface_Water_Mapping/04b_Get_Yearly_Water_History_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A02-Surface_Water_Mapping%2F04c_Get_Yearly_Water_History_(exercise)){target="_blank"}
Use the `JRC Yearly Water Classification History` dataset and visualize the surface water map for the year *2010*.
```{js eval=FALSE}
// Get the surface water image for the year 2010
// Display it on the map
```
## 05. Locate a SubBasin
The [HydroSHEDS](https://www.hydrosheds.org/) is a series of data primarily developed by the *World Wildlife Fund*. It contains a global level geo-reference stream network, watershed boundaries, and drainage directions. We will use the `hydroBASINS,` a feature collection containing drainage basin boundaries. This data is created using SRTM DEM data. There are multiple levels of hydroBASINS, ranging from 1 to 11. In level 1, the basin boundaries are delineated as huge groups. Moving levels up, these boundaries will be sub-divided into smaller boundaries.
We will use the Level 7 hydroBASINS feature collection to filter and locate a sun-basin called *Arkavathy*. The hydroBASINS doesn't contain basin names, so basins should be visually located and filtered using the *HYBAS_ID* property to filter a particular basin boundary.
[Open in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A02-Surface_Water_Mapping%2F05b_Locate_a_SubBasin_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/02-Surface_Water_Mapping/05b_Locate_a_SubBasin_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A02-Surface_Water_Mapping%2F05c_Locate_a_SubBasin_(exercise)){target="_blank"}
Using the Level 7 hydroBASINS, locate and filter a watershed basin in your region of interest.
```{js eval=FALSE}
// Add the hydrobasins layer to the map
// Zoom to your region on interest and inspect the layer
// Find the id for a sub basin of interest and add it to the map.
```
## 06. Create a Surface Water Map
A raster image output can be post-processed using morphological operations to create a clean-looking surface map. There are different types of operations like *Morphological Opening*, *Morphological Closing*, and *Majority Filtering*.
> Warning: We are processing the image here to clean it up to create a mapping product, but this changes the structure of the image and alters the statistics. Skip this step if your goal is to detect water pixels or compute the surface water area.
* The opening operation can reduce the salt and pepper noise in the image.
* The closing operation can fill holes and create a complete class.
* A majority filter will smooth the image. This operation should be used for mapping purposes only and not used while calculating statistics, as it will significantly alter the result.
Earth Engine has many functions to perform morphological operations under `ee.Image`. Let's use the `Max_extent` band from Global Surface Water and fill holes to create a surface water map. An *Erosion* operation follows a *Dilation* operation to perform a closing operation, which translates as the *focalMin* function chained with *focalMax* in the earth engine. Different *kernelType* are available, let's use the *Square* kernel with *30* as search *radius* as the JRC's Global Surface Water spatial resolution is 30m. We can also define a custom kernel if the required kernel is unavailable in kernelType.
[Open in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A02-Surface_Water_Mapping%2F06b_Create_a_Surface_Water_Map_(complete)){target="_blank"}
```{r echo=FALSE, fig.align='center', out.width='150%', fig.cap='Before Operation vs After Operation'}
knitr::include_graphics('images/gee_water_resources_management/morphological_operation.png')
```
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/02-Surface_Water_Mapping/06b_Create_a_Surface_Water_Map_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A02-Surface_Water_Mapping%2F06c_Create_a_Surface_Water_Map_(exercise)){target="_blank"}
By default, the total iteration is 1. We can increase it as required, so the kernel will pass through the image to perform the operation as many times as required.
Set the iteration parameter to 2 and execute the morphological closing operation.
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/02-Surface_Water_Mapping/06c_Create_a_Surface_Water_Map_(exercise)')}
```
## 07. Convert Raster to Vector
After creating a final raster map, we can vectorize it. The `reduceToVectors` function should be used with *countEvery* reducer to convert a raster to a vector. This reducer will connect all linked pixels of the same class into a single feature and return a feature collection. By default, the connectedness of a pixel is checked in cardinal directions only. To check the connectedness of a pixel in the diagonal direction, *eightConnected* should be set as *true*.
[Open in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A02-Surface_Water_Mapping%2F07b_Convert_Raster_to_Vector_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/02-Surface_Water_Mapping/07b_Convert_Raster_to_Vector_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A02-Surface_Water_Mapping%2F07c_Convert_Raster_to_Vector_(exercise)){target="_blank"}
The final feature collection will contain the class value from the pixel as the *label* property. Since the raster is a binary image with 0 - 1 value, the label with value 1 will represent the water bodies.
Use the *eq* filter and filter the water bodies alone.
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/02-Surface_Water_Mapping/07c_Convert_Raster_to_Vector_(exercise)')}
```
# Module 3: Precipitation Time Series Analysis
The main advantage of the gridded precipitation datasets is that they offer a consistent long-term time-series. We will cover the basics of gridded rainfall datasets, how to aggregate them to the requirement temporal resolution, prepare a time-series and perform pixel-wise trend analysis.
But to fully leverage the computation power of Earth Engine for our analysis, we must first learn about techniques for writing efficient parallel computing code. The Earth Engine API uses [Map/Reduce](https://en.wikipedia.org/wiki/MapReduce) paradigm for parallel computing.
<!-- Map/Reduce Video -->
[![Start Module 3 Videos](https://img.youtube.com/vi/frYZf17QyIc/mqdefault.jpg)](https://www.youtube.com/watch?v=frYZf17QyIc&list=PLppGmFLhQ1HI0YeA5zQHxdNlmxihvBawF&index=37){target="_blank"}
[Start Module 3 Videos ↗](https://www.youtube.com/watch?v=frYZf17QyIc&list=PLppGmFLhQ1HI0YeA5zQHxdNlmxihvBawF&index=37){target="_blank"}
[View the Presentation ↗](https://docs.google.com/presentation/d/1F_yRyBkItQdpbm-TXOTc4CkMXxynulfKY2p1TG0xS-g/edit?usp=sharing){target="_blank"}
----
<!-- Precipitation Time-Series Video -->
[![Watch the video](https://img.youtube.com/vi/t73sL6DPiiY/mqdefault.jpg)](https://www.youtube.com/watch?v=t73sL6DPiiY&list=PLppGmFLhQ1HI0YeA5zQHxdNlmxihvBawF&index=42){target="_blank"}
[Watch the Video ↗](https://www.youtube.com/watch?v=t73sL6DPiiY&list=PLppGmFLhQ1HI0YeA5zQHxdNlmxihvBawF&index=42){target="_blank"}
[View the Presentation ↗](https://docs.google.com/presentation/d/1G-v9Nz90DGGQ2OfTPxwD5j-HspPcIYUu9UB-nkNnGn4/edit?usp=sharing){target="_blank"}
## 01. Mapping a Function
This script introduces the basics of the Earth Engine API. Here we map a list of objects over a function to perform a task on all the objects. While defining a function, it should return a result after computation, which can be stored in a variable. To learn more, visit the [Earth Engine Objects and Methods](https://developers.google.com/earth-engine/tutorial_js_02) section of the Earth Engine User Guide.
Apart from other regular strings and numbers, the earth engine can understand dates. Under `ee.Date` there are many functions by which dates can be defined or converted from one format to another.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A03-Time_Series_Analysis%2F01b_Mapping_a_Function_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/03-Time_Series_Analysis/01b_Mapping_a_Function_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A03-Time_Series_Analysis%2F01c_Mapping_a_Function_(exercise)){target="_blank"}
Define the function `createDate`, map the `weeks` list as input. The function should return dates incremented by the week number.
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/03-Time_Series_Analysis/01c_Mapping_a_Function_(exercise)')}
```
## 02. Reducers
A *Reduce* operation allows you to compute statistics on a large amount of inputs. In Earth Engine, you need to run reduction operation when creating composites, calculating statistics, doing regression analysis etc. The Earth Engine API comes with a large number of built-in reducer functions (such as `ee.Reducer.sum()`, `ee.Reducer.histogram()`, `ee.Reducer.linearFit()` etc.) that can perform a variety of statistical operations on input data. You can run reducers using the `reduce()` function. Earth Engine supports running reducers on all data structures that can hold multiple values, such as Images (reducers run on different bands), ImageCollection, FeatureCollection, List, Dictionary etc. The script below introduces basic concepts related to reducers.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A03-Time_Series_Analysis%2F02b_Reducers_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/03-Time_Series_Analysis/02b_Reducers_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A03-Time_Series_Analysis%2F02c_Reducers_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/03-Time_Series_Analysis/02c_Reducers_(exercise)')}
```
## 03. Calculating Total Rainfall
The CHIRPS Pentad is 5 days composite of rainfall at ~6 km spatial resolution. To compute this data, both satellite and grounds values are considered. To read more about the methodology, visit [nature.com](https://www.nature.com/articles/sdata201566)
Using this image collection, lets filter all the images for 2017. To get a yearly rainfall we can reduce the collection using `reduce` function with *sum* reducer. This will return a single global image where each pixel represent the total annual rainfall value in *mm* at that location. Now to get a annual average rainfall at a particular region of interest, we can do a `reduceRegions` with a *mean* reducer over the region. This reducer will reduce the region's image and return a dictionary. The dictionary will contain the average value of all the bands in the image, which can be extracted using the *get* function.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A03-Time_Series_Analysis%2F03b_Calculating_Total_Rainfall_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/03-Time_Series_Analysis/03b_Calculating_Total_Rainfall_(complete)')}
```
Output
```
Average rainfall across ROI :
1345.867775034789
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A03-Time_Series_Analysis%2F03c_Calculating_Total_Rainfall_(exercise)){target="_blank"}
Update the date rage for monsoon season(1 June - 30 September) in India.
```{js eval=FALSE}
// Update the script to calculate total rainfall for the monsoon season
// Monsoon season in India is from 1 June - 30 September
```
## 04. Aggregating Time Series
In the previous exercise, we aggregated to get the average rainfall across a region. Let's compute a time series representing the total rainfall of each month in 2019.
Earth Engine has a function called `ee.Date.fromYMD` to create a date from *Year*, *Month*, and *Date*. Using this function and `.advance()`, we can create the filter date to filter the image collection to a particular month. Then with `reduce` function with *sum* as reducer, the monthly image collection is aggregated to the monthly total image. This newly created image won't have any properties. Hence using the `.set()` function, we have to assign the *Year*, *Month*, *system:time_start*, and *system:time_end* properties. With the above procedure in the sequence, we can create a function to input the month's number and return the monthly total precipitation image.
We can create the month's list using `ee.List.sequence` and map it to the function built. Since the mapped object is of type List, the resultant will also be a list with 12 images. This list of images can be converted back as Image Collection using `ee.ImageCollection.fromYMD`.
Once we have the collection print, it will contain 12 images representing the month's total precipitation.
>The *system:time_start* is a unique property that the earth engine can natively understand. It is the [Unix Timestamp](https://en.wikipedia.org/wiki/Unix_time) that is used to create a time series chart.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A03-Time_Series_Analysis%2F04b_Aggregating_Time_Series_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/03-Time_Series_Analysis/04b_Aggregating_Time_Series_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A03-Time_Series_Analysis%2F04c_Aggregating_Time_Series_(exercise)){target="_blank"}
Filter the `monthlyCollection` for the months June, July, August and September.
```{js eval=FALSE}
// Apply a filter to select images for the months
// June, July, August and September
// Print the collection to verify
```
## 05. Charting Monthly Rainfall
Now we can put together all the skills we have learned so far - filter, map, and reduce to create a chart of monthly total rainfall in the year 2019 over a region. Earth Engine API supports charting functions based on the Google Chart API. There are various charts to use, from which we use the `ui.Chart.image.series()` function to create a time-series chart.
Image series chart accepts an *image collection*, *geometry*, *scale*, and *reducer*. The geometry in the region of interest, reducer in the reduction operation the region of interest should be aggregated if the geometry is a polygon. Scale is the resolution at which the image should be reduced. Using `.setOptions`, we can customize the chart to our needs.
Charting itself is vast, and all function are self explanatory. Google Earth Engine documentation provides all types of [charting examples](https://developers.google.com/earth-engine/guides/charts_overview.)
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A03-Time_Series_Analysis%2F05b_Charting_Monthly_Rainfall_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/03-Time_Series_Analysis/05b_Charting_Monthly_Rainfall_(complete)')}
```
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='2019 - Monthly rainfall'}
knitr::include_graphics('images/gee_water_resources_management/charting_monthly_rainfall.png')
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A03-Time_Series_Analysis%2F05c_Charting_Monthly_Rainfall_(exercise)){target="_blank"}
Change the geometry to your location, compute the monthly total rainfall. Download the timeseries chart generated.
```{js eval=FALSE}
// Create a chart of monthly rainfall at your selected location
// print the chart and download it as a PNG
```
## 06. Import
You can import vector or raster data into Earth Engine. We will now import a shapefile of [Taluk](https://kgis.ksrsac.in/kgis/downloads.aspx) for a state in India. Unzip the `Taluk.rar` into a folder on your computer. In the Code Editor, go to *Assets → New → Table Upload → Shape Files*. Select the `.cpj`, `.sbn`, `.shp`, `.shx`, `.dbf`and .`prj` files. Enter `Taluk_Boundary` as the *Asset Name* and click *Upload*. In the *Tasks* tab you can see the progress of the upload. Once the ingestion is complete you will have a new asset in the *Assets* tab. The shapefile will be imported as a Feature Collection in Earth Engine. Select the `Taluk_Boundary` asset and click *Import*. You can then visualize the imported data.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A03-Time_Series_Analysis%2F06b_Import_(complete)){target="_blank"}
```{r echo=FALSE, fig.align='center', out.width='150%', fig.cap='Importing a Shapefile'}
knitr::include_graphics('images/gee_water_resources_management/upload.png')
```
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/03-Time_Series_Analysis/06b_Import_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A03-Time_Series_Analysis%2F06c_Import_(exercise)){target="_blank"}
Explore the uploaded Feature Collection, `SHAPE_STAr` property contains the area in meter_square, using `addArea` function area is converted into kilometer_square and stored as `area_sqkm`. Using this property filter all regions with area greater than 1000 sq km.
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/03-Time_Series_Analysis/06c_Import_(exercise)')}
```
## 07. Zonal Statistics
Now that we have uploaded a shapefile with many Taluk boundaries let us calculate the mean rainfall for each district. Before in `reduceRegion`, we learned to reduce a single image over a whole geometry. But by using the `reduceRegions`, we can reduce the image for each geometry in the feature collection. This function will return a *Feature Collection*, which contains all the features with an additional property of the reduced value.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A03-Time_Series_Analysis%2F07b_Zonal_Statistics_(complete)){target="_blank"}
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='Zonal Statistics'}
knitr::include_graphics('images/gee_water_resources_management/zonal_statistics.png')
```
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/03-Time_Series_Analysis/07b_Zonal_Statistics_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A03-Time_Series_Analysis%2F07c_Zonal_Statistics_(exercise)){target="_blank"}
Write an export function to export the Feature Collection as a CSV file.
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/03-Time_Series_Analysis/07c_Zonal_Statistics_(exercise)')}
```
## 08. Trend Analysis
Trend Analysis is a technique that is used to find the pattern. Let us do a Non-Parametric Trend Analysis using the [Sen Slope](https://en.wikipedia.org/wiki/Theil%E2%80%93Sen_estimator) technique to find the pattern of rainfall over time.
The sens slope is a reduction operation that expects two-band X and Y. The X is the constant band with value year, and the Y is the total precipitation of that pixel in that year. After creating the image collection in this format we can use the `ee.Reducer.sensSlope()` with the collection to compute the slope at each year.
This function returns an image with a positive pixel value representing the increase in precipitation and vice-versa.
> An advantage of doing trend analysis in earth engine is computing pre-pixel calculation other wise which would be computation intestiive task to perform.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A03-Time_Series_Analysis%2F08b_Trend_Analysis_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/03-Time_Series_Analysis/08b_Trend_Analysis_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A03-Time_Series_Analysis%2F08c_Trend_Analysis_(exercise)){target="_blank"}
The trend analysis is done for a particular season. Change the filter dates to compute the annual precipitation trend.
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/03-Time_Series_Analysis/08c_Trend_Analysis_(exercise)')}
```
# Module 4: Land Use Land Cover Classification
Supervised classification is one of the most popular machine learning technique used in remote sensing. Google Earth Engine is uniquely suited for supervised classification at a large scale and offers a flexible data model that allows you to easily incorporate variables from multiple data sources. The interactive nature of Earth Engine development allows for iterative development of supervised classification workflows by combining many different datasets into the model. This module covers basic supervised classification workflow, accuracy assessment, and area calculation.
[![Start Module 4 Videos](https://img.youtube.com/vi/G1TpZ7SrQQc/mqdefault.jpg)](https://www.youtube.com/watch?v=G1TpZ7SrQQc&list=PLppGmFLhQ1HI0YeA5zQHxdNlmxihvBawF&index=56){target="_blank"}
[Start Module 4 Videos ↗](https://www.youtube.com/watch?v=G1TpZ7SrQQc&list=PLppGmFLhQ1HI0YeA5zQHxdNlmxihvBawF&index=56){target="_blank"}
[View the Presentation ↗](https://docs.google.com/presentation/d/16jsxRrYG9RddvlUfa6Myt3_mc-ye4GgDcvYK6n7IgkU/edit?usp=sharing){target="_blank"}
## 01. Basic Supervised Classification
We will learn the technique to do a basic land cover classification using training points collected using the Code Editor with the help of the High-Resolution base map imagery provided by Google Maps. Even if no field data is available for training the model, this method is very effective in generating high-quality classification samples anywhere in the world. The goal is to classify Sentinel 2A pixel into one of the following classes - *urban, bare, water,* or *vegetation*. Using the drawing tools in the code editor lets us create 4 new feature collections with points representing pixels of each class. Each feature collection will be created with a property `landcover` where each collection has values of 0, 1, 2, or 3, representing urban, bare, water, or vegetation, respectively. We use these collected samples to train a *Random Forest* classifier and apply it to all the image pixels to create a land cover image with 4 classes.
> Fun fact: The classifiers in Earth Engine API have names starting with **smile** - such as `ee.Classifier.smileRandomForest()`. The *smile* part refers to the [Statistical Machine Intelligence and Learning Engine (SMILE)](https://haifengl.github.io/index.html) JAVA library which is used by Google Earth Engine to implement these algorithms.
[Open in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A04-Land_Use_Land_Cover_Classification%2F01d_Basic_Supervised_Classification_(noimport)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/04-Land_Use_Land_Cover_Classification/01d_Basic_Supervised_Classification_(noimport)')}
```
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='Supervised Classification Output'}
knitr::include_graphics('images/gee_water_resources_management/classified.png')
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A04-Land_Use_Land_Cover_Classification%2F01c_Basic_Supervised_Classification_(exercise)){target="_blank"}
Select and city of your choice from `urbanAreas` data. Create Feature collection with property `landcover` and collect training points for every four classes *urban, bare, water*, and *vegetation*. Then use the code to classify and create a land cover of the city.
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/04-Land_Use_Land_Cover_Classification/01c_Basic_Supervised_Classification_(exercise)')}
```
## 02. Accuracy Assessment
It is important to get a quantitative estimate of the accuracy of the classification. To do this, a common strategy is to divide your training samples into 2 random fractions - one used for *training* the model and the other for *validation* of the predictions. Once a classifier is trained, it can be used to classify the entire image. We can then compare the classified values with the ones in the validation fraction. We can use the `ee.Classifier.confusionMatrix()` method to calculate a *Confusion Matrix* representing expected accuracy.
> Don't get carried away tweaking your model to give you the highest validation accuracy. You must use both qualitative measures (such as visual inspection of results) along with quantitative measures to assess the results.
[Open in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A04-Land_Use_Land_Cover_Classification%2F02b_Accuracy_Assessment_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/04-Land_Use_Land_Cover_Classification/02b_Accuracy_Assessment_(complete)')}
```
Output
```
Confusion Matrix
0: [41,4,0,0]
1: [3,43,0,0]
2: [0,0,48,3]
3: [0,0,0,37]
Test Accuracy
0.9441340782122905
```
## 03. Improving the Classification
The Earth Engine data-model is especially well suited for machine learning tasks because of its ability to easily incorporate data sources of different spatial resolutions, projections and data types together By giving additional information to the classifier, it is able to separate different classes easily. Here we take the same example and augment it with the following techniques
* *Apply Cloud Masking*
* *Add Spectral Indices*: We add bands for different spectral indices such as - NDVI, NDBI, MNDWI and BSI.
* *Add Elevation and Slope*: We also add slope and elevation bands from the ALOS DEM.
* *Normalize the Inputs*: Machine learning models work best when all the inputs have the same scale. We will divide each band with the maximum value. This method ensures that all input values are between 0-1.
Our training features have more parameters and contain values of the same scale. The result is a much improved classification.
[Open in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A04-Land_Use_Land_Cover_Classification%2F03b_Improving_the_Classification_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/04-Land_Use_Land_Cover_Classification/03b_Improving_the_Classification_(complete)')}
```
Output
```
Confusion Matrix
0: [41,3,0,0]
1: [3,43,0,0]
2: [0,0,49,2]
3: [0,0,0,37]
Test Accuracy
0.9550561797752809
```
## 04. Exporting Classification Results
When working with complex classifiers over large regions, you may get a *User memory limit exceeded* or *Computation timed out* error in the Code Editor. The reason for this is that there is a fixed time limit and smaller memory allocated for code that is run with the *On-Demand Computation* mode. For larger computations, you can use the *Batch* mode with the `Export` functions. Exports run in the background and can run longer than 5-minutes time allocated to the computation code run from the Code Editor. This allows you to process very large and complex datasets. Here's an example showing how to export your classification results to Google Drive.
> We can only export Images or FeatureCollections. What if you wanted to export a number that is the result of a long computation? A useful *hack* is to create a FeatureCollection with just 1 feature containing `null` geometry and a property containing the number you want to export.
[Open in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A04-Land_Use_Land_Cover_Classification%2F04b_Exporting_Classification_Results_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/04-Land_Use_Land_Cover_Classification/04b_Exporting_Classification_Results_(complete)')}
```
```{r echo=FALSE, fig.align='center', out.width='50%', fig.cap='Exported Classification Accuracy'}
knitr::include_graphics('images/gee_water_resources_management/export_accuracy.png')
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A04-Land_Use_Land_Cover_Classification%2F04c_Exporting_Classification_Results_(exercise)){target="_blank"}
It is also a good idea to export the classified image as an Asset. This will allows you to import the classified image in another script without running the whole classification workflow. Use the `Export.image.toAsset()` function to export the classified image as an asset.
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/04-Land_Use_Land_Cover_Classification/04c_Exporting_Classification_Results_(exercise)')}
```
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='Exported Classified Asset'}
knitr::include_graphics('images/gee_water_resources_management/export_classification.png')
```
## 05. Using Existing Landcover Datasets
One of the ambitious projects was creating a global landcover data with many classes for many years. This type of data is essential as in expect few countries, the landcover data of terrain is not available / not shared publicly by the local governments. Hence creating a global land cover has been attempted by a few organizations One among them is *European Space Agency*. The ESA has created the 10m global landcover called [WorldCover](https://esa-worldcover.org/en) with 10 classes. At present, this data is available for the year 2020 and, ESA has promised to develop and release this data every year following 2020. [Watch the launch event](https://vimeo.com/637205140) to know more about this data and the methodology used to create this.
We can use the `eq` operator to extract a particular class, extract the water class, and create a surface water map for the Arkavathy region.
[Open in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A04-Land_Use_Land_Cover_Classification%2F05b_Using_Existing_Landcover_Datasets_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/04-Land_Use_Land_Cover_Classification/05b_Using_Existing_Landcover_Datasets_(complete)')}
```
```{r echo=FALSE, fig.align='center', out.width='75%', fig.cap='WorldView'}
knitr::include_graphics('images/gee_water_resources_management/esa_worldcover.png')
```
### Exercise
[Open in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A04-Land_Use_Land_Cover_Classification%2F05c_Using_Existing_Landcover_Datasets_(exercise)){target="_blank"}
Use the WorldCover data and extract the `Cropland` class for Arkavathy region. Then add it to map with *green* palette.
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/04-Land_Use_Land_Cover_Classification/05c_Using_Existing_Landcover_Datasets_(exercise)')}
```
## 06. Calculating Area
Now that we have extracted the open water from WorldCover, we will learn how to calculate the area for pixels in each class. Calculating area for features is done using the `area()` function and for images using the `ee.Image.pixelArea()` function. The `ee.Image.pixelArea()` function creates an image where each pixel's value is the area of the pixel. We multiply this pixel area image with our image and sum up the area using the `reduceRegion()` function.
> The `ee.Image.pixelArea()` function uses a custom equal-area projection for area calculation. The result is area in square meters regardless of the projection of the input image. [Learn more](https://groups.google.com/g/google-earth-engine-developers/c/Ccaorx-obVw/m/_ZQdP2wVAgAJ)
[Open in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A04-Land_Use_Land_Cover_Classification%2F06b_Calculating_Area_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/04-Land_Use_Land_Cover_Classification/06b_Calculating_Area_(complete)')}
```
Output
```
Total basin Area(sqkm)
4178
Total water area in the basin(sqkm)
19
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A04-Land_Use_Land_Cover_Classification%2F06c_Calculating_Area_(exercise)){target="_blank"}
Extract the area value as a number and convert it as hectares.
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/04-Land_Use_Land_Cover_Classification/06c_Calculating_Area_(exercise)')}
```
# Module 5: Flood Mapping
This module covers the change detection techniques for mapping floods. We will work with Sentinel-1 dataset and calculate the flooded area during the [2018 Kerala Floods](https://en.wikipedia.org/wiki/2018_Kerala_floods) in Ernakulam district in India.
Sentinel-1 is an active remote sensing platform that uses the microwave C-band to collect data. The main advantage of using microwave data is that it can penetrate through clouds and capture reflectance value both day and night since it is not dependent on Sunlight for reflectance. The spatial resolution of this data is 10m, and the temporal resolution varies between 6-12 days, depending on the location.
[![Start Module 5 Videos](https://img.youtube.com/vi/JWq_WepA5DY/mqdefault.jpg)](https://www.youtube.com/watch?v=JWq_WepA5DY&list=PLppGmFLhQ1HI0YeA5zQHxdNlmxihvBawF&index=69){target="_blank"}
[Start Module 5 Videos ↗](https://www.youtube.com/watch?v=JWq_WepA5DY&list=PLppGmFLhQ1HI0YeA5zQHxdNlmxihvBawF&index=69){target="_blank"}
[View the Presentation ↗](https://docs.google.com/presentation/d/1w1bTP49jI4LbHYTtQzEg4yytGGbCx_l5bhTisITXxKY/edit?usp=sharing){target="_blank"}
## 01. Load and Filter Sentinel-1 Data
We have learned basic skills to search for a dataset and filter it to a date range and location. Let us load the [Sentinel-1 C-band SAR log scaling ](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S1_GRD) dataset and filter the collection to flooding event time period. Filter the collection to the Ernakulam region.
Each image will have 3 bands *VV*, *VH*, and *angle*. Most research results say *VH - (vertical transmit and horizontal receive)* is best for detecting floods as water has low reflectance in the VH band and is easy to detect. Lets us select the VH band, clip it to the ROI and display it in Map with the appropriate visualization parameter.
[Open in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A05-Flood_Mapping%2F01b_Load_and_Filter_Sentinel-1_Data_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/05-Flood_Mapping/01b_Load_and_Filter_Sentinel-1_Data_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A05-Flood_Mapping%2F01c_Load_and_Filter_Sentinel-1_Data_(exercise)){target="_blank"}
To detect the flooded regions, we need 2 collections, one before and another after flood occurrence. A before image and an after image has been created. Select the *VH* band from the images and add both images to the map canvas.
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='VH single band visualization'}
knitr::include_graphics('images/gee_water_resources_management/flood_vh.png')
```
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/05-Flood_Mapping/01c_Load_and_Filter_Sentinel-1_Data_(exercise)')}
```
## 02. Visualize RGB Composites
We visualized the VH band as a single band image in the previous exercise. We can also visualize a SAR image as a multi-band RGB image. The usual practice is using the *VV* band in the red channel, the *VH* band in the green channel, and the *VV/VH* in the blue channel.
Three bands have different min-max values, but a single number for min-max value in visualization will not be correct. So we can pass a list of numbers, each representing each band's min-max value in Red Green Blue order, respectively.
[Open in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A05-Flood_Mapping%2F02b_Visualize_RGB_Composites_(complete)){target="_blank"}
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='RGB multi band visualization'}
knitr::include_graphics('images/gee_water_resources_management/flood_rgb.png')
```
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/05-Flood_Mapping/02b_Visualize_RGB_Composites_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A05-Flood_Mapping%2F02c_Visualize_RGB_Composites_(exercise)){target="_blank"}
We have learned to visualize a multi-band image using *VV*, *VH*, and *VV/VH* bands. Let us visualize the change by creating a composite image with *VH - before image*, *VH - after image*, and *VH - before image*. This visualization can effectively identify the before and after images’ changes.
To create this visualization, select the particular bands from each image and concatenate the three bands in the same order using `ee.Image.cat` function, use the visualization parameter as min: -25 and max: -8 and add it to the canvas.
```{r echo=FALSE, fig.align='center', out.width='75%', fig.cap='Change visualization'}
knitr::include_graphics('images/gee_water_resources_management/flood_change.png')
```
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/05-Flood_Mapping/02c_Visualize_RGB_Composites_(exercise)')}
```
## 03. Apply Speckle Filter
Any SAR image will be with noise. Speckle is like salt and pepper noise in the image. Before performing any operation, a filter is applied over the image to smooth it and reduce the noise. There are many types of filters. *Refined Lee* filter is a more scientific approach in filtering the noise.
The raw image should be passed into the `Refined Lee` function. Hence, the log image is converted to raw using the `toNatural` function. The resulting image from Refined Lee is again converted to log scale by passing it `toDB` function.
> Guido Lemoine implemented the Refined Lee filter in GEE. Keeping the Speckle filtering function at the end of any SAR processing script can be very handy for conversions and save time.
[Open in Code Editor ↗](https://code.earthengine.google.com/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A05-Flood_Mapping%2F03b_Apply_Speckle_Filter_(complete)){target="_blank"}
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='Speckle Filter'}
knitr::include_graphics('images/gee_water_resources_management/flood_speckle.png')
```
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/05-Flood_Mapping/03b_Apply_Speckle_Filter_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FGEE-Water-Resources-Management%3A05-Flood_Mapping%2F03c_Apply_Speckle_Filter_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/gee_water_resources_management/05-Flood_Mapping/03c_Apply_Speckle_Filter_(exercise)')}
```
## 04. Apply a Threshold