# Load libraries
import numpy as np
import geopandas as gpd
import xarray as xr
import rioxarray as rioxr
import matplotlib.pyplot as plt
from matplotlib.patches import Patch
from matplotlib.lines import Line2D
from matplotlib.colors import ListedColormap
from shapely.geometry import Polygon
from pystac_client import Client
import planetary_computer
import rasterio
from rasterio.plot import show
import contextily as ctx
Biodiversity in Phoenix, Arizona
Link to GitHub repository
Introduction
Purpose
The purpose of this analysis is to better understand and visualize biodiversity in Phoenix and highlight areas where biodiversity is declining. Specifically, the final map will show a map of Phoenix displayed on 100 meter grid-cells colored based on the area’s 2020 Biodiversity Intactness Index (BII), which is a score from 0 to 1. In addition, areas where BII declined from greater than 0.75 in 2017 to less than 0.75 in 2020 will be highlighted in a seperate color.
Highlights of analysis
- Add basemap with Contextily
- Fetch items from Microsoft Planetary Computer (MPC) catalog using search criteria
- Clip biodiversity raster based on polygon from shapefile of Arizona subdivisions
- Calculate percent of area with BII>0.75 in 2017 and 2020
- Visualize 2020 biodiversity and changes from 2017
Dataset descriptions
- The primary dataset used in this analysis estimates terrestrial Biodiversity Intactness as a 100-meter gridded maps for years 2017 to 2020. The data contained in the dataset comes from Impact Observatory and Vizzuality, and they generated the data using a database of spatially referenced observations of biodiversity across 32,000 sites and over 750 studies. The data was accessed from the Microsoft Planetary Computer (MPC) catalog.
- A dataset from the U.S. Census Bureau was used to clip biodiversity raster.
References to datasets
- Impact Observatory & Vizzuality. 2022. “Biodiversity Intactness.” Accessed via Microsoft Planetary Computer (MPC) Catalog. https://planetarycomputer.microsoft.com/dataset/io-biodiversity#overview.
- U.S. Census Bureau. 2022. “2022 TIGER/Line Shapefiles: County Subdivision”. https://www.census.gov/cgi-bin/geo/shapefiles/index.php?year=2022&layergroup=County+Subdivisions
1) Import libraries
2) Read in data
Biodiversity data
# Access catalog
= Client.open(
catalog "https://planetarycomputer.microsoft.com/api/stac/v1",
=planetary_computer.sign_inplace,
modifier
)
# Set temporal range of interest
= "2017-01-01/2020-01-01"
time_range
# Set Phoenix bounding box
= [-112.826843, 32.974108, -111.184387, 33.863574]
bbox
# Search catalog
= catalog.search(
search = ['io-biodiversity'],
collections = bbox,
bbox = time_range)
datetime
# Get items from search as list
= search.item_collection()
items print(f'There are {len(items)} items in the search.')
There are 4 items in the search.
# Store individual items
= items[0]
item_2020 = items[3]
item_2017
# Check CRS
'proj:epsg'] item_2017.properties[
4326
# Store raster data from items
= rioxr.open_rasterio(item_2020.assets['data'].href)
bii_2020 = rioxr.open_rasterio(item_2017.assets['data'].href)
bii_2017
# Print original dimensions and coords
print('Original 2017 raster', bii_2017.dims, bii_2017.coords, '\n')
# Remove length band dimension
# Print updated dimensions and coords
= bii_2020.squeeze()
bii_2020 = bii_2017.squeeze()
bii_2017
# Remove coordinates associated to band
= bii_2020.drop('band')
bii_2020 = bii_2017.drop('band')
bii_2017
# Print updated dimensions and coords
print('Updated 2017 raster', bii_2017.dims, bii_2017.coords, '\n')
Original 2017 raster ('band', 'y', 'x') Coordinates:
* band (band) int64 1
* x (x) float64 -115.4 -115.4 -115.4 ... -108.2 -108.2 -108.2
* y (y) float64 34.74 34.74 34.74 34.74 ... 27.57 27.57 27.57 27.57
spatial_ref int64 0
Updated 2017 raster ('y', 'x') Coordinates:
* x (x) float64 -115.4 -115.4 -115.4 ... -108.2 -108.2 -108.2
* y (y) float64 34.74 34.74 34.74 34.74 ... 27.57 27.57 27.57 27.57
spatial_ref int64 0
Arizona shapefile
# Read in Arizona shapefile
= gpd.read_file("data/tl_2022_04_cousub/tl_2022_04_cousub.shp")
arizona
# Select Phoenix subdivision
= arizona[arizona['NAME'] == 'Phoenix']
phoenix
# Convert CRS to match MPC data
= phoenix.to_crs('4326')
phoenix
# Check for matching CRS (should return True)
'proj:epsg'] == phoenix.crs item_2017.properties[
True
3) Create basic map of Phoenix subdivision
# Set axis for Phoenix
= phoenix.plot(figsize=(10, 10), alpha=0.5, edgecolor='k')
ax
# Add basemap from OpenStreetMap using Contextily
=phoenix.crs.to_string(), source=ctx.providers.OpenStreetMap.Mapnik)
ctx.add_basemap(ax, crs
# Add title
"Map of Phoenix subdivision")
plt.title(
# Display map
plt.show()
4) Clip rasters and calculate percent area with BII > 0.75 for 2017 and 2020
# Clip the rasters to Phoenix geometry
= bii_2017.rio.clip(phoenix.geometry, crs='4326')
bii_2017_clipped = bii_2020.rio.clip(phoenix.geometry, crs='4326')
bii_2020_clipped
# Calculate percent area with BII>0.75
= (np.sum(bii_2017_clipped > 0.75) / np.sum(bii_2017_clipped > 0)) * 100
percent_area_2017 = (np.sum(bii_2020_clipped > 0.75) / np.sum(bii_2020_clipped > 0)) * 100
percent_area_2020
# Print percents
print(f"Percentage of area with BII>0.75 in 2017: {percent_area_2017:.2f}%")
print(f"Percentage of area with BII>0.75 in 2020: {percent_area_2020:.2f}%")
Percentage of area with BII>0.75 in 2017: 7.13%
Percentage of area with BII>0.75 in 2020: 6.49%
5) Visualize 2020 BII and changes from 2017
# Make raster representing the area with BII>0.75 in 2017 that was lost by 2020
= (bii_2017_clipped > 0.75) & (bii_2020_clipped < 0.75)
lost_area
# Check that lost area raster has same spatial reference dimension as original rasters (should return True)
if lost_area.spatial_ref == bii_2017.spatial_ref == bii_2017.spatial_ref:
print('True')
True
# Convert bools to binary values
= lost_area.astype(int)
lost_area_numeric
# Replace zeros with NaN
= lost_area_numeric.where(lost_area_numeric == 1)
cropped_lost_area
# Define custom colormap for the lost area
= ListedColormap(['red'])
custom_cmap
# Plot figure and axis with custom colorbar
= plt.subplots()
fig, ax = bii_2020_clipped.plot(ax=ax, cmap='Blues', add_colorbar=False)
im =ax, cmap=custom_cmap, add_colorbar=False)
cropped_lost_area.plot(ax= plt.colorbar(im, orientation='horizontal', pad=0.15)
cbar 'Biodiversity Intactness Index (BII)')
cbar.set_label(False)
cbar.outline.set_visible(
# Create legend patch
= Patch(color='red', label='Area where 2017 BII > 0.75 but 2020 BII < 0.75')
red_patch
# Add legend below the figure
= fig.add_axes([0.80, 0.2, 0.02, 0.12])
legend_ax =[red_patch], ncol=1, frameon=False)
legend_ax.legend(handles'off')
legend_ax.axis(
# Add title
= 'Biodiversity in Phoenix, Arizona (2020)'
title_text
ax.set_title(title_text)
# Remove axis labels and ticks
'')
ax.set_xlabel('')
ax.set_ylabel(
ax.set_xticks([])
ax.set_yticks([])
# Remove frame around the entire figure
False)
ax.set_frame_on(
# Show the plot
plt.show()
From this map, we can see how the edges of certain areas in Phoenix, which had relatively high BII, decrease from greater than 0.75 to less than 0.75. In particular, this can be seen in the North East area of Phoenix, in addition to one spot in South Central Phoenix.
Citation
@online{ghanadan2023,
author = {Ghanadan, Linus},
title = {Spatial {Analysis} of {Biodiversity} {Changes} in {Phoenix,}
{AZ}},
date = {2023-12-11},
url = {https://linusghanadan.github.io/blog/2023-12-11-post/phoenix_biodiversity.html},
langid = {en}
}