1 Introduction

In this module, we will discuss the following concepts:

  1. Working with remotely sensed imagery of the ocean.

  2. Creating a video from an image time series.

  3. Time Series Analysis in GEE.

  4. Adding basic elements to the graphical user interface.

2 Background

The Deepwater Horizon oil spill is considered to be the largest accidental marine oil spill ever. The well released over 4.9 million barrels of oil of which 4.1 million barrels went into the Gulf of Mexico between April 20th and July 15th of 2010. Efforts were taken to reduce the impact of the spill by burning or skimming the oil on the ocean’s surface and by releasing over 1.84 million gallons of the chemical dispersant (Corexit) on the surface of the ocean and directly into the stream of oil being emitted at the well some 5,000 feet beneath the ocean surface. Even with these efforts, the oil spill has significantly affected the Gulf’s coastal and marine ecosystems. While extensive efforts were taken to evaluate the effects of the oil in these ecosystems, the massive area effected by the spill made it difficult. In this module we are going to conduct our own exploration of the ecological impact of this spill by monitoring the trend in algal concentration over time within an area highly impacted by the spill. As algae are the primary producers in marine ecosystems, monitoring how their populations were affected by this change may help us better understand the overall effect of the oil on the state of the affected ecosystems.



A wildlife biologist observing the oil-soaked sargassum, known as gulfweed. This represents is a loss of habitat for many small marine creatures. Credit: U.S. National Response Team

3 Trend Analysis in GEE

3.1 Monitoring Oil Directly with Remote Sensing

Remote sensing has a limited ability to detect oil directly. This is because oil reflects light in much the same way as water. However, oil does affect the surface roughness of the water. Areas with high concentrations of oil can smooth the surface of ocean. As a result, most of the remote sensing effort to detect oil after the Deepwater Horizon spill have involved airborne RADAR, an active sensor which can capture the texture of a surface. Unfortunately, these data are not available within GEE. While passive sensors are not well suited for the direct detection of oil on water, the remote sensing professionals on the NASA MODIS Rapid Response Team used the smoothing quality of oil to detect it in a very clever way.

3.2 Sunglint

Depending on the relationship between the angle of the sun and the sensor, the surface of a water body can effectively work as a mirror by reflecting most of the light directly back at the sensor. This process is referred to as sunglint and it is a consistent challenge when working with remotely sensed imagery of water. Sunglint effectively alters all the data about the surface it is covering because the energy reaching the sensor is simply a direct reflection of the sunlight not a subset of light based on what the surface absorbed and reflected. We know that oil has the ability to smooth the surface of the water and when this occurs within a sunglint area the oil covered surface reflects more light then water alone. This means oil will shine brighter than water in sunglint areas. The image below was captured by the Aqua MODIS sensor and clearly shows the extent of the sunglint oil 35 days after this initial release of oil from the Deepwater Horizon spill. The upper left corner is the Mississippi River delta.



An image of the sunglint area containing large amounts of surface oil. You can observe the changes in the reflectance of the oil as you move away from the center of the sunglint (right side of the image). Credit: NASA Earth Observatory

Because we know the sensor (MODIS) and the date, let us try to replicate this image in GEE.

// A point representing the general location of deepwater horizon oil rig.
var dw = ee.Geometry.Point([-88.36555556,28.73805556]);

// Pull in MODIS Aqua imagery and visualize the sunglint oil.
var mod2 = ee.ImageCollection("MODIS/006/MYD09GA")
  .filterDate("2010-05-25","2010-05-26");

// Add to map.
Map.addLayer(mod2, {bands: ["sur_refl_b01","sur_refl_b04","sur_refl_b03"],
gamma: 1,
max: 10278.86,
min: 192.14000000000001,
opacity: 1}, "mod2");

// Add Deepwater Horizon location to map.
Map.addLayer(dw,{},"DWH");
// Set map to center on deep water horizon location
Map.setCenter(-88.36555556,28.73805556, 8);


A replication of the MODIS image above created in GEE. You can adjust the gamma to brighten the image slightly.

This image shows that the oil has spread extensively during the first month of the spill. In GEE, MODIS imagery is available at the surface reflectance level of pre-processing. Details on when you should use surface reflectance imagery can be found in Module 5. While this is great for making comparisons over time, it means that some elements of the image that have very high reflectance values are actually masked out as part of the preprocessing of the images. This includes areas of sunglint oil in the case of the image above. Considering this, conducting a robust, quantitative assessment of oil extent based on MODIS imagery is not feasible. Still, this is a striking image that can be used to build interest in the story of one of the largest environmental disasters in United States history. This spill leaked oil for over 100 days and it is a major ecological disaster that took the lives of 11 people.

While not as clear, the image below also shows the plume of smoke visible the day after the initial explosion. The Deepwater Horizon drill rig burned for two days before sinking to the bottom of the ocean.

// Pull in MODIS aqua imagery and filter for specific date.
var smokePlume = ee.ImageCollection("MODIS/006/MYD09GA")
  .filterDate("2010-04-21","2010-04-22");

// Add to map.
Map.addLayer(smokePlume, {bands: ["sur_refl_b01","sur_refl_b04","sur_refl_b03"],
gamma: 1.32,
max: 3278.86,
min: 192.14000000000001,
opacity: 1}, "smokePlume");


While not the best quality image, the lighter area in the ocean to the south east of the sediment rich outlet of the Mississippi River is the smoke from the burning Deepwater Horizon oil rig.

There is a lot of qualitative value in this imagery and to get at that quickly we are going to make a time lapse movie of the MODIS imagery during the period when oil was actively leaking.

4 Video of Landscape Change

GEE started as a project to develop a cloud-free mosaic of the globe using Landsat imagery. This product became the base map for Google Earth. Once the cloud-free mosaic was created, the next products produced using the GEE infrastructure were time lapse videos of major landscape change. These videos are very engaging and somewhat frightening depictions of the drastic changes occurring on the surface of our planet. It is worth spending a few minutes looking at some of the pre-made examples.

To create one of these videos we need to accomplish three things.

  1. Define a regions of interest.

  2. Pull in images along a date range.

  3. Define visualization parameters.

To create the region of interest, we will buffer around the previous location of the Deepwater Horizon drill rig. GEE will use the dimensions of the buffer area to set the bounding box for the video. Basically, we still end up with a square even though our shape on the map is a circle. Add the following code to your existing script to get started.

// Buffer around the deep water horizon site.
var buffer = dw.buffer({distance:150000} );

Map.addLayer(buffer, {}, 'buffer');

We will continue to use Aqua MODIS surface reflectance imagery and use our previously defined visualization parameters. In this case, we are selecting images over a four month period. There will be approximately 120 images in the video. Add the following code to your script.

// Define the visualization parameters.
var vis = {gamma: 1,
max: 10278.86,
min: 192.14000000000001,
opacity: 1};


var collection = ee.ImageCollection("MODIS/006/MYD09GA")
  // Get four months of imagery.
  .filterDate('2010-04-01','2010-7-30')
  // Need to have 3-band imagery for the video.
  .select(['sur_refl_b01', 'sur_refl_b04', 'sur_refl_b03'])
  // Use the map function to apply the same visualizations to all images.
  .map(function(image) {
    return image.visualize(vis);
  });

Map.addLayer({eeObject: collection, name:'Video images'});  

With these elements in place the last step is to export the video. This works just as any other export function in GEE but there are some unique parameters, which are specific to the video quality.

Dimensions: The pixel resolution of the video. 720 by 720 is assumed when providing a single number.

FramesPerSecond: defines the number of images displayed per second. We are displaying about 120 images, so at four frames per second our video will be about 30 seconds long. If you want to use this video for more qualitative assessment you could drop it to as low as 1 frame per second. Add the code to your existing script.

// Export (change dimensions or scale for higher quality).
Export.video.toDrive({
  collection: collection,
  description: 'modisDWH',
  dimensions: 720,
  framesPerSecond: 4,
  region: buffer
});

As with any export from GEE you will need to execute this process by selecting the run button in the task pane after you run the script. Exporting this video will take some time. Depending on your connection speed and the parameters you selected for the video, expect this process to take between 10 and 20 minutes. Creating a video of your area of study can give you an interesting and engaging resource that showcases some of the character of this region. The video will make it clear the Gulf of Mexico is a generally cloudy place but there will be images where the sunglint oil shines brightly. An example of the video can be found here.

In the next step of this module were going to look into more quantitative methods for comparing the photosynthetic activity of this region over time.

5 Ecological Impact of the Deepwater Horizon Spill



Based on field survey data, this map shows the latency of oil on the ocean in the Gulf of Mexico and the severity of oil along the coast. While no scale bar is present, Baton Rouge and Pensacola are approximately 250 miles apart. Credit: U.S. National Response Team

As the image above illustrates, the primary impact of the Deepwater Horizon oil spill was the persistence of the oil in the ecosystem. With the well open for over 100 days, the oil appeared across a vast area of the Gulf of Mexico due to the changing ocean currents and weather conditions. Measuring the actual ecological impact is a real challenge because oil was present at so many places on the ocean surface and affected species across trophic levels. We will be attempting to monitor the effect of the spill on the photosynthetic algae that forms the base of the marine food web in the Gulf of Mexico.

5.1 Algal Blooms

The Deepwater Horizon event is an example of point source pollution. But the Gulf of Mexico, specifically around the Mississippi River delta, has been dealing with non-point source pollution for some time. The Mississippi River drains roughly a third of the land mass in the United States and much of this area is under intensive agricultural development. To grow plants, extra nutrients such as nitrogen and phosphorus are applied to the agricultural fields. While these nutrients are used by plants, some are washed out in precipitation events and eventually make it to the ocean. As a result, natural occurring algal populations receive extra nutrients and they bloom in tremendous numbers.

Spring time floods bring a tremendous about of sediment and dissolved nutrients into the Gulf of Mexico. This can dramatically increase algae populations along the coast. Algal blooms are visible as the light green color in the water along the coast. Credit: NASA Earth Observatory

The true color MODIS image above shows both sediment plumes (tan color) and algal blooms (light green color) from spring high water events throughout the Mississippi River delta. We are going to attempt to see if there is a measurable difference in the algal bloom extent and intensity during the year where oil was persistent on the ocean surface compared to the years where it was not.

5.2 MODIS Chlorophyll-a Product

The MODIS Aqua sensor that has been capturing imagery since 2000. During that time, the remote sensing community has also developed many content specific algorithms that are specifically designed for MODIS imagery. Many of the algorithms have been turned into pre-processed products that end users can engage with quickly in GEE. For the mapping of algal populations over time, we are going to rely on one of these pre-processed products available in GEE, Ocean Color SMI: Standard Mapped Image MODIS Aqua Data



Description of the MODIS Ocean Color image collection available in GEE.

The “chlor_a” band is a near-surface concentration of chlorophyll-a and is based on an empirical relationship between the blue and green bands of the MODIS sensor. Chlorophyll-a is the primary molecule responsible for photosynthesis and contributes to the green color in plants. By mapping chlorophyll-a concentration, we are working under the assumption that algae are the primary source of this molecule in this region of the ocean.

5.3 Differencing Two Years of Imagery

It is worthwhile to generate some simple visualizations of the ecological feature you are interested in as soon as you have the correct imagery to do so. We will do this by generating maps of chlorophyll-a density for both 2009 and 2010. We will also take the difference between these two images to visualize the spatial patterns in chlorophyll-a density between the two years.

We will filter our dataset a to capture the months that the oil well was actively leaking. Please open up a new script, starting with the following code.

// Set map to center on deep water horizon location
Map.setCenter(-88.36555556,28.73805556, 7);

// Define visualization parameters so the images are both presented in the same way.
var vis2 = {min:-7, max:14};

// Generate the based dataset for our processes.
var mod09 = ee.ImageCollection("NASA/OCEANDATA/MODIS-Aqua/L3SMI")
  .filterDate("2009-04-20","2009-07-31")
  .select("chlor_a")
  .median();
Map.addLayer(mod09, vis2, "09");

// Generate the based dataset for our processes.
var mod10 = ee.ImageCollection("NASA/OCEANDATA/MODIS-Aqua/L3SMI")
  .filterDate("2010-04-20","2010-07-31")
  .select("chlor_a")
  .median();
Map.addLayer(mod10, vis2, "10");

// Difference the model by subtracting.
var diff = mod10.subtract(mod09);
Map.addLayer(diff, {min:-6, max:6}, "diff");



Use the inspector tool to look at the difference in values. Darker areas suggest more algae is present in 2009, lighter areas suggest more algae is present in 2010.



The difference in algal concentrations between 2009 and 2010. Dark areas represent regions of decreased algal concentrations and light areas are regions of increase algal concentrations.

The very dark area may tip us off that the oil is having an effect on the algal productivity. But this is a complex system and it is wise to look at trends in the data rather than a direct comparison of just two time steps. We will examine two different methods for looking at the trend of algal productivity over time.

6 Trend Analysis Across the MODIS Collection

Trend analysis of remote sensing data is a large field of study. It is an important method because, in complex systems, singular events might be impactful in the short term but have little effect on ecosystem function over time due to the resilience of the systems. With the MODIS sensor we have data regarding algal concentrations from 2002 to present. We will be preparing these data using two different methods to highlight the variability in averages as well as daily measurements over time. Both methods highlight different trends and provide unique information on the effect of the oil spill on the algal populations.

6.1 An Median Value Approach.

In the image comparison approach above we looked at the difference between two images. In this example, we will develop a method that allows us to make a similar comparison across all years of available data. We will automate this process a bit by creating a dictionary of median reduced images from across the time period during which the oil well was leaking. We are using a custom built function to construct our image dictionary. This function requires some adaptation on the user’s part so we have included some descriptive text in the instructions so the user knows what exactly is needed. This is a great practice if you find yourself generating functions that are being used in many different situations by people other than you. Add the following code to your current script.

var constructMODDict = function(geometry)
  /*
  This function takes in a geometry feature from the GUI and uses it to
  generate a dictionary of median reduce images for the specified date range
  inputs
  geometry = geometry object representing you area of interest
  y_list = set based on sensor type
  imagecollection = unique id for collection type
  filterDate = cat() this is used to refine the month and day of start and end time
  With adaptation this should be flexible across sensors and times
  */
  {
  var startMonth = "-04-20";
  var endMonth = "-07-31";
  // Construct a dictionary for MODIS.
  var y_list = ee.List.sequence(2002, 2018);
  var ystr_list = y_list.map(function(y){return ee.Number(y).format('%1d')});
  var mod = y_list.map(function(y){return ee.ImageCollection('NASA/OCEANDATA/MODIS-Aqua/L3SMI')
                                          .filterDate(ee.String(ee.Number(y).format('%1d')).cat(startMonth),
                                                      ee.String(ee.Number(y).format('%1d')).cat(endMonth))
                                          .select("chlor_a")
                                          .median()
                                          .clip(geometry);
  })
  var mod_dict = ee.Dictionary.fromLists(ystr_list, mod);
  // Return MODIS dictionary.
  return mod_dict;
};

In short, this function pulls in all images over a set date range, selects a specific band, applies a median reducer, and clips the image to a geometry feature. We want to do this over multiple years, so we create a list of the years we want to cover. That list is converted to ee.Number objects, which is used to select and manipulate images for all the years in the list. When an image is created it is stored in a list. Then we convert that list to a dictionary which allows us to keep track of the image by defining its key to be the year that it represents. For more dictionary examples, see Module 10.

Running the function above brings the feature into memory. In the code below, we call the function and provide a geometry feature as the input. Create your own geometry feature that includes more of the shoreline of Louisiana, Mississippi, and Alabama. For reference, use the map of coastal areas impacted in Section 5 and make sure it includes a good 20 or 30 miles off ocean the coast. Algae are most prevalent in shallow waters but we want to be inclusive of potential habitat. Add the following code to your script to run the function.

// Apply function across the new geometry.
var elements = constructMODDict(geometry);
print(elements, "Image dictionary");

The image dictionary is a convenient feature to store our data because we can use keys that represent the year the image was captured to select images. This makes it easy to sort and understand what image you are working with. That said, dictionaries are not useful for displaying and running analysis on imagery. Because of this, we are going to create an image collection from our dictionary. Add the following code to your existing script.

// Convert the images in the dictionary to an image collection.
var collection2 = ee.ImageCollection.fromImages([
  ee.Image(elements.get('2002')),
  ee.Image(elements.get('2003')),
  ee.Image(elements.get('2004')),
  ee.Image(elements.get('2005')),
  ee.Image(elements.get('2006')),
  ee.Image(elements.get('2007')),
  ee.Image(elements.get('2008')),
  ee.Image(elements.get('2009')),
  ee.Image(elements.get('2010')),
  ee.Image(elements.get('2011')),
  ee.Image(elements.get('2012')),
  ee.Image(elements.get('2013')),
  ee.Image(elements.get('2014')),
  ee.Image(elements.get('2015')),
  ee.Image(elements.get('2016')),
  ee.Image(elements.get('2017')),
  ee.Image(elements.get('2018'))
  ]);

print(collection2)
Map.addLayer(collection2,{},'ic')

This is not an efficient method but, it does work. If you have a significantly large number images in your dictionary you would have to find a more creative method for creating this new image collection. One alternative to explore is the map() function in GEE, which works similarly to for loops or the lapply() function in R.

With the image collection added to the map we can use the inspector tool to select a location on the map and view a histogram of median chlorophyll-a concentrations at the selected location across a 17 year time period. The oil spill occurred in 2010 and our images start in 2002. This means that the eighth position on the histogram represents 2010. You can verify this by comparing the values on the histogram to the values in 2009 and 2010 rasters. The inspector tool will show the value of all imagery at the location you select.



A histogram showing median chlorophyll-a concentration at a selected location across all available MODIS imagery.

7 Conclusion

In this module, we developed a methodology that allows us to look at time series data of algal concentrations in the Gulf of Mexico to make estimates about the effect of the Deepwater Horizon oil spill on the base trophic level of this ecosystem. The size and complexity of the system indicates that coming to conclusive results about the actual impact would take a lot of additional work. But what is clear from this process is that GEE offers the computing power and flexibility to conduct time series analysis. Hopefully, you can use these tools and methods to ask your own questions about the long term effect of ecological disturbances over time.

7.1 Complete Trend Analysis Code

// Set map to center on deep water horizon location.
Map.setCenter(-88.36555556,28.73805556, 6);

// Define visualization parameters so the images are both presented in the same way.
var vis2 = {min:-7, max:14};

// Generate the based dataset for our processes.
var mod09 = ee.ImageCollection("NASA/OCEANDATA/MODIS-Aqua/L3SMI")
  .filterDate("2009-04-20","2009-07-31")
  .select("chlor_a")
  .median();
Map.addLayer(mod09, vis2, "09");

// Generate the based dataset for our processes.
var mod10 = ee.ImageCollection("NASA/OCEANDATA/MODIS-Aqua/L3SMI")
  .filterDate("2010-04-20","2010-07-31")
  .select("chlor_a")
  .median();
Map.addLayer(mod10, vis2, "10");

// Difference the model by subtracting.
var diff = mod10.subtract(mod09);
Map.addLayer(diff, {min:-6, max:6}, "diff");

var constructMODDict = function(geometry)
  /*
  This function takes in a geometry feature from the GUI and uses it to
  generate a dictionary of median reduce images for the specified date range
  inputs
  
  geometry = geometry object representing you area of interest
  y_list = set based on sensor type
  imagecollection = unique id for collection type
  filterDate = this is used to refine the month and day of start and end time
  
  With adaptation this should be flexible across sensors and date ranges.
  */
  {
  var startMonth = "-04-20";
  var endMonth = "-07-31";
  // Construct a dictionary for MODIS.
  var y_list = ee.List.sequence(2002, 2018);
  var ystr_list = y_list.map(function(y){return ee.Number(y).format('%1d')});
  var mod = y_list.map(function(y){return ee.ImageCollection('NASA/OCEANDATA/MODIS-Aqua/L3SMI')
                                          .filterDate(ee.String(ee.Number(y).format('%1d')).cat(startMonth),
                                                      ee.String(ee.Number(y).format('%1d')).cat(endMonth))
                                          .select("chlor_a")
                                          .median()
                                          .clip(geometry);
  })
  var mod_dict = ee.Dictionary.fromLists(ystr_list, mod);
  // Return MODIS dictionary.
  return mod_dict;
};

// Apply function across the new geometry.
var elements = constructMODDict(geometry);
print(elements, "Image dictionary");

// Convert the images in the dictionary to an image collection.
var collection2 = ee.ImageCollection.fromImages([
  ee.Image(elements.get('2002')),
  ee.Image(elements.get('2003')),
  ee.Image(elements.get('2004')),
  ee.Image(elements.get('2005')),
  ee.Image(elements.get('2006')),
  ee.Image(elements.get('2007')),
  ee.Image(elements.get('2008')),
  ee.Image(elements.get('2009')),
  ee.Image(elements.get('2010')),
  ee.Image(elements.get('2011')),
  ee.Image(elements.get('2012')),
  ee.Image(elements.get('2013')),
  ee.Image(elements.get('2014')),
  ee.Image(elements.get('2015')),
  ee.Image(elements.get('2016')),
  ee.Image(elements.get('2017')),
  ee.Image(elements.get('2018'))
  ]);

print(collection2)
Map.addLayer(collection2,{},'ic')

// Define start and end dates.
var start = '2008-01-01';
var end = '2012-12-31';

// Select all images with the months of April to July with a date range.
var col = ee.ImageCollection("NASA/OCEANDATA/MODIS-Aqua/L3SMI")
  .filterDate(start, end)
  .filter(ee.Filter.calendarRange(4,7,'month'))
  .filterBounds(geometry)
  .select("chlor_a");

print(col, "Individual Images By Year");

// Plot a time series of the chlor_a at a single location 
// or summarize values within an area.
var l8Chart = ui.Chart.image.series({imageCollection: col,
  region: roi,
  reducer: ee.Reducer.median()}
).setChartType('ScatterChart');

print(l8Chart);