diff --git a/_build/.doctrees/activities.doctree b/_build/.doctrees/activities.doctree new file mode 100644 index 0000000..657e8d5 Binary files /dev/null and b/_build/.doctrees/activities.doctree differ diff --git a/_build/.doctrees/activity1-js.doctree b/_build/.doctrees/activity1-js.doctree new file mode 100644 index 0000000..3f178bf Binary files /dev/null and b/_build/.doctrees/activity1-js.doctree differ diff --git a/_build/.doctrees/activity1-py.doctree b/_build/.doctrees/activity1-py.doctree new file mode 100644 index 0000000..c1fe985 Binary files /dev/null and b/_build/.doctrees/activity1-py.doctree differ diff --git a/_build/.doctrees/code.doctree b/_build/.doctrees/code.doctree new file mode 100644 index 0000000..7fa1cb9 Binary files /dev/null and b/_build/.doctrees/code.doctree differ diff --git a/_build/.doctrees/code2.doctree b/_build/.doctrees/code2.doctree new file mode 100644 index 0000000..2128a21 Binary files /dev/null and b/_build/.doctrees/code2.doctree differ diff --git a/_build/.doctrees/content.doctree b/_build/.doctrees/content.doctree new file mode 100644 index 0000000..d1c3dbf Binary files /dev/null and b/_build/.doctrees/content.doctree differ diff --git a/_build/.doctrees/environment.pickle b/_build/.doctrees/environment.pickle new file mode 100644 index 0000000..57429d9 Binary files /dev/null and b/_build/.doctrees/environment.pickle differ diff --git a/_build/.doctrees/glue_cache.json b/_build/.doctrees/glue_cache.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/_build/.doctrees/glue_cache.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/_build/.doctrees/intro.doctree b/_build/.doctrees/intro.doctree new file mode 100644 index 0000000..948c8f4 Binary files /dev/null and b/_build/.doctrees/intro.doctree differ diff --git a/_build/.doctrees/lake-champlain.doctree b/_build/.doctrees/lake-champlain.doctree new file mode 100644 index 0000000..f810538 Binary files /dev/null and b/_build/.doctrees/lake-champlain.doctree differ diff --git a/_build/.doctrees/markdown.doctree b/_build/.doctrees/markdown.doctree new file mode 100644 index 0000000..609c204 Binary files /dev/null and b/_build/.doctrees/markdown.doctree differ diff --git a/_build/.doctrees/notebooks.doctree b/_build/.doctrees/notebooks.doctree new file mode 100644 index 0000000..6f8fd34 Binary files /dev/null and b/_build/.doctrees/notebooks.doctree differ diff --git a/_build/html/.buildinfo b/_build/html/.buildinfo new file mode 100644 index 0000000..0d63869 --- /dev/null +++ b/_build/html/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 6c5c54cc8b9046fdec8a2676e1be8d63 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/_build/html/_sources/activities.md b/_build/html/_sources/activities.md new file mode 100644 index 0000000..6120f86 --- /dev/null +++ b/_build/html/_sources/activities.md @@ -0,0 +1,3 @@ +# Activities + +This book includes remote sensing analyses in both `JavaScript` and `Python`. diff --git a/_build/html/_sources/activity1-js.md b/_build/html/_sources/activity1-js.md new file mode 100644 index 0000000..4933c4b --- /dev/null +++ b/_build/html/_sources/activity1-js.md @@ -0,0 +1,100 @@ +# Javascript + +The purpose of this lesson is to review the change from leaf-off imagery to leaf-on imagery for a study areas of interest. + +In this lesson, you will: + +* Choose an area and Landsat collection of interest; +* Filter the Landsat collection to obtain leaf-off and leaf-on imagery; and, +* Display a single image from both leaf-off and leaf-on conditions. + +## Data Acquisition & Pre-Processing +```{code-block} javascript +// Define boundary for Rocky Mountain National Park, Colorado +var rmnp_boundary = ee.FeatureCollection("users/calekochenour/Rocky_Mountain_National_Park__Boundary_Polygon"); + +// Define Landsat 8 collection +var landsat8_t1_sr = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR'); + +// Filter Landsat 8 Tier 1 SR to snow-on conditions near RMNP, 2018 +var co_snow_on_2018 = landsat8_t1_sr + .filterDate('2018-03-01', '2018-04-30') + .filterBounds(rmnp_boundary) + .sort('CLOUD_COVER') + .first(); + +// Filter Landsat 8 Tier 1 SR to snow-off conditions near RMNP, 2018 +var co_snow_off_2018 = landsat8_t1_sr + .filterDate('2018-07-01', '2018-08-31') + .filterBounds(rmnp_boundary) + .sort('CLOUD_COVER') + .first(); +``` + +## Data Processing +```{code-block} javascript +// No data processsing in this lab. +``` + +## Data Visualization +```{code-block} javascript +// Define Landsat 8 RGB visualization parameters +var l8_vis_params_rgb = { + 'bands': ['B4', 'B3', 'B2'], + 'min': 0, + 'max': 3000 + }; + +// Define Landsat 8 CIR visualization parameters +var l8_vis_params_cir = { + 'bands': ['B5', 'B4', 'B3'], + 'min': 0, + 'max': 3000 + }; + +// Define RMNP boundary visualization parameters +var empty = ee.Image().byte(); + +var rmnp_boundary_vis = empty.paint({ + featureCollection: rmnp_boundary, + color: 1, + width: 3 +}); +``` + +```{code-block} javascript +// Center map to Rocky Mountain National Park, Colorado +Map.setCenter(-105.6836, 40.3428, 10); + +// Add snow-on and snow-off images to map, RGB and CIR +Map.addLayer( + rmnp_snow_on_2018, + l8_vis_params_rgb, + 'Landsat 8 - RGB - 2018 - RMNP - Snow On'); + +Map.addLayer( + rmnp_snow_on_2018, + l8_vis_params_cir, + 'Landsat 8 - CIR - 2018 - RMNP - Snow On'); + +Map.addLayer( + rmnp_snow_off_2018, + l8_vis_params_rgb, + 'Landsat 8 - RGB - 2018 - RMNP - Snow Off'); + +Map.addLayer( + rmnp_snow_off_2018, + l8_vis_params_cir, + 'Landsat 8 - CIR - 2018 - RMNP - Snow Off'); + +// Add RMNP boundary to map +Map.addLayer( + rmnp_boundary_vis, + {'palette': 'FF0000'}, + 'RMNP Boundary'); +``` + +## Data Export +```{code-block} javascript +// No data export in this lab. +``` diff --git a/_build/html/_sources/activity1-py.md b/_build/html/_sources/activity1-py.md new file mode 100644 index 0000000..f14f152 --- /dev/null +++ b/_build/html/_sources/activity1-py.md @@ -0,0 +1,124 @@ +# Python + +The purpose of this lesson is to review the change from leaf-off imagery to leaf-on imagery for a study areas of interest. + +In this lesson, you will: + +* Choose an area and Landsat collection of interest; +* Filter the Landsat collection to obtain leaf-off and leaf-on imagery; and, +* Display a single image from both leaf-off and leaf-on conditions. + +## Environment Setup +```{code-block} python +# Import packages +import ee +import geemap as gm + +# Initialze GEE Python API; authenticate if necessary +try: + ee.Initialize() + +except Exception as error: + ee.Authenticate() + ee.Initialize() +``` + +## Data Acquisition & Pre-Processing +```{code-block} python +# Define boundary for Rocky Mountain National Park, Colorado +rmnp_boundary = ee.FeatureCollection( + "users/calekochenour/Rocky_Mountain_National_Park__Boundary_Polygon") + +# Define Landsat 8 collection +landsat8_t1_sr = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR') + +# Filter Landsat 8 Tier 1 SR to snow-on conditions near RMNP, 2018 +co_snow_on_2018 = landsat8_t1_sr.filterDate( + '2018-03-01', '2018-04-30').filterBounds( + rmnp_boundary).sort('CLOUD_COVER').first() + +# Filter Landsat 8 Tier 1 SR to snow-off conditions near RMNP, 2018 +co_snow_off_2018 = landsat8_t1_sr.filterDate( + '2018-07-01', '2018-08-31').filterBounds( + rmnp_boundary).sort('CLOUD_COVER').first() + +# Clip snow-on and snow-off imagery to RMNP boundary +rmnp_snow_on_2018 = co_snow_on_2018.clip(rmnp_boundary) +rmnp_snow_off_2018 = co_snow_off_2018.clip(rmnp_boundary) +``` + +## Data Processing +```{code-block} python +# No data processing in this lab. +``` + +## Data Visualization +```{code-block} python +# Define Landsat 8 RGB visualization parameters +l8_vis_params_rgb = { + 'bands': ['B4', 'B3', 'B2'], + 'min': 0, + 'max': 3000 +} + +# Define Landsat 8 CIR visualization parameters +l8_vis_params_cir = { + 'bands': ['B5', 'B4', 'B3'], + 'min': 0, + 'max': 3000 +} + +# Define RMNP boundary visualization parameters +empty = ee.Image().byte() + +rmnp_boundary_vis = empty.paint( + featureCollection=rmnp_boundary, color=1, width=3) +``` + +```{code-block} python +# Create map for visualization +rmnp_snow_map = gm.Map() +rmnp_snow_map.setOptions('SATELLITE') + +# Center map to Rocky Mountain National Park, Colorado +rmnp_snow_map.setCenter(-105.6836, 40.3428, 10) +``` + +```{code-block} python +# Add snow-on and snow-off images to map, RGB and CIR +rmnp_snow_map.addLayer( + rmnp_snow_on_2018, + l8_vis_params_rgb, + 'Landsat 8 - RGB - 2018 - Snow On') + +rmnp_snow_map.addLayer( + rmnp_snow_on_2018, + l8_vis_params_cir, + 'Landsat 8 - CIR - 2018 - Snow On') + +rmnp_snow_map.addLayer( + rmnp_snow_off_2018, + l8_vis_params_rgb, + 'Landsat 8 - RGB - 2018 - Snow Off') + +rmnp_snow_map.addLayer( + rmnp_snow_off_2018, + l8_vis_params_cir, + 'Landsat 8 - CIR - 2018 - Snow Off') + +# Add RMNP boundary to map +rmnp_snow_map.addLayer( + rmnp_boundary_vis, + {'palette': 'FF0000'}, + 'RMNP Boundary') +``` + +```{code-block} python +# Display map +rmnp_snow_map +``` + +## Data Export +```{code-block} python +# No data export in this lab. +``` diff --git a/_build/html/_sources/code.md b/_build/html/_sources/code.md new file mode 100644 index 0000000..c0974b3 --- /dev/null +++ b/_build/html/_sources/code.md @@ -0,0 +1,179 @@ +# Code Snippets + +```{code-block} python +# Imports +import ee + +# Authenticate to GEE; initialze Python API +try: + ee.Initialize() +except Exception as e: + ee.Authenticate() + ee.Initialize() +``` + +```{code-block} javascript +// Activity 1 - Qualitative Change Detection + +// ================================= +// Data Acquisition & Pre-Processing +// ================================= + +// Define boundary for Rocky Mountain National Park, Colorado +var rmnp_boundary = ee.FeatureCollection("users/calekochenour/Rocky_Mountain_National_Park__Boundary_Polygon"); + +// Define Landsat 8 collection +var landsat8_t1_sr = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR'); + +// Filter Landsat 8 Tier 1 SR to snow-on conditions near RMNP, 2018 +var co_snow_on_2018 = landsat8_t1_sr + .filterDate('2018-03-01', '2018-04-30') + .filterBounds(rmnp_boundary) + .sort('CLOUD_COVER') + .first(); + +// Filter Landsat 8 Tier 1 SR to snow-off conditions near RMNP, 2018 +var co_snow_off_2018 = landsat8_t1_sr + .filterDate('2018-07-01', '2018-08-31') + .filterBounds(rmnp_boundary) + .sort('CLOUD_COVER') + .first(); + +// =============== +// Data Processing +// =============== + +// No data processsing in this lab. + + +// ================== +// Data Visualization +// ================== + +// Define Landsat 8 RGB visualization parameters +var l8_vis_params_rgb = { + 'bands': ['B4', 'B3', 'B2'], + 'min': 0, + 'max': 3000 + }; + +// Define Landsat 8 CIR visualization parameters +var l8_vis_params_cir = { + 'bands': ['B5', 'B4', 'B3'], + 'min': 0, + 'max': 3000 + }; + +// Define RMNP boundary visualization parameters +var empty = ee.Image().byte(); + +var rmnp_boundary_vis = empty.paint({ + featureCollection: rmnp_boundary, + color: 1, + width: 3 +}); + +// Center map to Rocky Mountain National Park, Colorado +Map.setCenter(-105.6836, 40.3428, 10); + +// Add snow-on and snow-off images to map, RGB and CIR +Map.addLayer( + rmnp_snow_on_2018, + l8_vis_params_rgb, + 'Landsat 8 - RGB - 2018 - RMNP - Snow On'); + +Map.addLayer( + rmnp_snow_on_2018, + l8_vis_params_cir, + 'Landsat 8 - CIR - 2018 - RMNP - Snow On'); + +Map.addLayer( + rmnp_snow_off_2018, + l8_vis_params_rgb, + 'Landsat 8 - RGB - 2018 - RMNP - Snow Off'); + +Map.addLayer( + rmnp_snow_off_2018, + l8_vis_params_cir, + 'Landsat 8 - CIR - 2018 - RMNP - Snow Off'); + +// Add RMNP boundary to map +Map.addLayer( + rmnp_boundary_vis, + {'palette': 'FF0000'}, + 'RMNP Boundary'); + + +// =========== +// Data Export +// =========== + +// No data export in this lab. +``` + +```{code-block} python +--- +lineno-start: 10 +emphasize-lines: 1, 3 +caption: | + This is my + multi-line caption. It is *pretty nifty* ;-) +--- +a = 2 +print('my 1st line') +print(f'my {a}nd line') +``` + +```{code-block} ipython +--- +class: hide-output +--- +print("Hello") +``` + +```{code-block} ipython +print("Hello") +``` + +```{code-block} python +import numpy as np +import matplotlib.pyplot as plt +%matplotlib inline + +import quantecon as qe +from numba import njit, jitclass, float64, prange +``` + +```{code-block} python +f_vals, l_vals = qe.lorenz_curve(w) + +fig, ax = plt.subplots() +ax.plot(f_vals, l_vals, label='Lorenz curve, lognormal sample') +ax.plot(f_vals, f_vals, label='Lorenz curve, equality') +ax.legend() +plt.show() +``` + +```{code-block} ipython +f_vals, l_vals = qe.lorenz_curve(w) + +fig, ax = plt.subplots() +ax.plot(f_vals, l_vals, label='Lorenz curve, lognormal sample') +ax.plot(f_vals, f_vals, label='Lorenz curve, equality') +ax.legend() +plt.show() +``` + + +```{math} +--- +label: eqn:ndvi +--- +ndvi = \frac{nir - red}{nir + red} +``` + +$$ + ndvi = \frac{nir - red}{nir + red} +$$ (eqn:ndvi_2) + +Look at the formula for ndvi: {eq}`eqn:ndvi` diff --git a/_build/html/_sources/content.md b/_build/html/_sources/content.md new file mode 100644 index 0000000..3448ebb --- /dev/null +++ b/_build/html/_sources/content.md @@ -0,0 +1,4 @@ +What is Google Earth Engine? +============================ + +Google Earth Engine is a cloud platform to access, use, and analyze remote sensing and geospatial data. diff --git a/_build/html/_sources/intro.md b/_build/html/_sources/intro.md new file mode 100644 index 0000000..87a1705 --- /dev/null +++ b/_build/html/_sources/intro.md @@ -0,0 +1,11 @@ +# Remote Sensing with Google Earth Engine + +This book provides text and examples for how to use Google Earth Engine to work through the remote sensing data workflow: + +* Acquisition and Pre-Processing; +* Processing; +* Post-Processing; +* Visualization; and, +* Export. + +The book includes code in `JavaScript` and `Python` languages for completing remote sensing analyses. diff --git a/_build/html/_sources/lake-champlain.md b/_build/html/_sources/lake-champlain.md new file mode 100644 index 0000000..2e2915f --- /dev/null +++ b/_build/html/_sources/lake-champlain.md @@ -0,0 +1,362 @@ +# Lake Champlain + +## Introduction + +The purpose of this lesson is to further extend your knowledge of GEE and functions to bring images and image collections into the browser for further analysis. + +You’ll locate a Landsat image in any area on the planet that interests you. It could be some place you've lived, visited, or a place where you've worked. It's your choice. You can use the map (at the bottom of the Code Editor). In the upper left corner there are drawing tools to allow you to define polygons on the map interface below the Code Editor window. + +## Lesson Steps + +### 0. Set Up GEE Environment + +```{code-block} python +# Import packages +import ee +import geemap as gm + +# Initialze GEE Python API; authenticate if necessary +try: + ee.Initialize() + +except Exception as error: + ee.Authenticate() + ee.Initialize() +``` + +### 1. Chose an Area of Interest + +Define a study area of interest. + +Hint: Point or polygon geometry should suffice. Review the EE [Geometry Overview](https://developers.google.com/earth-engine/geometries#creating-geometry-objects). + +```{code-block} python +# Define point for the center of Lake Champlain, Vermont +lake_champlain_center = ee.Geometry.Point(-73.3333, 44.5333) +``` + +```{code-block} python +# DO NOT MODIFY - AUTOGRADE +# Initialize points +points = 0 + +# Check if type is EE geometry +try: + assert isinstance(lake_champlain_center, ee.geometry.Geometry) + print("Your study area is the correct type - ee.geometry.Geometry") + points += 10 + +# Catch assertion error +except AssertionError as error: + print("AssertionError:", + "Your study area object should be of type ee.geometry.Geometry.") + +# Show points earned +print(f"Points earned: {points}") +``` + +### 2. Import a Landsat Collection + +Use the `ee.ImageCollection` ("Name of Collection") function. + +Hint: In the EE DataCatalog each collection has an "EE Snippet" of code that you can cut-and-paste. You can choose any of the Landsat Tier-1 Collections (more on collections that are in the Data Catalog later). + + +```{code-block} python +# Define collection +landsat8_t1_sr = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR') +``` + +```{code-block} python +# DO NOT MODIFY - AUTOGRADE +# Initialize points +points = 0 + +# Check if type is EE image collection +try: + assert isinstance(landsat8_t1_sr, ee.imagecollection.ImageCollection) + print("Your image collection object is the correct type - ee.imagecollection.ImageCollection") + points += 10 + +# Catch assertion error +except AssertionError as error: + print("AssertionError:", + "Your image collection object should be of type ee.imagecollection.ImageCollection.") + +# Show points earned +print(f"Points earned: {points}") +``` + +### 3. Filter the Collection to a Specific Time Period + +Use the various `.filter` methods under `ee.collection` to filter your data. See examples [here](https://developers.google.com/earth-engine/ic_filtering). + +For instance: + +```{code-block} python +reduced_collection = ee.ImageCollection( + 'LANDSAT/LT05/C01/T2').filterDate('1987-01-01', '1990-05-01') +``` + +You can filter on time and location, image quality, and numerous other image collection properties. + +For now just choose a time range and a location (use `.filterbounds` for this step). + +```{code-block} python +# Filter Landsat 8 Tier 1 SR to Vermont, 6/2018-9/2018 +vermont_jun_sep_2018 = landsat8_t1_sr.filterDate( + '2018-06-01', '2018-09-30').filterBounds(lake_champlain_center) +``` + +```{code-block} python +# DO NOT MODIFY - AUTOGRADE +# Initialize points +points = 0 + +# Check if filtered collection is reduced (less images than original) +try: + assert vermont_jun_sep_2018.size().getInfo() < landsat8_t1_sr.size().getInfo() + print("Your filtered image collection object has been reduced.") + points += 10 + +# Catch assertion error +except AssertionError as error: + print("AssertionError:", + "Your filtered image collection object has not been reduced." + "It has the same number of images as the original collection.") + +# Show points earned +print(f"Points earned: {points}") +``` + + Your filtered image collection object has been reduced. + Points earned: 10 + +### 4. Apply the Palette to Improve your Visualizations + +Recall that you used the EE palette in Lesson 1, feel free to re-use that code in this exercise. More information on the palette and visualizing imagery can be found [here](https://developers.google.com/earth-engine/tutorial_api_02). You should use the palette to help you visualize your outputs in this exercise. + +```{code-block} python +# Define Landsat 8 RGB visualization parameters +l8_vis_params_rgb = { + 'bands': ['B4', 'B3', 'B2'], + 'min': 0, + 'max': 3000 +} + +# Define Landsat 8 CIR visualization parameters +l8_vis_params_cir = { + 'bands': ['B5', 'B4', 'B3'], + 'min': 0, + 'max': 5000 +} +``` + +```{code-block} python +# DO NOT MODIFY - AUTOGRADE +# Initialize points +points = 0 + +# Check if vis params have the correct bands for Landsat 8 +try: + assert l8_vis_params_rgb.get('bands') == ['B4', 'B3', 'B2'] + print("Your RGB visualization parameters have the correct bands.") + points += 10 + +# Catch assertion error +except AssertionError as error: + print("AssertionError:", + "Your RGB visualization parameters have incorrect bands.") + +# Show points earned +print(f"Points earned: {points}") +``` + +### 5. "Reduce" Your Collection by Compositing Imagery + +Using filters above helps to "reduce" the number of scenes in a collection that you're working with. However this can still result in a "ton" of data! You can use compositing, as described [here](https://developers.google.com/earth-engine/tutorial_api_05), to calculate across all of the images (and bands) in your filtered collection to create, for example, a "median" image. Recall your basic statistics: the median is the "middle value" in a set of observations. Other measures could be applied here too, for instance the "mean" across all images could be determined. + +For this part of the exercise take your time- and space-filtered collection from above and apply a reducer like the "median". One of the things to remember about collections and display is that the default display on the map for a collection is to take the very latest image in the collection and display. Reducing to the median allows you to "composite" all of the images in the collection and display this result. + +```{code-block} python +# Sort collection from least to most cloudy +vermont_sorted = vermont_jun_sep_2018.sort('CLOUD_COVER') + +# Reduce collection to the first (least cloudy) image +vermont_least_cloudy = ee.Image(vermont_sorted.first()) +``` + +```{code-block} python +# DO NOT MODIFY - AUTOGRADE +# Initialize points +points = 0 + +# Check if image collection has been reduced to a single image +try: + assert vermont_least_cloudy.getInfo().get('type') == 'Image' + print("Your image collection has been reduced to a single image.") + points += 10 + +# Catch assertion error +except AssertionError as error: + print("AssertionError:", + "Your image collection has not been reduced to a single image.") + +# Show points earned +print(f"Points earned: {points}") +``` + +### 6. Create a Map of the Composite Image + +Combine the visualization parameters with your composite image to add the composite to an interactive map for viewing. + +Hint: Review the [Image Visualization](https://developers.google.com/earth-engine/image_visualization) documentation, specifically the `Map.addLayer()` function, for help with adding layers to an EE map. + +Hint: Run the following commands in Jupyter Notebook to review `geemap` documentation for creating and working with an interactive map in Python: + +```{code-block} python +# Call help on geemap class and methods +help(gm.Map) +help(gm.Map.setOptions) +help(gm.Map.setCenter) +help(gm.Map.addLayer) +``` + +Hint: To display a map within Jupyter Notebook, first create a `geemap.Map` object, configure options, and add layers, then call the variable containing the `geemap.Map` object: + +```{code-block} python +# Instantiate map object +ee_map = gm.Map() + +# Configure map options +# CODE FOR MAP OPTIONS + +# Add layers to map +# CODE FOR MAP LAYERS + +# Display map +ee_map +``` + +```{code-block} python +# Create interactive map for visualization +vermont_map = gm.Map() + +# Set basemap +vermont_map.setOptions('SATELLITE') + +# Center map to study area +vermont_map.setCenter( + lon=lake_champlain_center.coordinates().getInfo()[0], + lat=lake_champlain_center.coordinates().getInfo()[1], + zoom=8) +``` + +```{code-block} python +# Add least cloudy, RGB and CIR to interactive map +vermont_map.addLayer( + ee_object=vermont_least_cloudy, + vis_params=l8_vis_params_rgb, + name="Vermont | Lake Champlain | Least Cloudy | RGB", + shown=True, + opacity=1) + +vermont_map.addLayer( + ee_object=vermont_least_cloudy, + vis_params=l8_vis_params_cir, + name="Vermont | Lake Champlain | Least Cloudy | CIR", + shown=True, + opacity=1) + +# Add study area (point) to map +vermont_map.addLayer( + ee_object=lake_champlain_center, + vis_params={'color': '00FF00', 'width': 5}, + name='Vermont | Lake Champlain | Center', + shown=True, + opacity=1) +``` + +```{code-block} python +# Display map +vermont_map +``` + +### 7. Apply Masking and Mosaicking Functions + +Masks and mosaics (information found [here](https://developers.google.com/earth-engine/tutorial_api_05)) are very traditional image processing functions. GEE provides very nice capabilities to customize outputs. Read through the example provided and apply a similar approach to your reduced collection. The example discusses a "water mask", but there are other ways to mask an image, like for instance using a polygon coverage of political boundaries, or maybe "ecoregions". Try your hand at applying the water mask or developing your own mask, and then use the mosaic function to combine the mask and the reduced image. Hint: There are ancillary data resources in the data catalog that could be used in this step. + +```{code-block} python +# Load the Hansen dataset +hansen_2015 = ee.Image('UMD/hansen/global_forest_change_2015') + +# Select the mask band +datamask = hansen_2015.select('datamask') + +# Create the binary mask; non-water features, no data (0) and land (1) +water = datamask.eq(2) + +# Create water image (mask water with itself) +water = water.mask(water) +``` + +```{code-block} python +# Create visualization image for Landsat 8 +vermont_least_cloudy_rgb = vermont_least_cloudy.visualize( + **{'bands': ['B4', 'B3', 'B2'], 'max': 3000, 'min': 0}) + +# Create visualization image for Hansen water mask +water_vis = water.visualize( + **{'palette': 'blue', 'max': 1, 'min': 0, 'opacity': 0.75}) +``` + +```{code-block} python +# Get Landsat image boundary coordinates +landsat_image_coords = vermont_least_cloudy.getInfo().get( + 'properties').get('system:footprint').get('coordinates') + +# Define Landsat clip polygon from coordinates +vermont_clip_poly = ee.Geometry.Polygon([landsat_image_coords]) + +# Clip water mask to Landsat polygon +water_vis_clip = water_vis.clip(vermont_clip_poly) +``` + +```{code-block} python +# Create image collection from image visualizations +vermont_collection = ee.ImageCollection( + [vermont_least_cloudy_rgb, water_vis_clip]) + +# Create mosaic from image collection +vermont_mosaic = vermont_collection.mosaic() +``` + +### 8. Create a Map of the Mosaic Image + +Create a new interactive map and add the mosaic image to the map for viewing. + +Hint: Follow the guidance provided in Section 6 for creating and configuring an interactive map in Jupyter Notebook. + +```{code-block} python +# Create interactive map for visualization +mosaic_map = gm.Map() + +# Set basemap +mosaic_map.setOptions('SATELLITE') + +# Center map to study area +mosaic_map.setCenter( + lon=lake_champlain_center.coordinates().getInfo()[0], + lat=lake_champlain_center.coordinates().getInfo()[1], + zoom=8) +``` + +```{code-block} python +# Add mosaic image to the map +mosaic_map.addLayer(vermont_mosaic, {}, 'Vermont | Lake Champlain | Water Mask Mosaic'); +``` + +```{code-block} python +# Display map +mosaic_map +``` diff --git a/_build/html/_sources/markdown.md b/_build/html/_sources/markdown.md new file mode 100644 index 0000000..80c55d3 --- /dev/null +++ b/_build/html/_sources/markdown.md @@ -0,0 +1,139 @@ +# Markdown Files + +Whether you write your book's content in Jupyter Notebooks (`.ipynb`) or +in regular markdown files (`.md`), you'll write in the same flavor of markdown +called **MyST Markdown**. + +## What is MyST? + +MyST stands for "Markedly Structured Text". It +is a slight variation on a flavor of markdown called "CommonMark" markdown, +with small syntax extensions to allow you to write **roles** and **directives** +in the Sphinx ecosystem. + +## What are roles and directives? + +Roles and directives are two of the most powerful tools in Jupyter Book. They +are kind of like functions, but written in a markup language. They both +serve a similar purpose, but **roles are written in one line**, whereas +**directives span many lines**. They both accept different kinds of inputs, +and what they do with those inputs depends on the specific role or directive +that is being called. + +### Using a directive + +At its simplest, you can insert a directive into your book's content like so: + +```` +```{mydirectivename} +My directive content +``` +```` + +This will only work if a directive with name `mydirectivename` already exists +(which it doesn't). There are many pre-defined directives associated with +Jupyter Book. For example, to insert a note box into your content, you can +use the following directive: + +```` +```{note} +Here is a note +``` +```` + +This results in: + +```{note} +Here is a note +``` + +In your built book. + +For more information on writing directives, see the +[MyST documentation](https://myst-parser.readthedocs.io/). + ++++ + +### Using a role + +Roles are very similar to directives, but they are less-complex and written +entirely on one line. You can insert a role into your book's content with +this pattern: + +``` +Some content {rolename}`and here is my role's content!` +``` + +Again, roles will only work if `rolename` is a valid role's name. For example, +the `doc` role can be used to refer to another page in your book. You can +refer directly to another page by its relative path. For example, the +role syntax `` {doc}`intro` `` will result in: {doc}`intro`. + +For more information on writing roles, see the +[MyST documentation](https://myst-parser.readthedocs.io/). + ++++ + +### Adding a citation + +Leaving empty; need to figure out BibTex. + ++++ + +You can also cite references that are stored in a `bibtex` file. For example, +the following syntax: `` {cite}`ruby` `` will render like +this: {cite}`ruby`. + +`` {cite}`1987:nelson` `` will render like this: {cite}`1987:nelson` + +`test single tick` + +``test double tick`` + +Moreoever, you can insert a bibliography into your page with this syntax: +The `{bibliography}` directive must be used for all the `{cite}` roles to +render properly. +For example, if the references for your book are stored in `references.bib`, +then the bibliography is inserted with: + +```` +```{bibliography} references.bib +``` +```` + + +Resulting in a rendered bibliography that looks like: + +```{bibliography} references.bib +``` + ++++ + +### Executing code in your markdown files + +If you'd like to include computational content inside these markdown files, +you can use MyST Markdown to define cells that will be executed when your +book is built. Jupyter Book uses *jupytext* to do this. + +First, add Jupytext metadata to the file. For example, to add Jupytext metadata +to this markdown page, run this command: + +``` +jupyter-book myst init markdown.md +``` + +Once a markdown file has Jupytext metadata in it, you can add the following +directive to run the code at build time: + +```` +```{code-cell} +print("Here is some code to execute") +``` +```` + +When your book is built, the contents of any `{code-cell}` blocks will be +executed with your default Jupyter kernel, and their outputs will be displayed +in-line with the rest of your content. + +For more information about executing computational content with Jupyter Book, +see [The MyST-NB documentation](https://myst-nb.readthedocs.io/). diff --git a/_build/html/_sources/notebooks.ipynb b/_build/html/_sources/notebooks.ipynb new file mode 100644 index 0000000..6ea0f4a --- /dev/null +++ b/_build/html/_sources/notebooks.ipynb @@ -0,0 +1,39 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Jupyter Notebook Files" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.2" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/_build/html/_static/basic.css b/_build/html/_static/basic.css new file mode 100644 index 0000000..616111c --- /dev/null +++ b/_build/html/_static/basic.css @@ -0,0 +1,855 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 270px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 450px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dt:after { + content: ":"; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0.5em; + content: ":"; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +div.doctest > div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.descname { + background-color: transparent; + font-weight: bold; + font-size: 1.2em; +} + +code.descclassname { + background-color: transparent; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/_build/html/_static/clipboard.min.js b/_build/html/_static/clipboard.min.js new file mode 100644 index 0000000..02c549e --- /dev/null +++ b/_build/html/_static/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.4 + * https://zenorocha.github.io/clipboard.js + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return function(n){var o={};function r(t){if(o[t])return o[t].exports;var e=o[t]={i:t,l:!1,exports:{}};return n[t].call(e.exports,e,e.exports,r),e.l=!0,e.exports}return r.m=n,r.c=o,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=function(){function o(t,e){for(var n=0;n