Assignment : Vegetation Coding Challenge 🌏 📈¶

Study Area: The Cherry Canyon Fire, Colorado, USA
Cherry Canyon Fire broke out on 24/5/2020, 13 miles north of Kim, Colorado. As stated, it was caused due to Strong winds and extremely low humidity. In this assignment, three years pre 2018-2020 and post fire 2020-2023 is analyzed using MODIS NDVI data.

Data: MODIS NDVI Data

Duration: 2018-2023 (3 years pre 2018-2020 and post fires 2020-2023)
Fire_Event: 2020

API Used: AppEEARS API for NASA Earthdata access
url: https://appeears.earthdatacloud.nasa.gov/api/

In [1]:
# Install the development version of the earthpy package
!pip install git+https://github.com/earthlab/earthpy@apppears
Collecting git+https://github.com/earthlab/earthpy@apppears
  Cloning https://github.com/earthlab/earthpy (to revision apppears) to /tmp/pip-req-build-hrgp4vnk
  Running command git clone --filter=blob:none --quiet https://github.com/earthlab/earthpy /tmp/pip-req-build-hrgp4vnk
  Running command git checkout -b apppears --track origin/apppears
  Switched to a new branch 'apppears'
  Branch 'apppears' set up to track remote branch 'apppears' from 'origin'.
  Resolved https://github.com/earthlab/earthpy to commit 20e0b17e563da17ba46dc32832cf4ed9173a7531
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
  Preparing metadata (pyproject.toml) ... done
Requirement already satisfied: geopandas in /opt/conda/lib/python3.10/site-packages (from earthpy==0.10.0) (0.13.2)
Requirement already satisfied: matplotlib>=2.0.0 in /opt/conda/lib/python3.10/site-packages (from earthpy==0.10.0) (3.7.2)
Requirement already satisfied: numpy>=1.14.0 in /opt/conda/lib/python3.10/site-packages (from earthpy==0.10.0) (1.25.2)
Requirement already satisfied: rasterio in /opt/conda/lib/python3.10/site-packages (from earthpy==0.10.0) (1.3.8)
Requirement already satisfied: scikit-image in /opt/conda/lib/python3.10/site-packages (from earthpy==0.10.0) (0.21.0)
Requirement already satisfied: requests in /opt/conda/lib/python3.10/site-packages (from earthpy==0.10.0) (2.31.0)
Requirement already satisfied: keyring in /opt/conda/lib/python3.10/site-packages (from earthpy==0.10.0) (25.2.0)
Requirement already satisfied: contourpy>=1.0.1 in /opt/conda/lib/python3.10/site-packages (from matplotlib>=2.0.0->earthpy==0.10.0) (1.1.0)
Requirement already satisfied: cycler>=0.10 in /opt/conda/lib/python3.10/site-packages (from matplotlib>=2.0.0->earthpy==0.10.0) (0.11.0)
Requirement already satisfied: fonttools>=4.22.0 in /opt/conda/lib/python3.10/site-packages (from matplotlib>=2.0.0->earthpy==0.10.0) (4.42.1)
Requirement already satisfied: kiwisolver>=1.0.1 in /opt/conda/lib/python3.10/site-packages (from matplotlib>=2.0.0->earthpy==0.10.0) (1.4.5)
Requirement already satisfied: packaging>=20.0 in /opt/conda/lib/python3.10/site-packages (from matplotlib>=2.0.0->earthpy==0.10.0) (23.1)
Requirement already satisfied: pillow>=6.2.0 in /opt/conda/lib/python3.10/site-packages (from matplotlib>=2.0.0->earthpy==0.10.0) (10.0.0)
Requirement already satisfied: pyparsing<3.1,>=2.3.1 in /opt/conda/lib/python3.10/site-packages (from matplotlib>=2.0.0->earthpy==0.10.0) (3.0.9)
Requirement already satisfied: python-dateutil>=2.7 in /opt/conda/lib/python3.10/site-packages (from matplotlib>=2.0.0->earthpy==0.10.0) (2.8.2)
Requirement already satisfied: fiona>=1.8.19 in /opt/conda/lib/python3.10/site-packages (from geopandas->earthpy==0.10.0) (1.9.4)
Requirement already satisfied: pandas>=1.1.0 in /opt/conda/lib/python3.10/site-packages (from geopandas->earthpy==0.10.0) (2.1.0)
Requirement already satisfied: pyproj>=3.0.1 in /opt/conda/lib/python3.10/site-packages (from geopandas->earthpy==0.10.0) (3.6.0)
Requirement already satisfied: shapely>=1.7.1 in /opt/conda/lib/python3.10/site-packages (from geopandas->earthpy==0.10.0) (2.0.1)
Requirement already satisfied: jaraco.classes in /opt/conda/lib/python3.10/site-packages (from keyring->earthpy==0.10.0) (3.4.0)
Requirement already satisfied: jaraco.functools in /opt/conda/lib/python3.10/site-packages (from keyring->earthpy==0.10.0) (4.0.1)
Requirement already satisfied: jaraco.context in /opt/conda/lib/python3.10/site-packages (from keyring->earthpy==0.10.0) (5.3.0)
Requirement already satisfied: importlib-metadata>=4.11.4 in /opt/conda/lib/python3.10/site-packages (from keyring->earthpy==0.10.0) (6.8.0)
Requirement already satisfied: SecretStorage>=3.2 in /opt/conda/lib/python3.10/site-packages (from keyring->earthpy==0.10.0) (3.3.3)
Requirement already satisfied: jeepney>=0.4.2 in /opt/conda/lib/python3.10/site-packages (from keyring->earthpy==0.10.0) (0.8.0)
Requirement already satisfied: affine in /opt/conda/lib/python3.10/site-packages (from rasterio->earthpy==0.10.0) (2.4.0)
Requirement already satisfied: attrs in /opt/conda/lib/python3.10/site-packages (from rasterio->earthpy==0.10.0) (23.1.0)
Requirement already satisfied: certifi in /opt/conda/lib/python3.10/site-packages (from rasterio->earthpy==0.10.0) (2023.7.22)
Requirement already satisfied: click>=4.0 in /opt/conda/lib/python3.10/site-packages (from rasterio->earthpy==0.10.0) (8.1.7)
Requirement already satisfied: cligj>=0.5 in /opt/conda/lib/python3.10/site-packages (from rasterio->earthpy==0.10.0) (0.7.2)
Requirement already satisfied: snuggs>=1.4.1 in /opt/conda/lib/python3.10/site-packages (from rasterio->earthpy==0.10.0) (1.4.7)
Requirement already satisfied: click-plugins in /opt/conda/lib/python3.10/site-packages (from rasterio->earthpy==0.10.0) (1.1.1)
Requirement already satisfied: setuptools in /opt/conda/lib/python3.10/site-packages (from rasterio->earthpy==0.10.0) (68.1.2)
Requirement already satisfied: charset-normalizer<4,>=2 in /opt/conda/lib/python3.10/site-packages (from requests->earthpy==0.10.0) (3.2.0)
Requirement already satisfied: idna<4,>=2.5 in /opt/conda/lib/python3.10/site-packages (from requests->earthpy==0.10.0) (3.4)
Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/conda/lib/python3.10/site-packages (from requests->earthpy==0.10.0) (2.0.4)
Requirement already satisfied: scipy>=1.8 in /opt/conda/lib/python3.10/site-packages (from scikit-image->earthpy==0.10.0) (1.11.2)
Requirement already satisfied: networkx>=2.8 in /opt/conda/lib/python3.10/site-packages (from scikit-image->earthpy==0.10.0) (3.1)
Requirement already satisfied: imageio>=2.27 in /opt/conda/lib/python3.10/site-packages (from scikit-image->earthpy==0.10.0) (2.31.1)
Requirement already satisfied: tifffile>=2022.8.12 in /opt/conda/lib/python3.10/site-packages (from scikit-image->earthpy==0.10.0) (2023.8.30)
Requirement already satisfied: PyWavelets>=1.1.1 in /opt/conda/lib/python3.10/site-packages (from scikit-image->earthpy==0.10.0) (1.4.1)
Requirement already satisfied: lazy_loader>=0.2 in /opt/conda/lib/python3.10/site-packages (from scikit-image->earthpy==0.10.0) (0.3)
Requirement already satisfied: six in /opt/conda/lib/python3.10/site-packages (from fiona>=1.8.19->geopandas->earthpy==0.10.0) (1.16.0)
Requirement already satisfied: zipp>=0.5 in /opt/conda/lib/python3.10/site-packages (from importlib-metadata>=4.11.4->keyring->earthpy==0.10.0) (3.16.2)
Requirement already satisfied: pytz>=2020.1 in /opt/conda/lib/python3.10/site-packages (from pandas>=1.1.0->geopandas->earthpy==0.10.0) (2023.3.post1)
Requirement already satisfied: tzdata>=2022.1 in /opt/conda/lib/python3.10/site-packages (from pandas>=1.1.0->geopandas->earthpy==0.10.0) (2023.3)
Requirement already satisfied: cryptography>=2.0 in /opt/conda/lib/python3.10/site-packages (from SecretStorage>=3.2->keyring->earthpy==0.10.0) (41.0.3)
Requirement already satisfied: more-itertools in /opt/conda/lib/python3.10/site-packages (from jaraco.classes->keyring->earthpy==0.10.0) (10.2.0)
Requirement already satisfied: backports.tarfile in /opt/conda/lib/python3.10/site-packages (from jaraco.context->keyring->earthpy==0.10.0) (1.1.1)
Requirement already satisfied: cffi>=1.12 in /opt/conda/lib/python3.10/site-packages (from cryptography>=2.0->SecretStorage>=3.2->keyring->earthpy==0.10.0) (1.15.1)
Requirement already satisfied: pycparser in /opt/conda/lib/python3.10/site-packages (from cffi>=1.12->cryptography>=2.0->SecretStorage>=3.2->keyring->earthpy==0.10.0) (2.21)
In [2]:
import getpass
import json
import os
import pathlib
from glob import glob
# Library for tabular data
import pandas as pd
#Library for vector data
import geopandas as gpd
import earthpy.appeears as eaapp
import hvplot.pandas
import hvplot.xarray
import rioxarray as rxr
import xarray as xr
In [3]:
data_dir = os.path.join(pathlib.Path.home(), 'cherry-data')
# Make the data directory
os.makedirs(data_dir, exist_ok=True)

#To visualize the directory path
data_dir
Out[3]:
'/home/jovyan/cherry-data'
In [4]:
# Download the Cherry Canyon fire boundary

cherry_url = ("https://services3.arcgis.com/T4QMspbfLg3qTGWY/arcgis"
              "/rest/services/WFIGS_Interagency_Perimeters/FeatureServer/0/"
              "query?where=poly_IncidentName%20%3D%20'CHERRY%20CANYON'&outFields=*&outSR=4326&f=json") 
cherry_url

#Opening data with geopandas

cherry_gdf = gpd.read_file(cherry_url)
cherry_gdf
Out[4]:
OBJECTID poly_SourceOID poly_IncidentName poly_FeatureCategory poly_MapMethod poly_GISAcres poly_CreateDate poly_DateCurrent poly_PolygonDateTime poly_IRWINID ... attr_ModifiedOnDateTime_dt attr_Source attr_IsCpxChild attr_CpxName attr_CpxID attr_SourceGlobalID GlobalID Shape__Area Shape__Length geometry
0 15518 NaN Cherry Canyon Wildfire Daily Fire Perimeter Hand Sketch 11756.34 1679512187728 NaN NaN {F32D0475-5315-4448-9C2A-9272C5B0F6FE} ... 1593543458777 IRWIN 0 NaN NaN {F32D0475-5315-4448-9C2A-9272C5B0F6FE} 5c500faf-4dad-4819-b5bb-ebba2d85a578 0.004843 0.812748 MULTIPOLYGON (((-103.43758 37.47623, -103.4375...

1 rows × 114 columns

In [10]:
cherry_gdf.explore()
Out[10]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [11]:
# Initialize AppeearsDownloader for MODIS NDVI data
ndvi_downloader = eaapp.AppeearsDownloader(
    download_key='cherry-ndvi',
    ea_dir=data_dir,
    product='MOD13Q1.061',
    layer='_250m_16_days_NDVI',
    start_date="07-01",
    end_date="07-31",
    recurring=True,
    year_range=[2018, 2023],
    polygon=cherry_gdf
)

ndvi_downloader.download_files(cache=True)
In [5]:
# Get a list of NDVI tif file paths

ndvi_files = sorted(glob(os.path.join(data_dir, 'cherry-ndvi', '*', '*NDVI*.tif')))
len(ndvi_files)
Out[5]:
18
In [6]:
scale_factor = 10000
d_start = -19
d_end = -12
In [7]:
ndvi_das = []
for ndvi_path in ndvi_files:
    # Get date from file name
    doy = ndvi_path[d_start:d_end]
    date = pd.to_datetime(doy, format='%Y%j')

    # Open dataset
    da = rxr.open_rasterio(ndvi_path, masked=True).squeeze()

    # Add date dimension and clean up metadata
    da = da.assign_coords({'date': date})
    da = da.expand_dims({'date': 1})
    da.name = 'NDVI'

    # Multiple by scale factor
    da = da / scale_factor

    # Prepare for concatenation
    ndvi_das.append(da)

len(ndvi_das)
Out[7]:
18
In [8]:
ndvi_da = xr.combine_by_coords(ndvi_das, coords=['date'])
ndvi_da
Out[8]:
<xarray.Dataset>
Dimensions:      (x: 49, y: 55, date: 18)
Coordinates:
    band         int64 1
  * x            (x) float64 -103.5 -103.5 -103.5 ... -103.4 -103.4 -103.4
  * y            (y) float64 37.48 37.48 37.48 37.47 ... 37.37 37.37 37.37 37.37
    spatial_ref  int64 0
  * date         (date) datetime64[ns] 2018-06-26 2018-07-12 ... 2023-07-28
Data variables:
    NDVI         (date, y, x) float32 0.2481 0.2481 0.2036 ... 0.2931 0.2931
xarray.Dataset
    • x: 49
    • y: 55
    • date: 18
    • band
      ()
      int64
      1
      array(1)
    • x
      (x)
      float64
      -103.5 -103.5 ... -103.4 -103.4
      array([-103.467708, -103.465625, -103.463542, -103.461458, -103.459375,
             -103.457292, -103.455208, -103.453125, -103.451042, -103.448958,
             -103.446875, -103.444792, -103.442708, -103.440625, -103.438542,
             -103.436458, -103.434375, -103.432292, -103.430208, -103.428125,
             -103.426042, -103.423958, -103.421875, -103.419792, -103.417708,
             -103.415625, -103.413542, -103.411458, -103.409375, -103.407292,
             -103.405208, -103.403125, -103.401042, -103.398958, -103.396875,
             -103.394792, -103.392708, -103.390625, -103.388542, -103.386458,
             -103.384375, -103.382292, -103.380208, -103.378125, -103.376042,
             -103.373958, -103.371875, -103.369792, -103.367708])
    • y
      (y)
      float64
      37.48 37.48 37.48 ... 37.37 37.37
      array([37.480208, 37.478125, 37.476042, 37.473958, 37.471875, 37.469792,
             37.467708, 37.465625, 37.463542, 37.461458, 37.459375, 37.457292,
             37.455208, 37.453125, 37.451042, 37.448958, 37.446875, 37.444792,
             37.442708, 37.440625, 37.438542, 37.436458, 37.434375, 37.432292,
             37.430208, 37.428125, 37.426042, 37.423958, 37.421875, 37.419792,
             37.417708, 37.415625, 37.413542, 37.411458, 37.409375, 37.407292,
             37.405208, 37.403125, 37.401042, 37.398958, 37.396875, 37.394792,
             37.392708, 37.390625, 37.388542, 37.386458, 37.384375, 37.382292,
             37.380208, 37.378125, 37.376042, 37.373958, 37.371875, 37.369792,
             37.367708])
    • spatial_ref
      ()
      int64
      0
      crs_wkt :
      GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AXIS["Latitude",NORTH],AXIS["Longitude",EAST],AUTHORITY["EPSG","4326"]]
      semi_major_axis :
      6378137.0
      semi_minor_axis :
      6356752.314245179
      inverse_flattening :
      298.257223563
      reference_ellipsoid_name :
      WGS 84
      longitude_of_prime_meridian :
      0.0
      prime_meridian_name :
      Greenwich
      geographic_crs_name :
      WGS 84
      horizontal_datum_name :
      World Geodetic System 1984
      grid_mapping_name :
      latitude_longitude
      spatial_ref :
      GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AXIS["Latitude",NORTH],AXIS["Longitude",EAST],AUTHORITY["EPSG","4326"]]
      GeoTransform :
      -103.46874999073073 0.0020833333331466974 0.0 37.481249996642234 0.0 -0.0020833333331466974
      array(0)
    • date
      (date)
      datetime64[ns]
      2018-06-26 ... 2023-07-28
      array(['2018-06-26T00:00:00.000000000', '2018-07-12T00:00:00.000000000',
             '2018-07-28T00:00:00.000000000', '2019-06-26T00:00:00.000000000',
             '2019-07-12T00:00:00.000000000', '2019-07-28T00:00:00.000000000',
             '2020-06-25T00:00:00.000000000', '2020-07-11T00:00:00.000000000',
             '2020-07-27T00:00:00.000000000', '2021-06-26T00:00:00.000000000',
             '2021-07-12T00:00:00.000000000', '2021-07-28T00:00:00.000000000',
             '2022-06-26T00:00:00.000000000', '2022-07-12T00:00:00.000000000',
             '2022-07-28T00:00:00.000000000', '2023-06-26T00:00:00.000000000',
             '2023-07-12T00:00:00.000000000', '2023-07-28T00:00:00.000000000'],
            dtype='datetime64[ns]')
    • NDVI
      (date, y, x)
      float32
      0.2481 0.2481 ... 0.2931 0.2931
      array([[[0.2481, 0.2481, 0.2036, ..., 0.1929, 0.1974, 0.1994],
              [0.2383, 0.2331, 0.2033, ..., 0.1996, 0.2115, 0.2074],
              [0.1961, 0.1856, 0.2104, ..., 0.2199, 0.1945, 0.1945],
              ...,
              [0.1704, 0.1687, 0.1691, ..., 0.1835, 0.1799, 0.1741],
              [0.1798, 0.1809, 0.193 , ..., 0.1881, 0.1791, 0.1685],
              [0.2231, 0.2579, 0.3029, ..., 0.1862, 0.1797, 0.1797]],
      
             [[0.2828, 0.2828, 0.2437, ..., 0.2323, 0.2298, 0.236 ],
              [0.2748, 0.2545, 0.2358, ..., 0.2597, 0.2429, 0.2382],
              [0.2292, 0.228 , 0.2276, ..., 0.2478, 0.2177, 0.2177],
              ...,
              [0.1812, 0.1708, 0.1798, ..., 0.1992, 0.2034, 0.2052],
              [0.2199, 0.2365, 0.2365, ..., 0.2018, 0.2033, 0.2033],
              [0.3013, 0.3146, 0.3193, ..., 0.2173, 0.2123, 0.2123]],
      
             [[0.3471, 0.3471, 0.3356, ..., 0.288 , 0.3119, 0.3233],
              [0.2925, 0.2765, 0.3161, ..., 0.3124, 0.323 , 0.3361],
              [0.3183, 0.2656, 0.2597, ..., 0.3097, 0.2939, 0.2939],
              ...,
      ...
              [0.3538, 0.3661, 0.3581, ..., 0.3666, 0.3802, 0.3809],
              [0.3739, 0.3739, 0.3863, ..., 0.3666, 0.3522, 0.3522],
              [0.3832, 0.3832, 0.4037, ..., 0.363 , 0.355 , 0.355 ]],
      
             [[0.3728, 0.3728, 0.3726, ..., 0.2858, 0.3101, 0.3252],
              [0.3362, 0.3175, 0.3117, ..., 0.3258, 0.3102, 0.3214],
              [0.3055, 0.3055, 0.309 , ..., 0.2948, 0.291 , 0.291 ],
              ...,
              [0.3535, 0.3622, 0.3648, ..., 0.3617, 0.3492, 0.3658],
              [0.3656, 0.3711, 0.3915, ..., 0.3453, 0.3492, 0.3388],
              [0.3749, 0.4171, 0.4061, ..., 0.3551, 0.3464, 0.3464]],
      
             [[0.2987, 0.2987, 0.3324, ..., 0.2658, 0.2932, 0.2744],
              [0.277 , 0.2987, 0.2804, ..., 0.2923, 0.274 , 0.2803],
              [0.277 , 0.2866, 0.2804, ..., 0.2909, 0.274 , 0.274 ],
              ...,
              [0.3479, 0.3527, 0.3442, ..., 0.2866, 0.2892, 0.2701],
              [0.3548, 0.3527, 0.36  , ..., 0.2901, 0.2931, 0.2701],
              [0.3807, 0.368 , 0.4027, ..., 0.2955, 0.2931, 0.2931]]],
            dtype=float32)
    • x
      PandasIndex
      PandasIndex(Index([-103.46770832406415,   -103.465624990731, -103.46354165739785,
             -103.46145832406471, -103.45937499073156, -103.45729165739841,
             -103.45520832406527, -103.45312499073212, -103.45104165739897,
             -103.44895832406583, -103.44687499073268, -103.44479165739953,
             -103.44270832406639, -103.44062499073324,  -103.4385416574001,
             -103.43645832406695,  -103.4343749907338, -103.43229165740065,
             -103.43020832406751, -103.42812499073436, -103.42604165740121,
             -103.42395832406807, -103.42187499073492, -103.41979165740177,
             -103.41770832406863, -103.41562499073548, -103.41354165740233,
             -103.41145832406919, -103.40937499073604,  -103.4072916574029,
             -103.40520832406975,  -103.4031249907366, -103.40104165740345,
              -103.3989583240703, -103.39687499073716, -103.39479165740401,
             -103.39270832407087, -103.39062499073772, -103.38854165740457,
             -103.38645832407143, -103.38437499073828, -103.38229165740513,
             -103.38020832407199, -103.37812499073884,  -103.3760416574057,
             -103.37395832407255,  -103.3718749907394, -103.36979165740625,
              -103.3677083240731],
            dtype='float64', name='x'))
    • y
      PandasIndex
      PandasIndex(Index([ 37.48020832997566, 37.478124996642514,  37.47604166330937,
              37.47395832997622,  37.47187499664307,  37.46979166330993,
              37.46770832997678,  37.46562499664363,  37.46354166331049,
              37.46145832997734,  37.45937499664419,  37.45729166331105,
               37.4552083299779,  37.45312499664475,  37.45104166331161,
              37.44895832997846,  37.44687499664531,  37.44479166331217,
              37.44270832997902,  37.44062499664587, 37.438541663312726,
              37.43645832997958,  37.43437499664643, 37.432291663313286,
              37.43020832998014,  37.42812499664699, 37.426041663313846,
               37.4239583299807,  37.42187499664755, 37.419791663314406,
              37.41770832998126,  37.41562499664811, 37.413541663314966,
              37.41145832998182,  37.40937499664867, 37.407291663315526,
              37.40520832998238,  37.40312499664923, 37.401041663316086,
              37.39895832998294,  37.39687499664979, 37.394791663316646,
               37.3927083299835,  37.39062499665035, 37.388541663317206,
              37.38645832998406,  37.38437499665091, 37.382291663317766,
              37.38020832998462,  37.37812499665147, 37.376041663318325,
              37.37395832998518,  37.37187499665203, 37.369791663318885,
              37.36770832998574],
            dtype='float64', name='y'))
    • date
      PandasIndex
      PandasIndex(DatetimeIndex(['2018-06-26', '2018-07-12', '2018-07-28', '2019-06-26',
                     '2019-07-12', '2019-07-28', '2020-06-25', '2020-07-11',
                     '2020-07-27', '2021-06-26', '2021-07-12', '2021-07-28',
                     '2022-06-26', '2022-07-12', '2022-07-28', '2023-06-26',
                     '2023-07-12', '2023-07-28'],
                    dtype='datetime64[ns]', name='date', freq=None))
In [9]:
# Compute the difference in NDVI before and after the fire

# Plot the difference
import matplotlib.pyplot as plt 

fig, ax = plt.subplots()

ndvi_diff = (
    ndvi_da
        .sel(date=slice('2021', '2023'))
        .mean('date')
        .NDVI 
   - ndvi_da
        .sel(date=slice('2018', '2020'))
        .mean('date')
        .NDVI
)
ndvi_diff.plot(x='x',y='y',cmap='PiYG', ax= ax)
cherry_gdf.plot(color = 'None' , edgecolor='black', ax= ax)
Out[9]:
<Axes: title={'center': 'band = 1, spatial_ref = 0'}, xlabel='x', ylabel='y'>
No description has been provided for this image

Higher values of NDVI that is towards postive values shows a healthy vegetation whereas negative, near zero values shows stressed vegetation and may represent features like water body, exposed soil, urban area. In the above figure, healthy vegetation are shown in green colors and stressed or other features with pink and white colors. Negative values are shown using dark pink, near zero values with white, and positive values with green.

In [10]:
area_out_gdf = (
    gpd.GeoDataFrame(geometry=cherry_gdf.envelope)
    .overlay(cherry_gdf, how='difference'))
In [11]:
# Clip data to both inside and outside the boundary
ndvi_cherry_da = ndvi_da.rio.clip(cherry_gdf.geometry, from_disk=True)
ndvi_out_da = ndvi_da.rio.clip(area_out_gdf.geometry, from_disk=True)
In [12]:
# Compute mean annual July NDVI
jul_ndvi_cherry_df = (
    ndvi_cherry_da
    .groupby(ndvi_cherry_da.date.dt.year)
    .mean(...)
    .NDVI.to_dataframe())
jul_ndvi_out_df = (
    ndvi_out_da
    .groupby(ndvi_out_da.date.dt.year)
    .mean(...)
    .NDVI.to_dataframe())

# Plot inside and outside the reservation
jul_ndvi_df = (
    jul_ndvi_cherry_df[['NDVI']]
    .join(
        jul_ndvi_out_df[['NDVI']], 
        lsuffix=' Burned Area', rsuffix=' Unburned Area')
)

jul_ndvi_df.hvplot(
    title='NDVI before and after the Cherry Canyon Fire'
)
/opt/conda/lib/python3.10/site-packages/holoviews/core/data/pandas.py:39: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
  return dataset.data.dtypes[idx].type
/opt/conda/lib/python3.10/site-packages/holoviews/core/data/pandas.py:39: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
  return dataset.data.dtypes[idx].type
Out[12]:

Analysis of the Graph¶

In 2019, the NDVI values of burned and Unburned areas indicates a healthy vegetation with values greater than 0.35. However, in 2020, lower NDVI values of burned area indicates stressed vegetation due to fire. Post fire event, the vegetation of burned area shows an upward trend indicating improvement in vegetation health with time in 2021 and afterwards.

In [13]:
# Plot difference inside and outside the reservation
jul_ndvi_df['difference'] = (
    jul_ndvi_df['NDVI Burned Area']
    - jul_ndvi_df['NDVI Unburned Area'])
jul_ndvi_df.difference.hvplot(
    title='Difference between NDVI within and outside the Cherry Canyon Fire'
)
/opt/conda/lib/python3.10/site-packages/holoviews/core/data/pandas.py:39: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
  return dataset.data.dtypes[idx].type
/opt/conda/lib/python3.10/site-packages/holoviews/core/data/pandas.py:39: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
  return dataset.data.dtypes[idx].type
Out[13]:

In the year 2020, as it is seen from the graph the value of NDVI is negative (less than -0.06). This suggests a very stressed vegetation. If compared from 2018 to 2020, there is depreciating value of NDVI from greater then 0.02 to -0.06, whereas the value of NDVI rises from -0.06 to -0.03 from 2020 to 2023.

In [14]:
%%capture
%%bash
#Covert to HTML
jupyter nbconvert vegetation.ipynb --to html