Skip to content

Grassland Bird Habitat

Introduction

This tutorial aims to answer the question:

In 2016, where was the best potential habitat for grassland birds in the Champlain Valley that was owned by Middlebury College?

To answer this question, we will develop a model based on these guidelines developed by the Vermont Agency of Natural Resources.

Background

The Bobolink (Dolichonyx oryzivorus) is a grassland bird species with a bubbling song and a remarkable life cycle. Bobolinks winter in South America, primarily Paraguay, Argentina, and Bolivia. In the spring, they migrate back to their breeding habitats in North America, including grassland habitat here in the Champlain Valley. Interestingly, Bobolinks seem to have keen spatial memory and sense of place; they tend to return to the same specific field each summer to breed and research indicates that this “site fidelity” improves breeding success.

Bobolink

source: iNaturalist

Bobolinks are also an interesting example of a “new native” species. During Abenaki times, Bobolinks did not breed in Vermont, because there was very little grassland habitat for them to do so. Open, grassy habitat was uncommon in what we now call the Champlain Valley; the landscape here was largely forested, save for the margins of water bodies and places where Abekai cultivated crops or set fires at a frequency that prevented trees from growing. Following the American Revolution, white migrants appropriated Abenaki lands in the Champlain Valley and pitched farms, claiming the land by clearing it of trees. This created large expanses of open habitat in the formerly forested landscape. Bobolinks soon colonized this new habitat, migrating from native breeding territories on the midwestern prairies of North America.

Today, Vermont plays an important role in the conservation of Bobolinks and other native North American grassland species. Since the 1940s, breeding populations of Bobolinks have significantly declined across North America, primarily from habitat loss caused by both changes in agricultural practices and the conversion of agricultural land into other land uses.

This tutorial develops a model with Earth Engine to identify where Middlebury College owns land that could contribute to the conservation of native North American grassland bird species by protecting the open structure of the habitat and working with farmers to adapt land use practices that do not conflict with breeding cycles of grassland birds.

Criteria

According to the ANR guidelines, the best potential habitat for Bobolink and other grassland bird species should meet the following criteria:

  1. Open land cover (grass/shrub, water, bare);
  2. Buffered from the edge, or with a core area that is at least 50 meters from closed habitat structure (tree canopy) or developed land (roads, buildings, pavement, etc);
  3. Large, or at least 20 acres in area;
  4. With a large interior, or a perimeter-area ratio of 0.015 or less.

Workflow overview

The diagram below shows the general workflow for the model, or how each step in the tutorial connects to other steps. The color represents the format of the result (or output) of each step as shown below.

graph TD
  vector[vector] ;
  raster[raster] ;
  task[task] ;

style vector fill:#E1C3E6,stroke-width:0px
style raster fill:#C5E6A1,stroke-width:0px
style task fill:#ADD8E6,stroke-width:0px

Here is how each step in the workflow connects to another step.

graph LR
  step01[1] ;
  step02[2] ;
  step03[3] ;
  step04[4] ;
  step05[5] ;
  step06[6] ;
  step07[7] ;
  step08[8] ;
  step09[9] ;
  step10[10] ;
  step11[11] ;
  step12[12] ;
  step13[13] ;
  step14[14] ;
  step15[15] ;
  step16[16] ;

  step01 --> step02 --> step03  
  step04 --> step05
  step03 --> step06
  step05 --> step06
  step06 --> step07 
  step07 --> step08  
  step08 --> step09
  step02 --> step10
  step09 --> step10  
  step09 --> step11
  step11 --> step12
  step03 --> step12
  step12 --> step13  
  step02 --> step13
  step13 --> step14  
  step14 --> step15
  step15 --> step16

  style step01 fill:#E1C3E6,stroke-width:0px
  style step02 fill:#E1C3E6,stroke-width:0px
  style step03 fill:#E1C3E6,stroke-width:0px
  style step04 fill:#C5E6A1,stroke-width:0px
  style step05 fill:#C5E6A1,stroke-width:0px
  style step06 fill:#C5E6A1,stroke-width:0px
  style step07 fill:#C5E6A1,stroke-width:0px
  style step08 fill:#C5E6A1,stroke-width:0px
  style step09 fill:#C5E6A1,stroke-width:0px
  style step10 fill:#E1C3E6,stroke-width:0px
  style step11 fill:#C5E6A1,stroke-width:0px
  style step12 fill:#E1C3E6,stroke-width:0px
  style step13 fill:#E1C3E6,stroke-width:0px
  style step14 fill:#E1C3E6,stroke-width:0px
  style step15 fill:#E1C3E6,stroke-width:0px
  style step16 fill:#ADD8E6,stroke-width:0px

The connections are made because the output of one step provides an input or argument for another step. This makes the workflow one long chain, or a series of connected input-method-output links.

The videos below walk you through each step in this workflow.

Start a new script

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//  Grassland bird habitat on Middlebury College Lands in Champlain Valley. 
//  
//  Jeff Howarth 
//  Sept 30, 2023
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1. Load feature collection and filter by attribute

template

// Load feature collection and filter by attribute.    

var output = ee.FeatureCollection("path")
  .filter(ee.Filter.eq("propertyKey", "value"))
;

diagram

graph LR
  method1["ee.FeatureCollection()"] ;
  arg_att1([pathname\n\nSTRING]) --> method1;

  method1 --> method2[".filter()"];
  method2 --> method3(["ee.Filter.eq()"]);

  method3 --> output>output\n\nFEATURE COLLECTION];

  arg_att2([property key\n\nSTRING]) --> method3;
  arg_att3([value\n\nSTRING]) --> method3;

  style method1 fill:#ADD8E6,stroke-width:0px
  style method2 fill:#ADD8E6,stroke-width:0px
  style method3 fill:#ADD8E6,stroke-width:0px
  style output fill:#E1C3E6,stroke-width:0px
  style arg_att1 fill:#DCDCDC,stroke-width:0px
  style arg_att2 fill:#DCDCDC,stroke-width:0px
  style arg_att3 fill:#DCDCDC,stroke-width:0px

demo

demo code

// ---------------------------------------------------------------------------
//  1. Load feature collection and filter by attribute.
//
//  Isolate Champlain Lowlands.
// ---------------------------------------------------------------------------

var region = ee.FeatureCollection("projects/conservation-atlas/assets/regions/Ecoregion_07232023");

print(
  "STEP 1:"
  )
;

Map.addLayer();

2. Load feature collection and filter by location

template

// Load feature collection and filter by location.  

var output = ee.FeatureCollection("path")
  .filterBounds(target)
;

diagram

graph LR
  method1["ee.FeatureCollection()"] ;
  arg_att1([path\n\nSTRING]) --> method1;

  method1 --> method2[".filterBounds()"];
  method2 --> output>output\n\nFEATURE COLLECTION];

  arg_att2([target\n\nGEOMETRY or FEATURE]) --> method2;

  style method1 fill:#ADD8E6,stroke-width:0px
  style method2 fill:#ADD8E6,stroke-width:0px
  style output fill:#E1C3E6,stroke-width:0px
  style arg_att1 fill:#DCDCDC,stroke-width:0px
  style arg_att2 fill:#E1C3E6,stroke-width:0px

demo

demo code

// ---------------------------------------------------------------------------
//  2. Load feature collection and filter by location,
//
//  Isolate College Lands in Champlain Valley.
// ---------------------------------------------------------------------------

var college_lands = ee.FeatureCollection("projects/conservation-atlas/assets/cadastre/Midd_College_Parcels_withattributes");

print(
  "STEP 2:"
  )
;

Map.centerObject();
Map.setOptions();

Map.addLayer();

3. Define study region

template

// Define study region  

var output = FC
  .union(maxError)       
  .geometry() 
  .bounds(maxError) 
  .buffer(distance, maxError)
;

diagram

graph LR
  input[/input\n\nFEATURE COLLECTION/] --> method1[".union()"] ;

  method1 --> method2[".geometry()"];
  method2 --> method3[".bounds()"];
  method3 --> method4[".buffer()"]
  method4 --> output>output\n\nGEOMETRY];

  arg_att1([maxError\n\nNUMBER]) --> method1 ;
  arg_att2([maxError\n\nNUMBER])  --> method3 ;
  arg_att3([distance\n\nNUMBER])  --> method4 ;
  arg_att4([maxError\n\nNUMBER])  --> method4 ;


  style input fill:#E1C3E6,stroke-width:0px
  style method1 fill:#ADD8E6,stroke-width:0px
  style method2 fill:#ADD8E6,stroke-width:0px
  style method3 fill:#ADD8E6,stroke-width:0px
  style method4 fill:#ADD8E6,stroke-width:0px
  style output fill:#E1C3E6,stroke-width:0px
  style arg_att1 fill:#DCDCDC,stroke-width:0px
  style arg_att2 fill:#DCDCDC,stroke-width:0px
  style arg_att3 fill:#DCDCDC,stroke-width:0px
  style arg_att4 fill:#DCDCDC,stroke-width:0px

demo

demo code

// ---------------------------------------------------------------------------
// 3. Define study region
// ---------------------------------------------------------------------------

var bounds ;

print(
  "STEP 3:",
  bounds
  )
;

Map.addLayer();

4. Load an image

template

// Load an image.  

var output = ee.Image("path")
;

diagram

graph LR
  method1["ee.Image()"] ;
  arg_att1([path\n\nSTRING]) --> method1;
  method1 --> output>output\n\nIMAGE];

  style method1 fill:#ADD8E6,stroke-width:0px
  style output fill:#C5E6A1,stroke-width:0px
  style arg_att1 fill:#DCDCDC,stroke-width:0px

demo

demo code

// ---------------------------------------------------------------------------
//  4. Load an image
//
//  Import land cover image for Vermont.
// ---------------------------------------------------------------------------

var lc ;

var lc_viz = {
  min: 1,
  max: 8,
  palette: [
    '#ABD998',    //   1. Tree Canopy  
    '#EBF09C',    //   2. Grass/Shrub 
    '#f7f7f7',    //   3. Bare soil
    '#95E6D5',    //   4. Water
    '#525252',    //   5. Buildings    
    '#F7F7F7',    //   6. Roads
    '#cccccc',    //   7. 0ther pavement
    '#F7F7F7',    //   8. Railroads  
    ]
  };

print(
  "STEP 4:", 
  lc,
  lc.projection()
  )
;

Map.addLayer();

5. Reclassify an image

template

// Reclassify an image.  

var output = input.remap(
  ["o","l","d"],
  ["n","e","w"],
);

diagram

graph LR
  input[/input\n\nIMAGE/] --> method1[".remap()"] ;
  arg_att1([old values\n\nLIST]) --> method1;
  arg_att2([new values\n\nLIST]) --> method1;
  method1 --> output>output\n\nIMAGE];

  style input fill:#C5E6A1,stroke-width:0px
  style method1 fill:#ADD8E6,stroke-width:0px
  style output fill:#C5E6A1,stroke-width:0px
  style arg_att1 fill:#DCDCDC,stroke-width:0px
  style arg_att2 fill:#DCDCDC,stroke-width:0px

demo

demo code

// ---------------------------------------------------------------------------
//  5. Reclassify an image
//
//  Make a binary image of grasslands.  
// ---------------------------------------------------------------------------

var lc_binary ;

print(
  "STEP 5:",
  lc_binary,
  lc_binary.projection()
  )
;

Map.addLayer();

6. Clip image by region

template

// Clip image by region.  

var output = input.clip(region)
;

diagram

graph LR
  input[/input\n\nIMAGE/] --> method1[".clip()"] ;
  arg_att1([region or aoi\n\nGEOMETRY, FEATURE or\nFEATURE COLLECTION]) --> method1;
  method1 --> output>output\n\nIMAGE];

  style input fill:#C5E6A1,stroke-width:0px
  style method1 fill:#ADD8E6,stroke-width:0px
  style output fill:#C5E6A1,stroke-width:0px
  style arg_att1 fill:#DCDCDC,stroke-width:0px

demo

demo code

// ---------------------------------------------------------------------------
//  6. Clip image by region
//
//  Isolate grasslands in study region. 
// ---------------------------------------------------------------------------

var lc_binary_bounds ;

print(
  "STEP 6:",
  lc_binary_bounds,
  lc_binary_bounds.projection()
  )
;

Map.addLayer();

7. Select by pixel value

template

// Select a pixel value (make a binary).

var output = input.ee(value)
;

diagram

graph LR
  input[/input\n\nIMAGE/] --> method1[".eq()"] ;
  arg_att1([value\n\nNUMBER]) --> method1;
  method1 --> output>output\n\nIMAGE];

  style input fill:#C5E6A1,stroke-width:0px
  style method1 fill:#ADD8E6,stroke-width:0px
  style output fill:#C5E6A1,stroke-width:0px
  style arg_att1 fill:#DCDCDC,stroke-width:0px

demo

demo code

// ---------------------------------------------------------------------------
//  7. Select by pixel value.
//
//  Invert the grassland binary. 
// ---------------------------------------------------------------------------

var invert_binary ;

print(
  "STEP 7:",
  invert_binary,
  invert_binary.projection()
  )
;

Map.addLayer();

8. Compute distance

template

// Compute distance with a euclidean kernel.   

var output = input
  .distance(
    ee.Kernel.euclidean(radius, "units")
  )
  .reproject("crs")       // When should you comment out this line?
  .unmask(value)          
)

diagram

graph LR
  input[/input\n\nIMAGE/] --> method1[".distance()"] ;
  method1 --> method2(["ee.Kernel.euclidean()"])
  arg_att1([radius\n\nNUMBER]) --> method2;
  arg_att2([units\n\nSTRING]) --> method2;
  method2 --> method3[".reproject()"]
  arg_att3([crs\n\nSTRING]) --> method3;
  method3 --> method4(".unmask()")
  arg_att4([value\n\nNUMBER]) --> method4;
  method4 --> output>output\n\nIMAGE];

  style input fill:#C5E6A1,stroke-width:0px
  style method1 fill:#ADD8E6,stroke-width:0px
  style method2 fill:#ADD8E6,stroke-width:0px
  style method3 fill:#ADD8E6,stroke-width:0px
  style method4 fill:#ADD8E6,stroke-width:0px
  style output fill:#C5E6A1,stroke-width:0px
  style arg_att1 fill:#DCDCDC,stroke-width:0px
  style arg_att2 fill:#DCDCDC,stroke-width:0px
  style arg_att3 fill:#DCDCDC,stroke-width:0px
  style arg_att4 fill:#DCDCDC,stroke-width:0px

demo

demo code

// ---------------------------------------------------------------------------
//  8. Compute distance 
//
//  Calculate distance from edge of grasslands towards interior
// ---------------------------------------------------------------------------

var crs = "EPSG: 32145"; // Vermont State Plane North American Datum 1983

var grassland_distance ;

print(
  "Step 8:",
  grassland_distance,
  grassland_distance.projection()
  )
;

// Here is a nice palette that looks good for distance when you reverse it.

var inferno = ["#000004", "#320A5A", "#781B6C", "#BB3654", "#EC6824", "#FBB41A", "#FCFFA4"].reverse();

Map.addLayer();

9. Select by a threshold value

template

// Select by threshold value (and output a binary).

var output = input.gt(value)
;

diagram

graph LR
  input[/input\n\nIMAGE/] --> method1[".gt()"] ;
  arg_att1([value\n\nNUMBER]) --> method1;
  method1 --> output>output\n\nIMAGE];

  style input fill:#C5E6A1,stroke-width:0px
  style method1 fill:#ADD8E6,stroke-width:0px
  style output fill:#C5E6A1,stroke-width:0px
  style arg_att1 fill:#DCDCDC,stroke-width:0px

demo

demo code

// ---------------------------------------------------------------------------
//  9. Select by threshold value 
//
//  Isolate all pixels that are greater than 50 meters from grassland edge. 
// ---------------------------------------------------------------------------

var grassland_cores ;

print(
  "Step 9:",
  grassland_cores,
  grassland_cores.projection()
  )
;

Map.addLayer();

10. Zonal overlay

template

// Zonal overlay.

var output = input.reduceRegions(
  {
    collection: cutter,
    reducer: ee.Reducer(),
    scale: number,
    crs: "string"
  }
;

diagram

graph LR
  input[/"input 'dough'"\n\nIMAGE/] --> method1[".reduceRegions()"] ;
  arg_att1(["collection 'cutter'"\n\nFEATURE COLLECTION]) --> method1;
  arg_att2([reducer\n\nREDUCER]) --> method1;
  arg_att3([scale\n\nNUMBER]) --> method1;
  arg_att4([crs\n\nSTRING]) --> method1;
  method1 --> output>output\n\nFEATURE COLLECTION];

  style input fill:#C5E6A1,stroke-width:0px
  style method1 fill:#ADD8E6,stroke-width:0px
  style output fill:#E1C3E6,stroke-width:0px
  style arg_att1 fill:#E1C3E6,stroke-width:0px
  style arg_att2 fill:#DCDCDC,stroke-width:0px
  style arg_att3 fill:#DCDCDC,stroke-width:0px
  style arg_att4 fill:#DCDCDC,stroke-width:0px

demo

demo code

// ---------------------------------------------------------------------------
//  10. Zonal overlay 
//
//  Find college parcels that overlap core grassland habitat. 
// ---------------------------------------------------------------------------

var college_with_core ;

var college_with_core_filter ;

print(
  "STEP 10:",
  college_with_core.size(),
  college_with_core_filter.size()
  )
;

Map.addLayer();

11. Mask an image.

template

Case 1: to use an image to mask another image.

/// Use an image to mask another image.  

var output = input.updateMask(mask)
;

Case 2: to use an image to mask itself.

/// Use an image to mask itself.  

var output = input.selfMask()
;

diagram

Case 1: to use an image to mask another image.

graph LR
  input[/input\n\nIMAGE/] --> method1[".updateMask()"] ;
  arg_att1([mask\n\nIMAGE]) --> method1;
  method1 --> output>output\n\nIMAGE];

  style input fill:#C5E6A1,stroke-width:0px
  style method1 fill:#ADD8E6,stroke-width:0px
  style output fill:#C5E6A1,stroke-width:0px
  style arg_att1 fill:#C5E6A1,stroke-width:0px

Case 2: to use an image to mask itself.

graph LR
  input[/input\n\nIMAGE/] --> method1[".selfMask()"] ;
  method1 --> output>output\n\nIMAGE];

  style input fill:#C5E6A1,stroke-width:0px
  style method1 fill:#ADD8E6,stroke-width:0px
  style output fill:#C5E6A1,stroke-width:0px

demo

demo code

// ---------------------------------------------------------------------------
//  11. Mask an image
//
//  Ignore all pixels that are not grasslands. 
// ---------------------------------------------------------------------------

var grassland_cores_masked;      

print(
  "STEP 11:",
  grassland_cores_masked,
  grassland_cores_masked.projection()
  )
;

Map.addLayer();

12. Make objects

template

// Make objects from a binary image. 

var output = input.reduceToVectors(
  {
    reducer: ee.Reducer(),
    geometry: aoi, // area of interest   
    scale: number,
    geometryType: "string",
    eightConnected: boolean,  
    maxPixels: 1e12, 
    geometryInNativeProjection: boolean 
  }
);

diagram

graph LR
  input[/input\n\nIMAGE/] --> method1[".reduceToVectors()"] ;
  method1 --> output>output\n\nFEATURE COLLECTION];

  arg_att1([reducer\n\nREDUCER]) --> method1;
  arg_att2([aoi\n\nGEOMETRY]) --> method1;
  arg_att3([scale\n\nNUMBER]) --> method1;
  arg_att4([geometryType\n\nSTRING]) --> method1;
  arg_att5([eightConnected\n\nBOOLEAN]) --> method1;
  arg_att6([maxPixels\n\nNUMBER]) --> method1;
  arg_att7([geometryInNativeProjection\n\nBOOLEAN]) --> method1;

  style input fill:#C5E6A1,stroke-width:0px
  style method1 fill:#ADD8E6,stroke-width:0px
  style output fill:#E1C3E6,stroke-width:0px

  style arg_att1 fill:#ADD8E6,stroke-width:0px
  style arg_att2 fill:#E1C3E6,stroke-width:0px
  style arg_att3 fill:#DCDCDC,stroke-width:0px
  style arg_att4 fill:#DCDCDC,stroke-width:0px
  style arg_att5 fill:#DCDCDC,stroke-width:0px
  style arg_att6 fill:#DCDCDC,stroke-width:0px
  style arg_att7 fill:#DCDCDC,stroke-width:0px

demo

demo code

// ---------------------------------------------------------------------------
//  12. Make objects. 
//
//  Identify contiguous regions of grassland. 
// ---------------------------------------------------------------------------

var grassland_objects ;

print(
  "STEP 12:",
  grassland_objects
  )
;

Map.addLayer();

13. Select by location

template

// Select by location.  

var output = input
  .filterBounds(target)
;

diagram

graph LR
  input[/input\n\nFEATURE COLLECTION/] --> method2[".filterBounds()"];
  method2 --> output>output\n\nFEATURE COLLECTION];

  arg_att1([target\n\nGEOMETRY or FEATURE]) --> method2;

  style input fill:#E1C3E6,stroke-width:0px  
  style method2 fill:#ADD8E6,stroke-width:0px
  style output fill:#E1C3E6,stroke-width:0px
  style arg_att1 fill:#E1C3E6,stroke-width:0px

demo

demo code

// ---------------------------------------------------------------------------
//  13. Select by location.
//
//  Isolate grasslands on College Lands. 
// ---------------------------------------------------------------------------

var college_grasslands ;

print(
  "STEP 13:",
  college_grasslands.size(),
  college_grasslands.first()
  )
;

Map.addLayer();

14. Map function over collection

template

// Step 1: Write a function that takes a feature input. 

var myFunction = function(feature) {

  var crs = string ; 
  var area = feature.area(1, crs) ;

  return feature.set("area", area) ;
}

// Step 2: Apply the function to every feature in a collection.   

var output = input.map(myFunction)
;

diagram

graph LR
  input[/input\n\nFEATURE COLLECTION/] --> method2[".map()"];
  method2 --> output>output\n\nFEATURE COLLECTION];

  arg_att1([getArea\n\nFUNCTION]) --> method2;

  style input fill:#E1C3E6,stroke-width:0px  
  style method2 fill:#ADD8E6,stroke-width:0px
  style output fill:#E1C3E6,stroke-width:0px
  style arg_att1 fill:#ADD8E6,stroke-width:0px

demo

demo code

// ---------------------------------------------------------------------------
//  14. Compute spatial attributes.
//
//  Calculate area and perimeter-area ratios.
// ---------------------------------------------------------------------------

var getArea = function(f) {
  var crs = "EPSG: 32145"; // Vermont State Plane North American Datum 1983
  var area = f.area(1, crs).divide(4046.86);
  var pa = f.perimeter(1, crs).divide(f.area(1, crs));
  return f.set({"area": area, "pa": pa});
};

var grasslands_with_criteria ;

print(
  "STEP 14:",
  grasslands_with_criteria.size(),
  grasslands_with_criteria.first()
  )
;

Map.addLayer();

15. Select by two attributes

template

// Select features from a collection by two attributes.

var output = input.filter(
  ee.Filter.and(
    ee.Filter.first("property","value"),
    ee.Filter.second("property","value")
  )
);

diagram

graph LR
  input[/input\n\nFEATURE COLLECTION/] --> method1[".filter()"];
  method1 --> method2(["ee.Filter.and()"])

  method3(["ee.Filter.gt()"]) --> method2;
  method4(["ee.Filter.lte()"]) --> method2;

  arg_att1([property\n\nSTRING]) -->method3;
  arg_att2([value\n\nNUMBER]) -->method3;

  arg_att3([property\n\nSTRING]) -->method4;
  arg_att4([value\n\nNUMBER]) -->method4;

  method2 --> output>output\n\nFEATURE COLLECTION];


  style input fill:#E1C3E6,stroke-width:0px  
  style method1 fill:#ADD8E6,stroke-width:0px
  style method2 fill:#ADD8E6,stroke-width:0px
  style method3 fill:#ADD8E6,stroke-width:0px
  style method4 fill:#ADD8E6,stroke-width:0px
  style output fill:#E1C3E6,stroke-width:0px
  style arg_att1 fill:#DCDCDC,stroke-width:0px
  style arg_att2 fill:#DCDCDC,stroke-width:0px
  style arg_att3 fill:#DCDCDC,stroke-width:0px
  style arg_att4 fill:#DCDCDC,stroke-width:0px

demo

demo code

// ---------------------------------------------------------------------------
//  15. Select by two attributes
//
//  Identify grasslands that meet both criteria.
// ---------------------------------------------------------------------------

var best_grassland_habitat ;

print(
  "STEP 15:",
  best_grassland_habitat.size(),
  best_grassland_habitat.first()
  )
;

Map.addLayer();

16. Export to EE Asset

template

// Export feature collection to Asset.  

Export.table.toAsset({
  collection: FeatureCollection, 
  description: "string", 
  assetId: "string"
  }
);

diagram

graph LR
  method1["Export.table.toAsset()"] --> output>output\n\nTASK];

  arg_att1([collection\n\nFEATURE COLLECTION]) --> method1;
  arg_att2([description\n\nSTRING]) --> method1
  arg_att3([assetId\n\nSTRING]) --> method1

  style method1 fill:#ADD8E6,stroke-width:0px
  style output fill:#ADD8E6,stroke-width:0px
  style arg_att1 fill:#E1C3E6,stroke-width:0px
  style arg_att2 fill:#DCDCDC,stroke-width:0px
  style arg_att3 fill:#DCDCDC,stroke-width:0px

demo

demo code

// ---------------------------------------------------------------------------
//  16. Export to EE Asset
//
//  To run workflow with crs condition on distance (Step 10).
// ---------------------------------------------------------------------------

var x_name = "Best_college_grasslands_0930_2023"; 

Export.table.toAsset({
  collection: best_grassland_habitat, 
  description: x_name, 
  assetId: x_name
  }
);

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 4.0 International License.