-
Notifications
You must be signed in to change notification settings - Fork 18
/
end-to-end-gee.Rmd
1300 lines (746 loc) · 80.2 KB
/
end-to-end-gee.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: "End-to-End Google Earth Engine (Full Course)"
subtitle: "A hands-on introduction to applied remote sensing using Google Earth Engine."
author: "Ujaval Gandhi"
fontsize: 12pt
output:
# pdf_document:
# latex_engine: xelatex
# toc: yes
# toc_depth: 3
# fig_caption: false
# word_document:
# toc: false
# fig_caption: false
html_document:
df_print: paged
highlight: pygments
includes:
after_body: comment.html
toc: yes
toc_depth: 3
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}
---
\newpage
***
```{r echo=FALSE, fig.align='center', out.width='75%', out.width='250pt'}
knitr::include_graphics('images/spatial_thoughts_logo.png')
```
***
\newpage
# Introduction
Google Earth Engine is a cloud-based platform that enables large-scale processing of satellite imagery to detect changes, map trends, and quantify differences on the Earth’s surface. This course covers the full range of topics in Earth Engine to give the participants practical skills to master the platform and implement their remote sensing projects.
[![View Presentation](images/end_to_end_gee/course_overview.png){width="400px"}](https://docs.google.com/presentation/d/1q8HRDTqgQEp3Hmi8IG0T7djPLTC1wRig3jXrwFTmoVE/edit?usp=sharing){target="_blank"}
[View the Presentation ↗](https://docs.google.com/presentation/d/1q8HRDTqgQEp3Hmi8IG0T7djPLTC1wRig3jXrwFTmoVE/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.
## Complete the Class Pre-Work
This class needs about 2-hours of pre-work. Please watch the following videos to get a good understanding of remote sensing and how Earth Engine works. Videos are available online and can be streamed using the video links below.
### Introduction to Remote Sensing
This video introduces the remote sensing concepts, terminology and techniques.
[![Video](images/end_to_end_gee/intro_to_remote_sensing.png){width="400px"}](https://www.youtube.com/watch?v=xAyNu9HbK8s){target="_blank"}
- [Watch the Video](https://www.youtube.com/watch?v=xAyNu9HbK8s){target="_blank"}
- [View the Presentation ↗](https://docs.google.com/presentation/d/1opRKXIV8XSMa5h7Gqw10KXY5nW7_khfdiBmyDEcylUE/edit?usp=sharing){target="_blank"}
### Introduction to Google Earth Engine
This video gives a broad overview of Google Earth Engine with selected case studies and application. The video also covers the Earth Engine architecture and how it is different than traditional remote sensing software.
[![Video](images/end_to_end_gee/intro_to_gee.png){width="400px"}](https://www.youtube.com/watch?v=kpfncBHZBto){target="_blank"}
- [Watch the Video](https://www.youtube.com/watch?v=kpfncBHZBto){target="_blank"}
- [View the Presentation ↗](https://docs.google.com/presentation/d/1RMyufK1bD7_Mj0b0Pub-CADiBsmT8LqyGMXIgem3UW4/edit?usp=sharing){target="_blank"}
### Take the Quizes
After you watch the videos, please complete the following 2 Quizzes
1. Quiz-1 [Remote Sensing Fundamentals](https://forms.gle/BoaYhMgpjwNn3amS8){target="_blank"}.
2. Quiz-2 [Google Earth Engine Fundamentals](https://forms.gle/pGVShApd9f6uVYR89){target="_blank"}.
## 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/End-to-End-GEE) 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/End-to-End-GEE` 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/end_to_end_gee/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')
```
\newpage
# Module 1: Earth Engine Basics
Module 1 is designed to give you basic skills to be able to find datasets you need for your project, filter them to your region of interest, apply basic processing and export the results. Mastering this will allow you to start using Earth Engine for your project quickly and save a lot of time pre-processing the data.
## 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.
[![Video](images/end_to_end_gee/intro_to_javascript.png){width="400px"}](https://www.youtube.com/watch?v=RV3Sv5iogHs){target="_blank"}
- [Watch the Video](https://www.youtube.com/watch?v=RV3Sv5iogHs){target="_blank"}
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='75%', fig.cap='Hello World'}
knitr::include_graphics('images/end_to_end_gee/hello_world.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A01-Earth-Engine-Basics%2F01b_Hello_World_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/01-Earth-Engine-Basics/01b_Hello_World_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A01-Earth-Engine-Basics%2F01c_Hello_World_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/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/end_to_end_gee/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/end_to_end_gee/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 1C* dataset and you will find its id `COPERNICUS/S2_SR`. Visit the [Sentinel-2, Level 1C page](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2) 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='75%'}
knitr::include_graphics('images/end_to_end_gee/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. Replace the X and Y coordinates with the coordinates of your city and click *Run* to see the images of your city.
```{r echo=FALSE, fig.align='center', out.width='75%'}
knitr::include_graphics('images/end_to_end_gee/image_collection2.png')
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A01-Earth-Engine-Basics%2F02c_Image_Collections_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/01-Earth-Engine-Basics/02c_Image_Collections_(exercise)')}
```
## 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 filters.
```{r echo=FALSE, fig.align='center', out.width='75%'}
knitr::include_graphics('images/end_to_end_gee/filters.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A01-Earth-Engine-Basics%2F03b_Filtering_Image_Collection_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/01-Earth-Engine-Basics/03b_Filtering_Image_Collection_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A01-Earth-Engine-Basics%2F03c_Filtering_Image_Collection_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/01-Earth-Engine-Basics/03c_Filtering_Image_Collection_(exercise)')}
```
## 04. Creating Mosaics and Composites from ImageCollections
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.
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 from the stack.
> 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.
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='Mosaic vs. Composite'}
knitr::include_graphics('images/end_to_end_gee/mosaic_composite.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A01-Earth-Engine-Basics%2F04b_Mosaics_and_Composites_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/01-Earth-Engine-Basics/04b_Mosaics_and_Composites_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%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. Working with Feature Collections
Feature Collections are similar to Image Collections - but they contain *Features*, not images. They are equivalent to 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.
```{r echo=FALSE, fig.align='center', out.width='75%'}
knitr::include_graphics('images/end_to_end_gee/feature_collection.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A01-Earth-Engine-Basics%2F05b_Feature_Collections_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/01-Earth-Engine-Basics/05b_Feature_Collections_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A01-Earth-Engine-Basics%2F05c_Feature_Collections_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/01-Earth-Engine-Basics/05c_Feature_Collections_(exercise)')}
```
## 06. Importing Data
You can import vector or raster data into Earth Engine. We will now import a shapefile of [Urban Centres](https://bit.ly/ghs-ucdb-shapefile) from JRC's GHS Urban Centre Database (GHS-UCDB). Unzip the `ghs_urban_centers.zip` into a folder on your computer. In the Code Editor, go to *Assets → New → Table Upload → Shape Files*. Select the `.shp`, `.shx`, `.dbf` and .`prj` files. Enter `ghs_urban_centers` as the *Asset Name* and click *Upload*. Once the upload and ingest finishes, you will have a new asset in the *Assets* tab. The shapefile is imported as a Feature Collection in Earth Engine. Select the `ghs_urban_centers` asset and click *Import*. You can then visualize the imported data.
```{r echo=FALSE, fig.align='center', out.width='75%', fig.cap='Importing a Shapefile'}
knitr::include_graphics('images/end_to_end_gee/import.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A01-Earth-Engine-Basics%2F06b_Import_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/01-Earth-Engine-Basics/06b_Import_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A01-Earth-Engine-Basics%2F06c_Import_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/01-Earth-Engine-Basics/06c_Import_(exercise)')}
```
## 07. Clipping Images
It is often desirable to clip the images to your area of interest. You can use the `clip()` function to mask out an image using a geometry.
> While in a Desktop software, clipping is desirable to remove unnecessary portion of a large image and save computation time, in Earth Engine clipping can actually 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 the images or do it at the end of your script.
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='Original vs. Clipped Image'}
knitr::include_graphics('images/end_to_end_gee/clipping.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A01-Earth-Engine-Basics%2F07b_Clipping_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/01-Earth-Engine-Basics/07b_Clipping_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A01-Earth-Engine-Basics%2F07c_Clipping_(exercise)){target="_blank"}
```{js eval=FALSE}
// Add the imported table to the Map
// Use the Inspector to find the id of your home city or any urban area of your choice
// Change the filter to use the id of the selected feature
```
## 08. Exporting Data
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.
> 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.
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.
```{r echo=FALSE, fig.align='center', out.width='75%'}
knitr::include_graphics('images/end_to_end_gee/export_task01.png')
```
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='40%'}
knitr::include_graphics('images/end_to_end_gee/export_task02.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 in a GIS software.
```{r echo=FALSE, fig.align='center', out.width='85%', fig.cap='Visualized vs. Raw Composite'}
knitr::include_graphics('images/end_to_end_gee/exporting_data.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A01-Earth-Engine-Basics%2F08b_Export_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/01-Earth-Engine-Basics/08b_Export_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A01-Earth-Engine-Basics%2F08c_Export_(exercise)){target="_blank"}
```{js eval=FALSE}
// Write the export function to export the results for your chosen urban area
```
## Assignment 1
Load the Night Lights Data for May 2015 and May 2020. Compare the imagery for your region and find the changes in the city due to COVID-19 effect.
```{r echo=FALSE, fig.align='center', out.width='85%', fig.cap='Assignment1 Expected Output'}
knitr::include_graphics('images/end_to_end_gee/assignment1.png')
```
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3AAssignments%2FAssignment1){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/Assignments/Assignment1')}
```
\newpage
# Module 2: Earth Engine Intermediate
Module 2 builds on the basic Earth Engine skills you have gained. This model introduces the parallel programming concepts using Map/Reduce - which is key in effectively using Earth Engine for analyzing large volumes of data. You will learn how to use the Earth Engine API for calculating various spectral indices, do cloud masking and then use map/reduce to do apply these computations to collections of imagery. You will also learn how to take long time-series of data and create charts.
[![View Presentation](images/end_to_end_gee/map_reduce.png){width="400px"}](https://docs.google.com/presentation/d/10qOyxhubkwnsAVjniW54ETgwUHq3DXYKo3HGb6Gemi0/edit?usp=sharing){target="_blank"}
[View the Presentation ↗](https://docs.google.com/presentation/d/10qOyxhubkwnsAVjniW54ETgwUHq3DXYKo3HGb6Gemi0/edit?usp=sharing){target="_blank"}
## 01. Earth Engine Objects
This script introduces the basics of the Earth Engine API. When programming in Earth Engine, you must use the Earth Engine API so that your computations can use the Google Earth Engine servers. To learn more, visit [Earth Engine Objects and Methods](https://developers.google.com/earth-engine/tutorial_js_02) section of the Earth Engine User Guide.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A02-Earth-Engine-Intermediate%2F01b_Earth_Engine_Objects_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/02-Earth-Engine-Intermediate/01b_Earth_Engine_Objects_(complete)')}
```
> As a general rule, you should always use Earth Engine API methods in your code, there is one exception where you will need to use client-side Javascript method. If you want to get the current time, the server doesn't know your time. You need to use javascript method and cast it to an Earth Engine object.
```
var now = Date.now()
print(now)
var now = ee.Date(now)
print(now)
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A02-Earth-Engine-Intermediate%2F01c_Earth_Engine_Objects_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/02-Earth-Engine-Intermediate/01c_Earth_Engine_Objects_(exercise)')}
```
## 02. Calculating Indices
Spectral Indices are central to many aspects of remote sensing. Whether you are studying vegetation or tracking fires - you will need to compute a pixel-wise ratio of 2 or more bands. The most commonly used formula for calculating an index is 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). For more complex formulae, you can also use the `expression()` function to describe the calculation.
```{r echo=FALSE, fig.align='center', out.width='75%', fig.cap='MNDWI, SAVI and NDVI images'}
knitr::include_graphics('images/end_to_end_gee/indices.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A02-Earth-Engine-Intermediate%2F02b_Calculating_Indices_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/02-Earth-Engine-Intermediate/02b_Calculating_Indices_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A02-Earth-Engine-Intermediate%2F02c_Calculating_Indices_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/02-Earth-Engine-Intermediate/02c_Calculating_Indices_(exercise)')}
```
## 03. Computation on ImageCollections
So far we have learnt how to run computation on single images. If you want to apply some computation - such as calculating an index - to many images, you need to use `map()`. You first define a function that takes 1 image and returns the result of the computation on that image. Then you can `map()` that function over the ImageCollection which results in a new ImageCollection with the results of the computation. This is similar to a *for-loop* that you maybe familiar with - but using `map()` allows the computation to run in parallel. Learn more at [Mapping over an ImageCollection](https://developers.google.com/earth-engine/guides/ic_mapping)
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='NDVI computation on an ImageCollection'}
knitr::include_graphics('images/end_to_end_gee/imagecollection_computation.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A02-Earth-Engine-Intermediate%2F03b_Computation_on_Image_Collections_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/02-Earth-Engine-Intermediate/03b_Computation_on_Image_Collections_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A02-Earth-Engine-Intermediate%2F03c_Computation_on_Image_Collections_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/02-Earth-Engine-Intermediate/03c_Computation_on_Image_Collections_(exercise)')}
```
## 04. Cloud Masking
Masking pixels in an image makes those pixels transparent and excludes them from analysis and visualization. To mask an image, we can use the `updateMask()` function and pass it an image with 0 and 1 values. All pixels where the mask image is 0 will be masked.
Most remote sensing datasets come with a QA or Cloud Mask band that contains the information on whether pixels is cloudy or not. Your *Code Editor* contains pre-defined functions for masking clouds for popular datasets under *Scripts Tab → Examples → Cloud Masking*. To understand how cloud-masking functions work and learn advanced techniques for bitmasking, please refer to our article on [Working with QA Bands and Bitmasks in Google Earth Engine
](https://spatialthoughts.com/2021/08/19/qa-bands-bitmasks-gee/).
The script below takes the Sentinel-2 masking function and shows how to apply it on an image.
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='Applying pixel-wise QA bitmask'}
knitr::include_graphics('images/end_to_end_gee/cloud_masking.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A02-Earth-Engine-Intermediate%2F04b_Cloud_Masking_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/02-Earth-Engine-Intermediate/04b_Cloud_Masking_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A02-Earth-Engine-Intermediate%2F04c_Cloud_Masking_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/02-Earth-Engine-Intermediate/04c_Cloud_Masking_(exercise)')}
```
> Learn more about the [Cloud Score+](https://medium.com/google-earth/all-clear-with-cloud-score-bd6ee2e2235e) project.
## 05. Reducers
When writing parallel computing code, 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%2FEnd-to-End-GEE%3A02-Earth-Engine-Intermediate%2F05b_Reducers_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/02-Earth-Engine-Intermediate/05b_Reducers_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A02-Earth-Engine-Intermediate%2F05c_Reducers_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/02-Earth-Engine-Intermediate/05c_Reducers_(exercise)')}
```
## 06. Time-Series Charts
Now we can put together all the skills we have learnt so far - filter, map, reduce, and cloud-masking to create a chart of average NDVI values for a given farm over 1 year. Earth Engine API comes with support for charting functions based on the Google Chart API. Here we use the `ui.Chart.image.series()` function to create a time-series chart.
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='Computing NDVI Time-series for a Farm'}
knitr::include_graphics('images/end_to_end_gee/charts1.png')
```
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='NDVI Time-series showing Dual-Cropping Cycle'}
knitr::include_graphics('images/end_to_end_gee/charts2.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A02-Earth-Engine-Intermediate%2F06b_Time_Series_Charts_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/02-Earth-Engine-Intermediate/06b_Time_Series_Charts_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A02-Earth-Engine-Intermediate%2F06c_Time_Series_Charts_(exercise)){target="_blank"}
```{js eval=FALSE}
// Delete the farm boundary from the previous script
// and add another farm at a location of your choice
// Print the chart.
```
## Assignment 2
```{r echo=FALSE, fig.align='center', out.width='75%', fig.cap='Assignment2 Expected Output'}
knitr::include_graphics('images/end_to_end_gee/assignment2.png')
```
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3AAssignments%2FAssignment2){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/Assignments/Assignment2')}
```
\newpage
# Module 3: Supervised Classification
## Introduction to Machine Learning and Supervised Classification
Supervised classification is arguably the most important classical machine learning techniques in remote sensing. Applications range from generating Land Use/Land Cover maps to change detection. Google Earth Engine is unique suited to do supervised classification at scale. 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, hyperparameter tuning and change detection.
[![View Presentation](images/end_to_end_gee/supervised_classification.png){width="400px"}](https://docs.google.com/presentation/d/19L1b5vsxb38xS8GlHNKOjvPZ0IGqDhv93681btMEL5w/edit?usp=sharing){target="_blank"}
[View the Presentation ↗](https://docs.google.com/presentation/d/19L1b5vsxb38xS8GlHNKOjvPZ0IGqDhv93681btMEL5w/edit?usp=sharing){target="_blank"}
## 01. Basic Supervised Classification
We will learn how to do a basic land cover classification using training samples collected from the Code Editor using the High Resolution basemap imagery provided by Google Maps. This method requires no prior training data and is quite effective to generate high quality classification samples anywhere in the world. The goal is to classify each source pixel into one of the following classes - urban, bare, water or vegetation. Using the drawing tools in the code editor, you create 4 new feature collection with points representing pixels of that class. Each feature collection has a property called `landcover` with values of 0, 1, 2 or 3 indicating whether the feature collection represents urban, bare, water or vegetation respectively. We then train a *Random Forest* classifier using these training set to build a model and apply it to all the pixels of the image to create a 4 class image.
> 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.
```{r echo=FALSE, fig.align='center', out.width='75%', fig.cap='Supervised Classification Output'}
knitr::include_graphics('images/end_to_end_gee/classified.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A03-Supervised-Classification%2F01d_Basic_Supervised_Classification_(noimport)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/03-Supervised-Classification/01d_Basic_Supervised_Classification_(noimport)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A03-Supervised-Classification%2F01c_Basic_Supervised_Classification_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/03-Supervised-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.
Classification results are evaluated based on the following metrics
* **Overall Accuracy**: How many samples were classified correctly.
* **Producer’s Accuracy**: How well did the classification predict each class.
* **Consumer’s Accuracy (Reliability)**: How reliable is the prediction in each class.
* **Kappa Coefficient**: How well the classification performed as compared to random assignment.
```{r echo=FALSE, fig.align='center', out.width='75%', fig.cap='Accuracy Assessment'}
knitr::include_graphics('images/end_to_end_gee/accuracy_assessment.png')
```
> 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.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A03-Supervised-Classification%2F02b_Accuracy_Assessment_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/03-Supervised-Classification/02b_Accuracy_Assessment_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A03-Supervised-Classification%2F02c_Accuracy_Assessment_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/03-Supervised-Classification/02c_Accuracy_Assessment_(exercise)')}
```
## 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. A more [complete and robust technique](#image-normalization-and-standardization) for image normalization is provided in the course Supplement.
Our training features have more parameters and contain values of the same scale. The result is a much improved classification.
```{r echo=FALSE, fig.align='center', out.width='75%', fig.cap='Improved Classification Accuracy with use of Spectral Indices and Elevation Data'}
knitr::include_graphics('images/end_to_end_gee/improving_classification.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A03-Supervised-Classification%2F03b_Improving_the_Classification_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/03-Supervised-Classification/03b_Improving_the_Classification_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A03-Supervised-Classification%2F03c_Improving_the_Classification_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/03-Supervised-Classification/03c_Improving_the_Classification_(exercise)')}
```
## 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.
```{r echo=FALSE, fig.align='center', out.width='75%', fig.cap='Exported Classification Outputs'}
knitr::include_graphics('images/end_to_end_gee/export_classification.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A03-Supervised-Classification%2F04b_Exporting_Classification_Results_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/03-Supervised-Classification/04b_Exporting_Classification_Results_(complete)')}
```
### Exercise
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.
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A03-Supervised-Classification%2F04c_Exporting_Classification_Results_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/03-Supervised-Classification/04c_Exporting_Classification_Results_(exercise)')}
```
## 05. Calculating Area
Now that we have the results of our classification, we will learn how to calculate the area for pixels in each class. The functions used for area computations are different for vectors and raster data.
* **Area of Polygons**: Calculating area for polygons is done using the `area()` function. It computes area on a sphere (ignoring the ellipsoid flattening) and gives you the area in square meters. You can optionally supply `proj` and a non-zero `maxError` parameters to calculate area in a specific projected CRS. For example, `area({proj:'EPSG:32643', maxError: 1})` will calculate the area of the polygon after reprojecting it to the *WGS 84/UTM Zone 43* CRS with a tolerance of 1 meter.
* **Area of Image Pixels**: Area of image pixels is computed using the `ee.Image.pixelArea()` function. This function computes the area inside the 4 corners of each pixel using the WGS84 ellipsoid. 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).
```{r echo=FALSE, fig.align='center', out.width='75%', fig.cap='Calculating Green Cover from Classified Image'}
knitr::include_graphics('images/end_to_end_gee/area_calculation.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A03-Supervised-Classification%2F05b_Calculating_Area_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/03-Supervised-Classification/05b_Calculating_Area_(complete)')}
```
> If you want to compute area covered by each class, you can use a [Grouped Reducer](https://developers.google.com/earth-engine/reducers_grouping). See the [Supplement](end-to-end-gee-supplement.html#calculating-area-by-class) to see a code snippet.
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A03-Supervised-Classification%2F05c_Calculating_Area_(exercise)){target="_blank"}
```{js eval=FALSE}
// Exercise
// Compute and print the percentage green cover of the city
```
## Assignment 3
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3AAssignments%2FAssignment3){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/Assignments/Assignment3')}
```
# Module 4: Change Detection
## Introduction to Change Detection
Many earth observation datasets are available at regular intervals over long periods of time. This enables us to detect changes on the Earth's surface. Change detection technique in remote sensing fall in the following categories
- **Single Band Change**: Measuring change in a single band image or a spectral index using a threshold
- **Multi Band Change**: Measuring spectral distance and spectral angle between two multiband images
- **Classification of Change**: One-pass classification using stacked image containing bands from before and after an event
- **Post Classification Comparison**: Comparing two classified images and computing class transitions
In the following sections, we will apply the supervised classification techniques for change detection using multi-temporal images.
[![View Presentation](images/end_to_end_gee/change_detection.png){width="400px"}](https://docs.google.com/presentation/d/1vdFTWJ61yDuVfbfhpnumQ8zuMPGwGcHpHsBTRgo_o5I/edit?usp=sharing){target="_blank"}
[View the Presentation ↗](https://docs.google.com/presentation/d/1vdFTWJ61yDuVfbfhpnumQ8zuMPGwGcHpHsBTRgo_o5I/edit?usp=sharing){target="_blank"}
## 01. Spectral Index Change
Many types of change can be detected by measuring the change in a spectral index and applying a threshold. This technique is suitable when there is a suitable spectral index is available for the type of change you are interested in detecting.
Here we apply this technique to map the extent and severity of a forest fire. The **Normalized Burn Ratio (NBR)** is an index that is designed to highlight burnt vegetation areas. We compute the NBR for before and after images. Then we apply a suitable threshold to find burnt areas.
```{r echo=FALSE, fig.align='center', out.width='75%', fig.cap='Spectral Index Change Detection'}
knitr::include_graphics('images/end_to_end_gee/spectral_index_change.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A04-Change-Detection%2F01b_Spectral_Index_Change_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/04-Change-Detection/01b_Spectral_Index_Change_(complete)')}
```
### Exercise
```{r echo=FALSE, fig.align='center', out.width='75%', fig.cap='Classifying the Change Image'}
knitr::include_graphics('images/end_to_end_gee/spectral_index_change_exercise.png')
```
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A04-Change-Detection%2F01c_Spectral_Index_Change_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/04-Change-Detection/01c_Spectral_Index_Change_(exercise)')}
```
## 02. Spectral Distance Change
When you want to detect changes from multi-band images, a useful technique is to compute the Spectral Distance and Spectral Angle between the two images. Pixels that exhibit a large change will have a larger distance compared to those that did not change. This technique is particularly useful when there are no suitable index to detect the change. It can be applied to detect change after natural disasters or human conflicts.
Here we use this technique to detect landslides using before/after composites. You may learn more about this technique at [Craig D'Souza's Change Detection](https://goo.gl/xotYhk) presentation.
```{r echo=FALSE, fig.align='center', out.width='75%', fig.cap='Spectral Distance Change Detection'}
knitr::include_graphics('images/end_to_end_gee/spectral_distance.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A04-Change-Detection%2F01b_Spectral_Distance_Change_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/04-Change-Detection/02b_Spectral_Distance_Change_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A04-Change-Detection%2F01c_Spectral_Distance_Change_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/04-Change-Detection/02c_Spectral_Distance_Change_(exercise)')}
```
## 03. Direct Classification of Change
This technique of change detection is also known as *One-pass Classification* or *Direct Multi-date Classification*. Here we create a single stacked image containing bands from before and after images. We train a classifier with training data sampled from the stacked image and apply the classifier on the stacked image to find all change pixels.
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='All pixels that changed from bare ground to built-up'}
knitr::include_graphics('images/end_to_end_gee/change_classification.png')
```
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A04-Change-Detection%2F03b_Classifying_Change_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/04-Change-Detection/03b_Classifying_Change_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?accept_repo=users%2Fujavalgandhi%2FEnd-to-End-GEE&scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A04-Change-Detection%2F03c_Classifying_Change_(exercise)){target="_blank"}
```{js eval=FALSE}
// Add an NDBI band to improve the detection of changes.
var addNDBI = function(image) {
var ndbi = image.normalizedDifference(['B11', 'B8']).rename(['ndbi']);
return image.addBands(ndbi)
}
// use addNDBI() function to add the NDBI band to both 2019 and 2020 composite images
// Hint1: You can save the resulting image in the same variable to avoid changing
// a lot of code.
// var image = addNDBI(image)
```
## 04. Post-classification Comparison
We dealing with multi-class images, a useful metric for change detection is to know how many pixels from class X changed to class Y. This can be accomplished using the `ee.Reducer.frequencyHistogram()` reducer as shown below.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A04-Change-Detection%2F04b_Post_Classification_Comparison_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/04-Change-Detection/04b_Post_Classification_Comparison_(complete)')}
```
### Exercise
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='Lost water pixels between 2019 and 2020'}
knitr::include_graphics('images/end_to_end_gee/post_classification.png')
```
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A04-Change-Detection%2F04c_Post_Classification_Comparison_(exercise)){target="_blank"}
```{js eval=FALSE}
// Exercise
// Show all areas where water became other classes and display the result
// Hint1: Select class 3 pixels from before image and NOT class 3 pixels from after image
// Hint2: use the .and() operation to select pixels matching both conditions
```
# Module 5: Earth Engine Apps
This module is focused the concepts related to client vs. server that will help you in creating web apps. We will be building an app using the Earth Engine User Interface API and publishing it to Google Cloud.
[![View Presentation](images/end_to_end_gee/apps.png){width="400px"}](https://docs.google.com/presentation/d/1u4Q91OqT9_OS4m1OWMm3uRUgu_oseqDUxHV-8mpzGz4/edit?usp=sharing){target="_blank"}
[View the Presentation ↗](https://docs.google.com/presentation/d/1u4Q91OqT9_OS4m1OWMm3uRUgu_oseqDUxHV-8mpzGz4/edit?usp=sharing{target="_blank"})
## 01. Client vs. Server
The User Interface elements in your Code Editor - Map View, Drawing Tools etc. are 'client-side' elements. They run in YOUR browser. Image Collections, feature collections, calculations on Earth Engine objects etc. are 'server-side' elements. They run in Google's data center. You cannot mix both these objects. To learn more, visit the [Client vs. Server](https://developers.google.com/earth-engine/guides/client_server) section of the Earth Engine User Guide.
* To convert client-side objects to server-side objects, you can use the appropriate API function. Server-side functions start with `ee.`, such `ee.Date()`, `ee.Image()` etc.
* To convert server-side objects to client-side objects, you can call `.getInfo()` on am Earth Engine object. For the Python API, this is the only way to extract information from a server-side object, but the Javascript API provides a better (and preferred) - method for bring server-side objects to client-side using the `evaluate()` method. This method asynchronously retrieves the value of the object, without blocking the user interface - meaning it will let your code continue to execute while it fetches the value.
> Tip: You can use `ee.Algorithms.ObjectType()` to get the type of a server-side object
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A05-Earth-Engine-Apps%2F01b_Client_vs_Server_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/05-Earth-Engine-Apps/01b_Client_vs_Server_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A05-Earth-Engine-Apps%2F01c_Client_vs_Server_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/05-Earth-Engine-Apps/01c_Client_vs_Server_(exercise)')}
```
## 02. Using UI Elements
Earth Engine comes with a User Interface API that allows you to build an interactive web application powered by Earth Engine.
The Earth Engine API provides a library of User Interface (UI) widgets - such as Buttons, Drop-down Menus, Sliders etc. - that can be used to create interactive apps. All the user interface functions are contained in the `ui.` package - such as `ui.Select()`, `ui.Button()`. You can create those elements by calling these functions with appropriate parameters. Learn more in the [Earth Engine User Interface API](https://developers.google.com/earth-engine/guides/ui) section of the Earth Engine User Guide.
This section shows how to build a drop-down selector using the `ui.Select()` widget.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A05-Earth-Engine-Apps%2F02b_Using_UI_Elements_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/05-Earth-Engine-Apps/02b_Using_UI_Elements_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A05-Earth-Engine-Apps%2F02c_Using_UI_Elements_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/05-Earth-Engine-Apps/02c_Using_UI_Elements_(exercise)')}
```
## 03. Building and Publishing an App
Building a web mapping application typically requires the skills of a full stack developer and are out of reach for most analysts and scientists. But the Earth Engine User Interface API makes this process much more accessible by providing ready-to-use widgets and free cloud hosting to allow anyone to publish an app with just a few lines of code. The main container object is the `ui.Panel()` which can contain different types of widgets.
The code below shows how to build an app called [Night Lights Explorer](https://santhosh-m.users.earthengine.app/view/night-lights-explorer) that allows anyone to pick a year/month and load the *VIIRS Nighttime Day/Night Band Composite* for the selected month. Copy/paste the code below to your Code Editor and click *Run*.
```{r echo=FALSE, fig.align='center', out.width='100%'}
knitr::include_graphics('images/end_to_end_gee/app1.png')
```
You will see a panel on the right-hand side with 2 drop-down boxes and a button. These are User Interface (UI) widgets provided by the Earth Engine API that allows the user to interactively select the values. You can select the values for *year* and *month* and click *Load* button to see the image for the selected month.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A05-Earth-Engine-Apps%2F03b_Building_an_App_with_UI_Widgets_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/05-Earth-Engine-Apps/03b_Building_an_App_with_UI_Widgets_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A05-Earth-Engine-Apps%2F03c_Building_an_App_with_UI_Widgets_(exercise)){target="_blank"}
```{js eval=FALSE}
// Exercise
// Add a button called 'Reset'
// Clicking the button should remove all loaded layers
// Hint: Use Map.clear() for removing the layers
```
## 04. Publishing the App
We will now publish this app. Click on the *Apps* button.
```{r echo=FALSE, fig.align='center', out.width='100%', fig.cap='App with UI Elements'}
knitr::include_graphics('images/end_to_end_gee/app2.png')
```
In the *Manage Apps* window, click *New App*.
```{r echo=FALSE, fig.align='center', out.width='60%'}
knitr::include_graphics('images/end_to_end_gee/app3.png')
```
Select the existing project or create a new project. The app will be hosted on Google Cloud, so you will need to create and link a Google Cloud project with the app. If you don't have a Google Cloud account, you can select the *Register a New Project* option to create a new project. You can provide an edit access based on the project selection.
```{r echo=FALSE, fig.align='center', out.width='50%'}
knitr::include_graphics('images/end_to_end_gee/app4.png')
```
Give the name of your app and see the URL created for your app.
```{r echo=FALSE, fig.align='center', out.width='50%'}
knitr::include_graphics('images/end_to_end_gee/app5.png')
```
Select code to use for the app. It can be from the current content or choose any repository path where the code is saved. We will go ahead with *Current contents of editor*
```{r echo=FALSE, fig.align='center', out.width='60%'}
knitr::include_graphics('images/end_to_end_gee/app6.png')
```
Click next and in the *Publish New App* dialog, leave all other settings to default and click *Publish*.
```{r echo=FALSE, fig.align='center', out.width='50%'}
knitr::include_graphics('images/end_to_end_gee/app7.png')
```
The app will be hosted on Google Cloud and you can access it by clicking on the *App Name* of your app in the *Manage Apps* dialog.
```{r echo=FALSE, fig.align='center', out.width='60%'}
knitr::include_graphics('images/end_to_end_gee/app8.png')
```
You will see your Earth Engine powered app running in the browser. Anyone can access and interact with the app by just visiting the App URL.
> The app publishing process takes a few minutes. So if you get an error that your app is not yet ready, check back in a few minutes.
[Explore The App ↗](https://ujavalgandhi.users.earthengine.app/view/night-lights-explorer){target="_blank"}
```{r echo=FALSE, fig.align='center', out.width='100%'}
knitr::include_graphics('images/end_to_end_gee/app9.png')
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A05-Earth-Engine-Apps%2F04c_Publishing_the_App_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/05-Earth-Engine-Apps/04c_Publishing_the_App_(exercise)')}
```
## 05. Create a Split Panel App
Another useful widget that can be used in Apps is `ui.SplitPanel()`. This allows you to create an app that can display 2 different images of the same region that can be explored interactively by swiping. Here we create an app to explore the [ESA WorldCover 10m](https://developers.google.com/earth-engine/datasets/catalog/ESA_WorldCover_v100) global classification dataset.
On the left-hand panel, we will load a Sentinel-2 composite for the year 2020. On the right-hand panel, we will load the 11-class landcover classification of the same region.
[Open in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A05-Earth-Engine-Apps%2F05b_Split_Panel_App_(complete)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/05-Earth-Engine-Apps/05b_Split_Panel_App_(complete)')}
```
### Exercise
[Try in Code Editor ↗](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3A05-Earth-Engine-Apps%2F05c_Split_Panel_App_(exercise)){target="_blank"}
```{js eval=FALSE, code=readLines('code/end_to_end_gee/05-Earth-Engine-Apps/05c_Split_Panel_App_(exercise)')}
```
# Module 6: Google Earth Engine Python API
## Introduction to the Python API
Till this point in the course, we have used the Earth Engine Javascript API for all our analysis. Earth Engine also provides a Python API. If you are a Python programmer, you may prefer to use the Python API to integrate Earth Engine in your spatial analysis workflow. There are many options for running Python code that uses the Google Earth Engine API. We will use the following two methods in this course.
[![View Presentation](images/end_to_end_gee/python_api.png){width="400px"}](https://docs.google.com/presentation/d/1hPVRnxp2Vp1VHXBtu36SH_UtEOjPz70KcDV-zGIin3U/edit?usp=sharing){target="_blank"}
[View the Presentation ↗](https://docs.google.com/presentation/d/1hPVRnxp2Vp1VHXBtu36SH_UtEOjPz70KcDV-zGIin3U/edit?usp=sharing){target="_blank"}