MODIS MOD021KM and FIRMS#

Wildfires Modelling Standard Python

license render review

binder binder

RoHub doi

Context#

Purpose#

Explore MODIS satellite imagery and wildfire data that is open and free for scientific use.

Sensor description#

The MOD021KM product contains calibrated and geolocated at-aperture radiances for 36 discrete bands located in the 0.4 to 14.4 micron region of the electromagnetic spectrum.

Highlights#

  • Use satpy to load, visualise, and regrid MODIS level 1B data.

  • Fetch a fire database containing some 497364 fires from 2020.

  • Visualisation of fire pixels from the database.

  • Visualisation of the fire pixels alongside bands from the MODIS satellite data.

Contributions#

Notebook#

  • Samuel Jackson (author), Science & Technology Facilities Council, @samueljackson92

  • Alejandro Coca-Castro (reviewer), The Alan Turing Institute, @acocac

Dataset originator/creator#

MOD021KM#
  • MODIS Characterization Support Team (MCST)

  • MODIS Adaptive Processing System (MODAPS)

Firms#
  • University of Maryland

Dataset authors#

MOD021KM#
  • MODIS Science Data Support Team (SDST)

Firms#
  • NASA’s Applied Sciences Program

Dataset documentation#

Note

The author acknowledges MODIS Science Team and the use of data and/or imagery from NASA’s Fire Information for Resource Management System (FIRMS) (https://earthdata.nasa.gov/firms), part of NASA’s Earth Observing System Data and Information System (EOSDIS).

Install and load libraries#

Hide code cell source
!pip -q install geopandas
!pip -q install geoviews
WARNING: The directory '/home/jovyan/.cache/pip' or its parent directory is not owned or is not writable by the current user. The cache has been disabled. Check the permissions and owner of that directory. If executing pip with sudo, you should use sudo's -H flag.
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
WARNING: The directory '/home/jovyan/.cache/pip' or its parent directory is not owned or is not writable by the current user. The cache has been disabled. Check the permissions and owner of that directory. If executing pip with sudo, you should use sudo's -H flag.
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv

Hide code cell source
import pandas as pd
import numpy as np
import geopandas
import intake
import fsspec, aiohttp
import hvplot.xarray
import hvplot.pandas
import holoviews as hv
import panel as pn
import satpy
import xarray as xr
import tempfile
from pathlib import Path
from scipy.spatial import cKDTree
from satpy.writers import get_enhanced_image
from getpass import getpass
from pathlib import Path
from pyresample import geometry
import datetime
import urllib.request
import os.path
from dotenv import load_dotenv
import warnings
warnings.filterwarnings(action='ignore')

Set project structure#

notebook_folder = './notebook'
if not os.path.exists(notebook_folder):
    os.makedirs(notebook_folder)

Fetch Data#

Note

To download data from the NASA’s Earth Data site you must have a valid Earth Data account. Please register with Earth Data is you do not already have an account and then provide your username and password when prompted in the cell below.

Important

In order to download MODIS level1 data you must have authorized access to LAADS Web on your account. To do this navigate to your earthdata profile page

  • Click “Applications”

  • Click “Authorized Apps”

  • Click “Autorize More Applications”

  • Search for “LAADS Web”

  • Click “Authorize”

Now you should successfully be able to download MODIS data.

fname = 'MOD021KM.A2020245.0840.061.2020245193036.hdf'

if not os.path.isfile(os.path.join(notebook_folder, fname)) or os.path.getsize(os.path.join(notebook_folder, fname)) == 0:
    load_dotenv()
    username = os.environ.get("NASA_EARTHDATA_USER") #replace for your EarthData username if run local or in Binder
    password = os.environ.get("NASA_EARTHDATA_PWD")  #replace for your EarthData password if run local or in Binder

    fsspec.config.conf['https'] = dict(client_kwargs={'auth': aiohttp.BasicAuth(username, password)})

    url = f'https://ladsweb.modaps.eosdis.nasa.gov/archive/allData/61/MOD021KM/2020/245/{fname}'
    filename = url.split('/')[-1]
    with fsspec.open(url) as f:
        with Path(os.path.join(notebook_folder, filename)).open('wb') as handle:
            data = f.read()
            try:
                data.decode('utf-8')
                raise RuntimeError('Could not download MODIS data! Have you authorized LAADS Web in your Eathdata account above?')
            except UnicodeDecodeError:
                handle.write(data)

Download the database of MODIS wildfires from a publically accessible location.

filepath = 'https://firms2.modaps.eosdis.nasa.gov/data/country/zips'
filename = 'modis_2020_all_countries.zip'

if not os.path.isfile(filename) or os.path.getsize(filename) == 0:
    urllib.request.urlretrieve(os.path.join(filepath, filename), os.path.join(notebook_folder, filename))
    !unzip -o ./notebook/modis_2020_all_countries.zip -d ./notebook
Archive:  ./notebook/modis_2020_all_countries.zip
   creating: ./notebook/modis/2020/
  inflating: ./notebook/modis/2020/modis_2020_Afghanistan.csv  
  inflating: ./notebook/modis/2020/modis_2020_Albania.csv  
  inflating: ./notebook/modis/2020/modis_2020_Algeria.csv  
  inflating: ./notebook/modis/2020/modis_2020_Andorra.csv  
  inflating: ./notebook/modis/2020/modis_2020_Angola.csv  
  inflating: ./notebook/modis/2020/modis_2020_Antigua_and_Barbuda.csv  
  inflating: ./notebook/modis/2020/modis_2020_Argentina.csv  
  inflating: ./notebook/modis/2020/modis_2020_Armenia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Australia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Austria.csv  
  inflating: ./notebook/modis/2020/modis_2020_Azerbaijan.csv  
  inflating: ./notebook/modis/2020/modis_2020_Bahamas.csv  
  inflating: ./notebook/modis/2020/modis_2020_Bahrain.csv  
  inflating: ./notebook/modis/2020/modis_2020_Bangladesh.csv  
  inflating: ./notebook/modis/2020/modis_2020_Barbados.csv  
  inflating: ./notebook/modis/2020/modis_2020_Belarus.csv  
  inflating: ./notebook/modis/2020/modis_2020_Belgium.csv  
  inflating: ./notebook/modis/2020/modis_2020_Belize.csv  
  inflating: ./notebook/modis/2020/modis_2020_Benin.csv  
  inflating: ./notebook/modis/2020/modis_2020_Bermuda.csv  
  inflating: ./notebook/modis/2020/modis_2020_Bhutan.csv  
  inflating: ./notebook/modis/2020/modis_2020_Bolivia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Bosnia_and_Herzegovina.csv  
  inflating: ./notebook/modis/2020/modis_2020_Botswana.csv  
  inflating: ./notebook/modis/2020/modis_2020_Brazil.csv  
  inflating: ./notebook/modis/2020/modis_2020_British_Virgin_Islands.csv  
  inflating: ./notebook/modis/2020/modis_2020_Brunei_Darussalam.csv  
  inflating: ./notebook/modis/2020/modis_2020_Bulgaria.csv  
  inflating: ./notebook/modis/2020/modis_2020_Burkina_Faso.csv  
  inflating: ./notebook/modis/2020/modis_2020_Burundi.csv  
  inflating: ./notebook/modis/2020/modis_2020_Cambodia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Cameroon.csv  
  inflating: ./notebook/modis/2020/modis_2020_Canada.csv  
  inflating: ./notebook/modis/2020/modis_2020_Cape_Verde.csv  
  inflating: ./notebook/modis/2020/modis_2020_Cayman_Islands.csv  
  inflating: ./notebook/modis/2020/modis_2020_Central_African_Republic.csv  
  inflating: ./notebook/modis/2020/modis_2020_Chad.csv  
  inflating: ./notebook/modis/2020/modis_2020_Chile.csv  
  inflating: ./notebook/modis/2020/modis_2020_China.csv  
  inflating: ./notebook/modis/2020/modis_2020_Colombia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Comoros.csv  
  inflating: ./notebook/modis/2020/modis_2020_Costa_Rica.csv  
  inflating: ./notebook/modis/2020/modis_2020_Cote_d_Ivoire.csv  
  inflating: ./notebook/modis/2020/modis_2020_Croatia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Cuba.csv  
  inflating: ./notebook/modis/2020/modis_2020_Curacao.csv  
  inflating: ./notebook/modis/2020/modis_2020_Cyprus.csv  
  inflating: ./notebook/modis/2020/modis_2020_Czech_Republic.csv  
  inflating: ./notebook/modis/2020/modis_2020_Dem_Rep_Korea.csv  
  inflating: ./notebook/modis/2020/modis_2020_Democratic_Republic_of_the_Congo.csv  
  inflating: ./notebook/modis/2020/modis_2020_Denmark.csv  
  inflating: ./notebook/modis/2020/modis_2020_Djibouti.csv  
  inflating: ./notebook/modis/2020/modis_2020_Dominica.csv  
  inflating: ./notebook/modis/2020/modis_2020_Dominican_Republic.csv  
  inflating: ./notebook/modis/2020/modis_2020_Ecuador.csv  
  inflating: ./notebook/modis/2020/modis_2020_Egypt.csv  
  inflating: ./notebook/modis/2020/modis_2020_El_Salvador.csv  
  inflating: ./notebook/modis/2020/modis_2020_Equatorial_Guinea.csv  
  inflating: ./notebook/modis/2020/modis_2020_Eritrea.csv  
  inflating: ./notebook/modis/2020/modis_2020_Estonia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Ethiopia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Falkland_Islands.csv  
  inflating: ./notebook/modis/2020/modis_2020_Fiji.csv  
  inflating: ./notebook/modis/2020/modis_2020_Finland.csv  
  inflating: ./notebook/modis/2020/modis_2020_France.csv  
  inflating: ./notebook/modis/2020/modis_2020_French_Guiana.csv  
  inflating: ./notebook/modis/2020/modis_2020_French_Polynesia.csv  
  inflating: ./notebook/modis/2020/modis_2020_French_Southern_and_Antarctic_Lands.csv  
  inflating: ./notebook/modis/2020/modis_2020_Gabon.csv  
  inflating: ./notebook/modis/2020/modis_2020_Georgia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Germany.csv  
  inflating: ./notebook/modis/2020/modis_2020_Ghana.csv  
  inflating: ./notebook/modis/2020/modis_2020_Greece.csv  
  inflating: ./notebook/modis/2020/modis_2020_Greenland.csv  
  inflating: ./notebook/modis/2020/modis_2020_Guadeloupe.csv  
  inflating: ./notebook/modis/2020/modis_2020_Guam.csv  
  inflating: ./notebook/modis/2020/modis_2020_Guatemala.csv  
  inflating: ./notebook/modis/2020/modis_2020_Guinea-Bissau.csv  
  inflating: ./notebook/modis/2020/modis_2020_Guinea.csv  
  inflating: ./notebook/modis/2020/modis_2020_Guyana.csv  
  inflating: ./notebook/modis/2020/modis_2020_Haiti.csv  
  inflating: ./notebook/modis/2020/modis_2020_Heard_I_and_McDonald_Islands.csv  
  inflating: ./notebook/modis/2020/modis_2020_Honduras.csv  
  inflating: ./notebook/modis/2020/modis_2020_Hong_Kong.csv  
  inflating: ./notebook/modis/2020/modis_2020_Hungary.csv  
  inflating: ./notebook/modis/2020/modis_2020_India.csv  
  inflating: ./notebook/modis/2020/modis_2020_Indonesia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Iran.csv  
  inflating: ./notebook/modis/2020/modis_2020_Iraq.csv  
  inflating: ./notebook/modis/2020/modis_2020_Ireland.csv  
  inflating: ./notebook/modis/2020/modis_2020_Israel.csv  
  inflating: ./notebook/modis/2020/modis_2020_Italy.csv  
  inflating: ./notebook/modis/2020/modis_2020_Jamaica.csv  
  inflating: ./notebook/modis/2020/modis_2020_Japan.csv  
  inflating: ./notebook/modis/2020/modis_2020_Jordan.csv  
  inflating: ./notebook/modis/2020/modis_2020_Kazakhstan.csv  
  inflating: ./notebook/modis/2020/modis_2020_Kenya.csv  
  inflating: ./notebook/modis/2020/modis_2020_Kiribati.csv  
  inflating: ./notebook/modis/2020/modis_2020_Kosovo.csv  
  inflating: ./notebook/modis/2020/modis_2020_Kuwait.csv  
  inflating: ./notebook/modis/2020/modis_2020_Kyrgyzstan.csv  
  inflating: ./notebook/modis/2020/modis_2020_Lao_PDR.csv  
  inflating: ./notebook/modis/2020/modis_2020_Latvia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Lebanon.csv  
  inflating: ./notebook/modis/2020/modis_2020_Lesotho.csv  
  inflating: ./notebook/modis/2020/modis_2020_Liberia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Libya.csv  
  inflating: ./notebook/modis/2020/modis_2020_Lithuania.csv  
  inflating: ./notebook/modis/2020/modis_2020_Luxembourg.csv  
  inflating: ./notebook/modis/2020/modis_2020_Macedonia_Former_Yugoslav_Republic_of.csv  
  inflating: ./notebook/modis/2020/modis_2020_Madagascar.csv  
  inflating: ./notebook/modis/2020/modis_2020_Malawi.csv  
  inflating: ./notebook/modis/2020/modis_2020_Malaysia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Maldives.csv  
  inflating: ./notebook/modis/2020/modis_2020_Mali.csv  
  inflating: ./notebook/modis/2020/modis_2020_Malta.csv  
  inflating: ./notebook/modis/2020/modis_2020_Martinique.csv  
  inflating: ./notebook/modis/2020/modis_2020_Mauritania.csv  
  inflating: ./notebook/modis/2020/modis_2020_Mauritius.csv  
  inflating: ./notebook/modis/2020/modis_2020_Mexico.csv  
  inflating: ./notebook/modis/2020/modis_2020_Moldova.csv  
  inflating: ./notebook/modis/2020/modis_2020_Mongolia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Montenegro.csv  
  inflating: ./notebook/modis/2020/modis_2020_Montserrat.csv  
  inflating: ./notebook/modis/2020/modis_2020_Morocco.csv  
  inflating: ./notebook/modis/2020/modis_2020_Mozambique.csv  
  inflating: ./notebook/modis/2020/modis_2020_Myanmar.csv  
  inflating: ./notebook/modis/2020/modis_2020_Namibia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Nepal.csv  
  inflating: ./notebook/modis/2020/modis_2020_Netherlands.csv  
  inflating: ./notebook/modis/2020/modis_2020_New_Caledonia.csv  
  inflating: ./notebook/modis/2020/modis_2020_New_Zealand.csv  
  inflating: ./notebook/modis/2020/modis_2020_Nicaragua.csv  
  inflating: ./notebook/modis/2020/modis_2020_Niger.csv  
  inflating: ./notebook/modis/2020/modis_2020_Nigeria.csv  
  inflating: ./notebook/modis/2020/modis_2020_Northern_Mariana_Islands.csv  
  inflating: ./notebook/modis/2020/modis_2020_Norway.csv  
  inflating: ./notebook/modis/2020/modis_2020_Oman.csv  
  inflating: ./notebook/modis/2020/modis_2020_Pakistan.csv  
  inflating: ./notebook/modis/2020/modis_2020_Palau.csv  
  inflating: ./notebook/modis/2020/modis_2020_Palestine.csv  
  inflating: ./notebook/modis/2020/modis_2020_Panama.csv  
  inflating: ./notebook/modis/2020/modis_2020_Papua_New_Guinea.csv  
  inflating: ./notebook/modis/2020/modis_2020_Paraguay.csv  
  inflating: ./notebook/modis/2020/modis_2020_Peru.csv  
  inflating: ./notebook/modis/2020/modis_2020_Philippines.csv  
  inflating: ./notebook/modis/2020/modis_2020_Poland.csv  
  inflating: ./notebook/modis/2020/modis_2020_Portugal.csv  
  inflating: ./notebook/modis/2020/modis_2020_Puerto_Rico.csv  
  inflating: ./notebook/modis/2020/modis_2020_Qatar.csv  
  inflating: ./notebook/modis/2020/modis_2020_Republic_of_Congo.csv  
  inflating: ./notebook/modis/2020/modis_2020_Republic_of_Korea.csv  
  inflating: ./notebook/modis/2020/modis_2020_Reunion.csv  
  inflating: ./notebook/modis/2020/modis_2020_Romania.csv  
  inflating: ./notebook/modis/2020/modis_2020_Russian_Federation.csv  
  inflating: ./notebook/modis/2020/modis_2020_Rwanda.csv  
  inflating: ./notebook/modis/2020/modis_2020_Saint_Helena.csv  
  inflating: ./notebook/modis/2020/modis_2020_Saint_Kitts_and_Nevis.csv  
  inflating: ./notebook/modis/2020/modis_2020_Saint_Lucia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Saint_Vincent_and_the_Grenadines.csv  
  inflating: ./notebook/modis/2020/modis_2020_Samoa.csv  
  inflating: ./notebook/modis/2020/modis_2020_Sao_Tome_and_Principe.csv  
  inflating: ./notebook/modis/2020/modis_2020_Saudi_Arabia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Senegal.csv  
  inflating: ./notebook/modis/2020/modis_2020_Serbia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Seychelles.csv  
  inflating: ./notebook/modis/2020/modis_2020_Sierra_Leone.csv  
  inflating: ./notebook/modis/2020/modis_2020_Singapore.csv  
  inflating: ./notebook/modis/2020/modis_2020_Slovakia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Slovenia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Solomon_Islands.csv  
  inflating: ./notebook/modis/2020/modis_2020_Somalia.csv  
  inflating: ./notebook/modis/2020/AttributesReadme.txt  
  inflating: ./notebook/modis/2020/modis_2020_South_Africa.csv  
  inflating: ./notebook/modis/2020/modis_2020_South_Sudan.csv  
  inflating: ./notebook/modis/2020/modis_2020_Spain.csv  
  inflating: ./notebook/modis/2020/modis_2020_Sri_Lanka.csv  
  inflating: ./notebook/modis/2020/modis_2020_Sudan.csv  
  inflating: ./notebook/modis/2020/modis_2020_Suriname.csv  
  inflating: ./notebook/modis/2020/modis_2020_Svalbard_and_Jan_Mayen.csv  
  inflating: ./notebook/modis/2020/modis_2020_Swaziland.csv  
  inflating: ./notebook/modis/2020/modis_2020_Sweden.csv  
  inflating: ./notebook/modis/2020/modis_2020_Switzerland.csv  
  inflating: ./notebook/modis/2020/modis_2020_Syria.csv  
  inflating: ./notebook/modis/2020/modis_2020_Taiwan.csv  
  inflating: ./notebook/modis/2020/modis_2020_Tajikistan.csv  
  inflating: ./notebook/modis/2020/modis_2020_Tanzania.csv  
  inflating: ./notebook/modis/2020/modis_2020_Thailand.csv  
  inflating: ./notebook/modis/2020/modis_2020_The_Gambia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Timor-Leste.csv  
  inflating: ./notebook/modis/2020/modis_2020_Togo.csv  
  inflating: ./notebook/modis/2020/modis_2020_Tonga.csv  
  inflating: ./notebook/modis/2020/modis_2020_Trinidad_and_Tobago.csv  
  inflating: ./notebook/modis/2020/modis_2020_Tunisia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Turkey.csv  
  inflating: ./notebook/modis/2020/modis_2020_Turkmenistan.csv  
  inflating: ./notebook/modis/2020/modis_2020_Turks_and_Caicos_Islands.csv  
  inflating: ./notebook/modis/2020/modis_2020_Uganda.csv  
  inflating: ./notebook/modis/2020/modis_2020_Ukraine.csv  
  inflating: ./notebook/modis/2020/modis_2020_United_Arab_Emirates.csv  
  inflating: ./notebook/modis/2020/modis_2020_United_Kingdom.csv  
  inflating: ./notebook/modis/2020/modis_2020_United_States.csv  
  inflating: ./notebook/modis/2020/modis_2020_United_States_Minor_Outlying_Islands.csv  
  inflating: ./notebook/modis/2020/modis_2020_United_States_Virgin_Islands.csv  
  inflating: ./notebook/modis/2020/modis_2020_Uruguay.csv  
  inflating: ./notebook/modis/2020/modis_2020_Uzbekistan.csv  
  inflating: ./notebook/modis/2020/modis_2020_Vanuatu.csv  
  inflating: ./notebook/modis/2020/modis_2020_Venezuela.csv  
  inflating: ./notebook/modis/2020/modis_2020_Vietnam.csv  
  inflating: ./notebook/modis/2020/modis_2020_Yemen.csv  
  inflating: ./notebook/modis/2020/modis_2020_Zambia.csv  
  inflating: ./notebook/modis/2020/modis_2020_Zimbabwe.csv  

Load an intake catalog for the downloaded data

# set catalogue location
catalog_file = os.path.join(notebook_folder, 'catalog.yaml')

with open(catalog_file, 'w') as f:
    f.write('''
sources:
    modis_l1b:
      args:
        urlpath: 'notebook/MOD021KM.A2020245.0840.061.2020245193036.hdf'
        reader: 'modis_l1b'
      description: "MODIS Level 1B Products"
      driver: SatpySource
      metadata: {}
    modis_fires:
      args:
        urlpath: 'notebook/modis/2020/modis_*.csv'
      description: "MODIS Level 2 Fires"
      driver: csv
      metadata: {}
''')
from intake.source.base import PatternMixin
from intake.source.base import DataSource, Schema

import glob

class SatpySource(DataSource, PatternMixin):
    """Intake driver for data supported by satpy.Scene"""
    
    container = 'python'
    name = 'satpy'
    version = '0.0.1'
    partition_access = False

    def __init__(self, urlpath, reader=None, metadata=None, path_as_pattern=True):
        """
        Parameters
        ----------
        path: str, location of model pkl file
        Either the absolute or relative path to the file
        opened. Some examples:
          - ``{{ CATALOG_DIR }}/file.nat``
          - ``{{ CATALOG_DIR }}/*.nc``
        reader: str, optional
        Name of the satpy reader to use when loading data (ie. ``modis_l1b``)
        metadata: dict, optional
        Additional metadata to pass to the intake catalog
        path_as_pattern: bool or str, optional
        Whether to treat the path as a pattern (ie. ``data_{field}.nc``)
        and create new coodinates in the output corresponding to pattern
        fields. If str, is treated as pattern to match on. Default is True.
        """

        self.path_as_pattern = path_as_pattern
        self.urlpath = urlpath
        self._reader = reader
        super(SatpySource, self).__init__(metadata=metadata)

    def _load(self):
        files = self.urlpath
        files = list(glob.glob(files))
        return satpy.Scene(files, reader=self._reader)
    
    def _get_schema(self):
        self._schema = Schema(
            npartitions=1,
            extra_metadata={}
        )
        return self._schema

    def read(self):
        self._load_metadata()
        return self._load()

intake.register_driver('SatpySource', SatpySource)
cat = intake.open_catalog(catalog_file)

Load MODIS Satellite Data#

Here we use satpy to load the MODIS level 1b data into memory. As well as loading the image data, satpy provides a easy way to regrid the data to different coordinate systems.

scn = cat['modis_l1b'].read()
scn
<satpy.scene.Scene at 0x798e8f378e20>
Hide code cell source
scn.load(['true_color', '20'], resolution=1000)
plot_modis_raw = scn.show('true_color')
plot_modis_raw
100%|██████████| 52/52 [00:00<00:00, 954.03kB/s]
No rsr file /home/jovyan/.local/share/pyspectral/rsr_modis_EOS-Terra.h5 on disk
100%|██████████| 5/5 [00:00<00:00, 779.29kB/s]
../../../_images/35265949a3fb4d1296726885d54ad54e0b56744ad2ba78940125713c03b9e55f.png

Resample to a different projection#

In the plot above you can see that the raw MODIS data has distortion towards edge of the image. By regridding the data we can avoid some of this distortion.

area_id = "Southern Africa"
description = "Southern Africa in Mercator-Projection"
proj_id = "Southern Africa"
proj_dict = {"proj": "eqc"}

width = 1000    # width of the result domain in pixels
height = 1000   # height of the result domain in pixels

llx =  23E5   # projection x coordinate of lower left corner of lower left pixel
lly =  -22.9E5   # projection y coordinate of lower left corner of lower left pixel
urx =  48E5   # projection x coordinate of upper right corner of upper right pixel
ury =  -1.9E5   # projection y coordinate of upper right corner of upper right pixel

area_extent = (llx,lly,urx,ury)
from pyresample import create_area_def
resolution=1000
center =(0,0)
area_def = create_area_def(area_id, proj_dict, center=center, resolution=resolution)

modis_scn = scn.resample(area_def, radius_of_influence=10000)
Hide code cell source
plot_modis_scn = modis_scn.show('true_color')
plot_modis_scn
../../../_images/4d9816ca7364aeb4c91cc3b08c82c5c07a8973f72d51b99fea7e728063ff141c.png

Load MODIS Fire Database#

Now we’re going to load the modis fire database from CSV files. This contains the longitude, latitude, and time of where fires have been detected to occur. It also includes an estimate of the Fire Radiative Power (FRP), a measure of the intensity of the fire, for each fire detected.

Hide code cell source
fires = cat['modis_fires'].read()

time = fires.acq_date.astype(str) + ' ' + fires.acq_time.astype(str).str.zfill(4)
fires['timestamp'] = pd.to_datetime(time, format='%Y-%m-%d %H%M')
fires = fires.loc[fires.satellite == 'Terra']
fires = geopandas.GeoDataFrame(
    fires, geometry=geopandas.points_from_xy(fires.longitude, fires.latitude))

# We're only interested in data from Southern Africa for now
llx =  0    # projection x coordinate of lower left corner of lower left pixel
lly =  -30  # projection y coordinate of lower left corner of lower left pixel
urx =  55   # projection x coordinate of upper right corner of upper right pixel
ury =  10   # projection y coordinate of upper right corner of upper right pixel

fires = fires.cx[llx:urx, lly:ury]
fires.set_index('timestamp', drop=False, inplace=True)
fires = fires.sort_index()
fires = fires.loc['2020-09-01 00:00:00':'2020-10-01 00:00:00']
fires
latitude longitude brightness scan track acq_date acq_time satellite instrument confidence version bright_t31 frp daynight type timestamp geometry
timestamp
2020-09-01 07:02:00 -15.8201 46.6282 320.8 1.2 1.1 2020-09-01 702 Terra MODIS 59 6.03 306.2 8.7 D 0 2020-09-01 07:02:00 POINT (46.62820 -15.82010)
2020-09-01 07:02:00 -15.8183 46.6171 323.7 1.2 1.1 2020-09-01 702 Terra MODIS 67 6.03 307.9 12.7 D 0 2020-09-01 07:02:00 POINT (46.61710 -15.81830)
2020-09-01 07:02:00 -15.7672 47.2667 324.8 1.1 1.1 2020-09-01 702 Terra MODIS 72 6.03 307.6 9.9 D 0 2020-09-01 07:02:00 POINT (47.26670 -15.76720)
2020-09-01 07:02:00 -15.7055 47.7069 328.2 1.1 1.0 2020-09-01 702 Terra MODIS 75 6.03 306.8 15.4 D 0 2020-09-01 07:02:00 POINT (47.70690 -15.70550)
2020-09-01 07:02:00 -15.0942 47.2146 320.4 1.2 1.1 2020-09-01 702 Terra MODIS 65 6.03 302.7 9.6 D 0 2020-09-01 07:02:00 POINT (47.21460 -15.09420)
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2020-09-30 22:05:00 -4.5185 12.0523 306.7 1.8 1.3 2020-09-30 2205 Terra MODIS 69 6.03 288.2 17.6 N 2 2020-09-30 22:05:00 POINT (12.05230 -4.51850)
2020-09-30 22:06:00 -2.7462 10.7768 302.2 1.5 1.2 2020-09-30 2206 Terra MODIS 47 6.03 287.3 8.6 N 0 2020-09-30 22:06:00 POINT (10.77680 -2.74620)
2020-09-30 22:06:00 -0.8865 8.8320 302.2 1.2 1.1 2020-09-30 2206 Terra MODIS 48 6.03 289.0 4.9 N 0 2020-09-30 22:06:00 POINT (8.83200 -0.88650)
2020-09-30 22:06:00 -2.8421 10.8256 301.0 1.5 1.2 2020-09-30 2206 Terra MODIS 37 6.03 287.2 7.8 N 0 2020-09-30 22:06:00 POINT (10.82560 -2.84210)
2020-09-30 22:08:00 4.4222 7.1571 302.5 1.1 1.1 2020-09-30 2208 Terra MODIS 49 6.03 291.9 4.5 N 2 2020-09-30 22:08:00 POINT (7.15710 4.42220)

65459 rows × 17 columns

Daily Fire Radiative Power#

Here we plot the Fire Radiative Power (FRP) for each day of the month of September. FRP is a measure of the intensity of a fire in units of MegaWatts.

Hide code cell source
from bokeh.models.formatters import DatetimeTickFormatter

def plot_timeseries(data, y_variable):
    """Timeseries plot showing the mean fire radiative power at each day as well as the 5% and 95%"""

    def percentile(n):
        def percentile_(x):
            return np.percentile(x, n)
        percentile_.__name__ = 'percentile_%s' % n
        return percentile_

    formatter = DatetimeTickFormatter(months='%b')

    bounds = data.groupby([data.index.day_of_year])[y_variable].agg([percentile(5), percentile(95)])
    avg = data.groupby([data.index.day_of_year])[y_variable].mean()

    bounds.index = data.groupby([data.index.day_of_year])['timestamp'].first()
    avg.index = bounds.index

    tseries = hv.Overlay([
        (bounds.hvplot.area('timestamp', 'percentile_5', 'percentile_95',
                      alpha=0.2, color='red', xformatter=formatter)),
            avg.hvplot.line(x='timestamp', label=f'Average Daily FRP', color='red', xformatter=formatter)])

    return tseries.options(width=800, height=400, xlabel='Day',ylabel=f'FRP (MW)',legend_position='top_left')

plot_FIRMS_ts = plot_timeseries(fires, 'frp')
plot_FIRMS_ts

Geographical distribution of Fires#

Here we plot the geographical distribution of fires detected by MODIS over Southern Africa.

Hide code cell source
plot_FIRMS_geo = fires.hvplot.points('longitude', 'latitude', groupby='index.day_of_year', c='frp', geo=True, alpha=0.2,
                    tiles='ESRI', xlim=(llx, urx), ylim=(lly, ury), cmap='autumn', logz=True,
                    dynamic=False)
plot_FIRMS_geo
WARNING:param.GeoPointPlot03910: Log color mapper lower bound <= 0 and will not render correctly. Ensure you set a positive lower bound on the color dimension or using the `clim` option.
WARNING:param.GeoPointPlot03910: Log color mapper lower bound <= 0 and will not render correctly. Ensure you set a positive lower bound on the color dimension or using the `clim` option.