The world’s leading publication for data science, AI, and ML professionals.

Exploring Seasonal Variations in Vegetation Cover around Indian Subcontinent

How to create an animated GIF of seasonal variations in vegetation cover using free and open-source tools in Python

Seasonal variations in vegetation cover: Image by Author
Seasonal variations in vegetation cover: Image by Author

1. Introduction

Vegetation plays a crucial role in maintaining the balance in various biogeochemical cycles, e.g., water, oxygen, carbon, nitrogen and so on. It strongly affects soil characteristics such as soil volume, chemistry and texture, and prevents soil erosion from wind and water. It serves as an indispensable wildlife habitat and the energy source for a vast array of animal species on the planet. In this blog post, I will demonstrate how we can use free and open source tools in Python to get a visual sense of seasonal variations in vegetation cover around the Indian subcontinent with just a few lines of codes.

2. Workflow

  • Import libraries and initialize Google Earth Engine (GEE)
  • Define the area of interest
  • Define the regional bounds containing the area of interest which will be used for the animation frame
  • Access the MODIS Terra Vegetation 16-Day Indices. Reduce the images of the same month by taking the median.
  • Plot the reduced monthly images as frames of an animated GIF.

We will begin with python set up and GEE initialization.

import geemap
import ee
try:
 ee.Initialize()
except:
 ee.Authenticate()
 ee.Initialize()

3. Data Processing

As discussed in the work flow, we now define the regions for analysis and visualisation. We will use the Food and Agriculture Organization’s (FAO’s) FeatureCollection which contains the GIS information on the international borders of countries.

# We use the country boundaries from Global Administrative Unit Layers (2015) provided by FAO(UN)
india = ee.FeatureCollection("FAO/GAUL/2015/level0") 
            .filter(ee.Filter.inList('ADM0_NAME', ['India', 'Jammu and Kashmir','Arunachal Pradesh',
                                                   'China/India','Aksai Chin']));
# Define the regional bounds for animation frames.
region = india.geometry().bounds();

Before we proceed further, let’s explore a bit more about MODIS products. MODIS stands for MODerate resolution Imaging Spectroradiometer. It is comprised of satellites under two missions – Aqua and Terra, and provides a wealth of information about our oceans, land and atmosphere through a number of spectral bands. These satellites complete one revolution around the earth in 1–2 days. MODIS images have coarse resolution ranging between 250m and 1000m. They can be used to know the health of vegetation through vegetation indices (e.g. Normalized Difference Vegetation Index (NDVI), Enhanced Vegetation Index (EVI)), and moisture indices (e.g. Normalized Difference Water Index (NDWI), Evapotranspiration (ET))). MODIS monitors the ocean by measuring ocean surface temperature, ocean color and clarity. It can also be used to monitor forest fires, land use changes, land surface temperature etc. In this article, we will be using MODIS vegetation indices which are available at 16-day intervals. These indices are retrieved from daily reflectance data subjected to a compositing process for removing low quality pixels as a large portion of daily MODIS images are often filled with clouds, thereby hampering its useability.

With this background, let’s continue from where we left off. We filter the MODIS image collection for the calendar year 2020. We will group the images from the same month by taking median. This will ensure we have one image for each month resulting in 12 images for the whole year.

# We use MODIS Terra Vegetation Indices 16-Day Global 1km distributed by NASA's Land Processes Distributed Active Archive Center (LP DAAC)
col = ee.ImageCollection('MODIS/006/MOD13A2').select('NDVI')
        .filterDate('2020-01-01','2020-12-31');
months = ee.List.sequence(1, 12);
def groupbyMonth(m):
    img = col.filter(ee.Filter.calendarRange(m,m, 'month')).median()
    return img;
colByMonth = ee.ImageCollection.fromImages(months.map(groupbyMonth))

As can be checked using col.size().getInfo() and colByMonth.size().getInfo(), there are 23 and 12 images in the raw collection and monthly collection respectively.

4. Plotting

The next step is to visualise these 12 images which are part of the colByMonth image collection. We set the parameters for visualising the NDVI rasters using the same color palettes as provided in GEE catalogue. The color palette provided as an argument linearly interpolates the colors between the minimum and maximum NDVI values.

# We use the NDVI visualisation parameters from GEE catalogue
gifParams = {
    'region': region,
    'dimensions': 600,
    'crs': 'EPSG:3857',
    'framesPerSecond': 1,
    'min': 0.0,
    'max': 9000.0,
    'palette': ['FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901',
                '66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01',
                '012E01', '011D01', '011301'],
};
gif_fname = 'C:UsersADMINDesktopsatellitegeemapndvi.gif'
geemap.download_ee_video(colByMonth, gifParams, gif_fname)

Once the animated GIF is ready, we will add the month information on each frame of the GIF. This can be done easily using add_text_to_gif function of geemap package.

# Add the months information on each frame of GIF 
text = ['Jan-20','Feb-20','Mar-20','Apr-20','May-20','Jun-20','Jul-20','Aug-20','Sep-20','Oct-20','Nov-20','Dec-20']
out_gif = 'C:UsersADMINDesktopsatellitegeemapndvi_out.gif'
geemap.add_text_to_gif(gif_fname, out_gif, xy = ('40%', '0%'), text_sequence = text, font_size=30, font_color = '#000000',duration = 1000)

You can visualize the annotated GIF within Jupyter Notebook using the show_image function of geemap package.

geemap.show_image(out_gif)

I hope you enjoyed reading the article and get to use it in your geospatial projects. Do share your thoughts about other interesting use cases of MODIS products in the comments section below.

Disclaimer: Views expressed in the blog are personal.


Related Articles