Density of observations/plots in climate space#

We want to determine the distribution and density of the iNaturalist observations and the sPlotOpen vegetation plots in climate space, specifically temperature / percipitation space.

This section covers:

  • Extract temperature and percipitation data from WorldClim

  • Plotting density in climate space

import pandas as pd
import numpy as np
import os
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.colors import LogNorm, Normalize
import cartopy.crs as ccrs
from matplotlib.colors import BoundaryNorm
from matplotlib.ticker import MaxNLocator
import rasterio as rio
from rasterio.plot import show
import geopandas as gpd
# open files
sPlot = pd.read_csv("sPlotOpen/cwm_loc.csv")

# open file with all iNaturalist observations and trait values
iNat = pd.read_csv("iNat_TRY_log.csv")

Convert to geodataframe, so that we can work with the geopandas geometry:

geo_iNat = gpd.GeoDataFrame( iNat.iloc[:,:22], geometry=gpd.points_from_xy(iNat.decimalLongitude, iNat.decimalLatitude), 
                            crs='epsg:4326')
geo_sPlot = gpd.GeoDataFrame(sPlot, geometry=gpd.points_from_xy(sPlot.Longitude, sPlot.Latitude), crs='epsg:4326')

Extract temperature and percipitation data from WorldClim#

# Open the raster of temperature and percipitation information

perc = rio.open('WorldClim/wc2.1_2.5m_bio_12.tif')
temp = rio.open('WorldClim/wc2.1_2.5m_bio_1.tif')
#https://gis.stackexchange.com/questions/317391/python-extract-raster-values-at-point-locations

# Read points from shapefile
clim_sPlot = geo_sPlot
clim_sPlot = clim_sPlot[['Longitude', 'Latitude','PlotObservationID','geometry']]
clim_sPlot.index = range(len(clim_sPlot))
coords = [(x,y) for x, y in zip(clim_sPlot.Longitude, clim_sPlot.Latitude)]

# Sample the raster at every point location and store values in DataFrame
clim_sPlot['Perc'] = [x[0] for x in perc.sample(coords)]
clim_sPlot['Temp'] = [x[0] for x in temp.sample(coords)]
# about 15 min

# Read points from shapefile
clim_iNat = iNat[['decimalLongitude', 'decimalLatitude','scientificName', 'eventDate']]
clim_iNat = clim_iNat[clim_iNat['decimalLongitude'].notna()]
clim_iNat = clim_iNat[clim_iNat['decimalLatitude'].notna()]
clim_iNat.index = range(len(clim_iNat))
coords = [(x,y) for x, y in zip(clim_iNat.decimalLongitude, clim_iNat.decimalLatitude)]

# Sample the raster at every point location and store values in DataFrame
clim_iNat['Perc'] = [x[0] for x in perc.sample(coords)]
clim_iNat['Temp'] = [x[0] for x in temp.sample(coords)]

Save climate data#

clim_iNat.to_csv("iNat_climate_variables.csv", index=False)
clim_sPlot.to_csv("sPlot_climate_variables.csv", index=False)

Plot in climate space#

# open files
clim_sPlot = pd.read_csv("sPlot_climate_variables.csv")
clim_iNat = pd.read_csv("iNat_climate_variables.csv")
# read Whittaker coordinates
# data taken from R package "plotbiomes": https://github.com/valentinitnelav/plotbiomes

Whittaker = pd.read_csv("Whittaker_biomes.csv")
Whittaker.head()
temp_c precp_cm biome_id biome
0 -10.216002 1.607134 6 Tundra
1 -10.628573 1.696938 6 Tundra
2 -11.141165 1.846052 6 Tundra
3 -11.617762 2.028094 6 Tundra
4 -12.059605 2.242129 6 Tundra
# change mm to cm
clim_iNat['Perc'] = clim_iNat['Perc'].div(10)
clim_sPlot['Perc'] = clim_sPlot['Perc'].div(10)
clim_sPlot
Longitude Latitude PlotObservationID geometry Perc Temp
0 -154.180000 62.420000 16 POINT (-154.18 62.42) 42.8 -2.578834
1 -154.180000 62.420000 17 POINT (-154.18 62.42) 42.8 -2.578834
2 -154.180000 62.420000 18 POINT (-154.18 62.42) 42.8 -2.578834
3 -154.180000 62.420000 20 POINT (-154.18 62.42) 42.8 -2.578834
4 -154.180000 62.420000 22 POINT (-154.18 62.42) 42.8 -2.578834
... ... ... ... ... ... ...
95099 27.273862 56.287870 1126749 POINT (27.273862 56.28787) 62.0 5.296333
95100 23.598014 56.939965 1126761 POINT (23.598014 56.939965) 61.7 6.614500
95101 23.598014 56.939965 1126769 POINT (23.598014 56.939965) 61.7 6.614500
95102 22.147667 57.248222 1126774 POINT (22.147667 57.248222) 66.8 6.546000
95103 26.892074 57.563967 1126790 POINT (26.892074 57.563967) 69.2 4.963833

95104 rows × 6 columns

for b in Whittaker['biome_id'].unique():
    subplot = Whittaker[Whittaker['biome_id']==b]
    plt.plot(subplot['temp_c'], subplot['precp_cm'], '-')
    plt.text(subplot["temp_c"].mean(),subplot["precp_cm"].mean(),s=str(subplot["biome"].unique()))
_images/Chapter_9_Observation_density_in_climate_space_20_0.png

Plot sPlotOpen in climate space:

plt.rcParams.update({'font.size': 13})


ax1 = clim_sPlot.plot.hexbin(x='Temp', y='Perc', 
                            gridsize=30, 
                            extent=[-15,30,0,600], 
                            cmap="cool", 
                            mincnt=1, 
                            bins='log', 
                             sharex=False,
                             linewidths=0.1,
                             edgecolors=None,
                             vmax = 400000
                            )

plt.xlabel("Mean Annual Temperature ($^\circ$C)")
plt.ylabel("Mean Annual Percipitation (cm)")

# add Whittaker biome line
for b in Whittaker['biome_id'].unique():
    subplot = Whittaker[Whittaker['biome_id']==b]
    plt.plot(subplot['temp_c'], subplot['precp_cm'], '-', color="midnightblue", linewidth=1)

plt.savefig('../Figures/sPlot_density_climate_space_tight.pdf', bbox_inches='tight')  
_images/Chapter_9_Observation_density_in_climate_space_22_0.png

Plot iNaturalist observations in climate space:

plt.rcParams.update({'font.size': 13})
ax2= clim_iNat.plot.hexbin(x='Temp', y='Perc', 
                           gridsize=30, 
                           extent=[-15,30,0,600], 
                           cmap="cool", 
                           mincnt=1, 
                           bins='log', 
                           sharex=False,
                            linewidths=0.1,
                            edgecolors=None,
                          vmax= 400000)
plt.xlabel("Mean Annual Temperature ($^\circ$C)")
plt.ylabel("Mean Annual Percipitation (cm)")

# add Whittaker biome line
for b in Whittaker['biome_id'].unique():
    subplot = Whittaker[Whittaker['biome_id']==b]
    plt.plot(subplot['temp_c'], subplot['precp_cm'], '-', color="midnightblue", linewidth=1)

plt.savefig('../Figures/iNat_density_climate_space_tight.pdf', bbox_inches='tight')  
_images/Chapter_9_Observation_density_in_climate_space_24_0.png