# read in pandas
import pandas as pd
# import matplotlib for colors
import matplotlib.pyplot as plt
# import libraries and functions here
import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
## for geospatial analysis
import xarray as xr
import rioxarray as rioxr
import geopandas as gpd
About
In this notebook I analyzed the affects of the Santa Barbara 2017 Thomas Fire. I created a time series showing the Averaged Air Quaility Index(AQI) from 2017 to 2018. As well as creating a raster map of the scar caused by the Thomas Fire.
Additional information can be found at my repository
Datasets
EPA’s Air Quality Data Collected at Outdoor Monitor Stations
The first dataset contains information on daily AQI readings across the United States. AQI readings are an indicator that allow the public to understand how polluted their air is. Higher levels in AQI translate to more pollution present in the atmosphere.
This dataset has been download from the EPA’s Air Quality System (AQS).
Additional information and metadata for this datset is available in the Airdata Download Files Documentation
As noted by The State of California and the Department of Forestry and Fire Protection this data provides a spatial distribution of the past large fires in California. But, this data is in no way a complete potrayal of the past fires.
This shapefile has been downloaded from California Govt State Geoportal.
Additional data can be found in the Fire Perimeters Description
This is a NetCDF file of a raster of Santa Barbara visualizing Santa Barbara. The data was accessed and pre-processed in the Microsoft Planetary Computer. The raster consists of three dimensions: x,y, band. It also contains the following data variables: red, green, blue, nir08(near infared), swir22(short wave).
Additional information regarding the Landsat bands can be found at the following USGS websites.
Final Output
The final visualization for this notebook are the following figures:
Santa Barbara AQI 2017-2018
Santa Barbara Thomas Fire 2017
Geographic Context
For context, let see where Santa Barbara county is relative to California
Import Libraries
Import necessary libraries for data wrangling and geospatial analysis
Import Data
Import neccessary data.
# read in 2017 Daily AQI by County data
= pd.read_csv("https://aqs.epa.gov/aqsweb/airdata/daily_aqi_by_county_2017.zip")
aqi_17
# read in 2018 Daily AQI by County data
= pd.read_csv("https://aqs.epa.gov/aqsweb/airdata/daily_aqi_by_county_2018.zip")
aqi_18 # read in 2017 and 2018 Daily AQI by County data
= pd.read_csv("https://aqs.epa.gov/aqsweb/airdata/daily_aqi_by_county_2017.zip")
aqi_17 = pd.read_csv("https://aqs.epa.gov/aqsweb/airdata/daily_aqi_by_county_2018.zip")
aqi_18
# Import California wildfire data
= gpd.read_file('data/California_Fire_Perimeters_2017/California_Fire_Perimeters_2017.shp')
wildfires # Import Landsat
= rioxr.open_rasterio(os.path.join(os.getcwd(),'data','landsat8-2018-01-26-sb-simplified.nc')) landsat
Data Preparation
AQI
Before I can plot a time series of the daily AQI I need to prepare the data. I need to combine the two years(2017 and 2018) of AQI, clean the columns, and update the object types.
# "Glue" aqi_17 and aqi_18
= pd.concat([aqi_17,aqi_18])
aqi
# Update column by making lower case and replace space with underscore
= aqi.columns.str.lower().str.replace(' ','_')
aqi.columns
# update date column to be datetime object
= aqi.copy()
aqi = pd.to_datetime(aqi.date)
aqi.date
# Set date to indez
= aqi.set_index("date") aqi
Landsat Data Preparation
The landsat data contains an extra dimension, band
, that is not necessary and can cause some issues when plotting. I will remove this dimension.
# remove length 1 dimension (band)
= landsat.squeeze()
landsat
# remove coordinates associated to band
= landsat.drop('band') landsat
Wildfire Data Preparation
Lets explore our Wildfire shapefile, update the column names, and update the CRS to the landsat CRS.
# Make column names lowercase
= wildfires.columns.str.lower()
wildfires.columns
#Update wildfire CRS to match Landsar CRS
= wildfires.to_crs(landsat.rio.crs) wildfires
Data Selection
Santa Barbara
Our current dataframe includes all Counties in the United States. But, we are only interested in Santa Barbara. Let’s filter our dataframe to Santa Barbara County and drop unecessary columns.
# Select Santa Barbara
= aqi[aqi.county_name == "Santa Barbara"]
aqi_sb
# Check that we only filtered for Santa Barbara by unique county_names
aqi_sb.county_name.unique()
# remove state_name, county_name, state_code and county_code columns
= aqi_sb.drop(columns = ['state_name','county_name','state_code','county_code']) aqi_sb
Wildfire
Our interest is only on the Thomas fire, let us filter our data to only include it.
# We are interested in the THOMAS FIRE
# Filter dataset to THOMAS FIRE
= wildfires[wildfires.fire_name == 'THOMAS'] wildfires
Data Visualization
Time Series
To calculate the trend of AQI values we conduct a 5-day rolling average.
# Create a new column with mean AQI over a 5-day rolling average.
#aqi_sb["five_day_average"] = aqi_sb.aqi.rolling("5D").mean()
"five_day_average"] = aqi_sb.aqi.rolling("5D").mean() aqi_sb[
Now we can make a line plot of our time series! Let us compare both the daily AQI and 5-day moving average.
# define colors for plot
= ['thistle','firebrick']
colors
# ------ Plot figure -----------------------------------------------------------------
# line plot of daily AQI and the 5-day average
= ['aqi','five_day_average'], # setting y as AQI and 5-day average AQI
aqi_sb.plot(y = "Date", # x-axis label
xlabel = "PM2.5 (μm)", #y-axis label
ylabel = "Daily AQI and 5-day average AQI for Santa Barbara", # title
title = colors) #setting colors for lines
color
# -----Save Figure-----------------------------------------------------------------------
'images/sb_county_aqi.png',bbox_inches = 'tight',dpi = 100)
plt.savefig( plt.show()
We see that Daily AQI peaks around December which is on par with when the Thomas Fire (December 4 - March 22) occured. An interesting thing to note is that the peak AQI was reached right at the start of the fire and eventually returned to the average AQI after January, even though the fire did not stop till March.
Map of Fire Scar
I can now map the Thomas Fire scar on top of the Santa Barbara raster.
# Plot Wildfire and Landsat data together
= plt.subplots()
fig, ax
# ---Landsat Map------------------------------------------------------------------------------------------------------------
# Here we are plotting with false color image by plotting the short-waved infared (swir22), near-infared, and red variable
# False color imaging allows us to differentiate the Thomas fire scar from the rest of the Santa Barbara area
'swir22','nir08','red']].to_array().plot.imshow(ax=ax,robust = True)
landsat[['white')
ax.set_facecolor(
#---Thomas Fire Layer-------------------------------------------------------------------------------------------------------
=ax, color = 'none', edgecolor = "yellow", linewidth = 1)
wildfires.plot(ax= mpatches.Patch(color = 'yellow',
wildfires_patch = 'Thomas fire perimeter')
label
# ---Legend-----------------------------------------------------------------------------------------------------------------
"Fire scar of Thomas Fire, 2017") # title
plt.title(= [wildfires_patch], frameon = False, loc = "upper right", labelcolor = "white")
ax.legend(handles
# ------Save Image----------------------------------------------------------------------------------------------------------
'images/sb_thomas_fire_2017.png',bbox_inches = 'tight',dpi = 100)
plt.savefig( plt.show()
Based on the map we can see that Thomas Fire heavily affected Ventura and Ojai.
Code for making Geographic context
{"tags": [
"hide-cell",
]
}
#--------- Import California boundary -----------------------------------------
= gpd.read_file("data/california_boundary/CA_State_TIGER2016.shp")
california = gpd.read_file("data/california_counties_boundaries/CA_Counties_TIGER2016.shp")
cali_counties
# -------Filter to Santa Barbara ----------------------------------------------
= cali_counties[cali_counties.NAME == "Santa Barbara"]
santa_barbara # ---------Create Map----------------------------------------------------------
= plt.subplots()
fig, ax 'off')
ax.axis(
"Santa Barbara County Location in California")
ax.set_title(
=ax,color = 'bisque')
california.plot(ax=ax, color = 'plum', edgecolor = "black")
santa_barbara.plot(ax= mpatches.Patch(color = "plum",
sb_patch = 'Santa Barbara')
label = [sb_patch], frameon = False, loc = "lower left", labelcolor = "black")
ax.legend(handles
'../Santa-Barbara-Thomas-Fire/images/sb_ca.png',bbox_inches = 'tight',dpi = 100) plt.savefig(
Citation
@online{vaquero,
author = {Vaquero, Hazel},
title = {2021 {Thomas} {Fire} {Air} {Quality} {Index} and {Fire}
{Scar} {Analysis}},
url = {https://hazelvaq.github.io/blog/2023-12-23-SB-Thomas-Fire/},
langid = {en}
}