ELE_1689_sm_AppendixS3

advertisement
Appendix S3
## CODE FOR MODEL SIMULATION
## -------- FUNCTIONS TO SIMULATE RANGE SHIFTS ------------# tempconv() convert temp to elevation
# int.mat() determines range overlaps as co_occurrences
# range.shift() deterministic model of range shift
# cm.taxon() does all range.shift runs for each taxon
# FUNCTION TO CREATE co_occurrence MATRIX based on ranges
int.mat <- function(species,ELmin,ELmax)
{
temp.mat <- matrix(0,nrow=length(species),ncol=length(species))
for (i in 1:length(species))
{ for (j in 1:length(species))
{ if (i < j & ELmin[j] <= ELmax[i] & is.na(ELmin[j])==FALSE &
is.na(ELmax[i])==FALSE )
temp.mat[i,j] = 1
} # end of for j spp loop
} # end for i spp loop
temp.mat
} # end of function
# RANGE SHIFT FUNCTION (calls on tempconv, elevconv, int.mat, tempshift = number of
degrees shifting; habitat = 'none', 'upper', 'lower', or 'both' limit(s) to strictly set by physiological
tolerance; dispersal = a coefficient(0,1), 'infinite', or 'random'; subsample = number of spp to
control for biodiversity or 'FALSE')
range.shift <- function(cmrange,Site,Taxon,tempshift='predicted',habitat='both',dispersal)
{
# subset the data and extract necessary variables:
subtaxon <- subset(cmrange,cmrange$site==Site & cmrange$taxa==Taxon)
# range limits set as midpoints between last observed and first absent data in each direction
ELmin <- rowMeans(cbind(ELmin,subtaxon$low_absent))
ELmax <- rowMeans(cbind(ELmax,subtaxon$high_absent))
# convert elevation (m) into temperature(degC):
lapse <- subtaxon$lapse/1000 # degraes/m
tempconv <- function(elev,meanT,newelev)
{ meanT - lapse*(newelev - elev) }
elev <- mean(subtaxon$elev)
meanT <- mean(subtaxon$mean)
CTmin <- tempconv(elev,meanT,ELmin)
CTmax <- tempconv(elev,meanT,ELmax)
j <- order(ELmin,ELmax) # order subset by range height
subtaxon <- subtaxon[j,]
ELmin <- ELmin[j]
ELmax <- ELmax[j]
CTmin <- CTmin[j]
CTmax <- CTmax[j]
species <- subtaxon$species[j]
if (tempshift == 'predicted')
{tempshift <- mean(subtaxon$projected_mean)}
if (habitat == 'both')
{ nhabmin <- ELmin + (1/lapse)*tempshift # new habitable ELmin after climate
change (CC)
nhabmax <- ELmax + (1/lapse)*tempshift # new habitable ELmax post-CC
nhabmax[nhabmax >= mean(subtaxon$mountmax)] <mean(subtaxon$mountmax)
nhabmin[nhabmin < 0] <- 0
nhabmax[nhabmax >= mean(subtaxon$mountmax)] <mean(subtaxon$mountmax)
}
if (habitat == 'none') # no limits determined by physiological tolerance
{ nhabmin <- ELmin
nhabmax <- ELmax
}
if (habitat == 'lower') # only lower limit is defined by physiology
{ nhabmin <- ELmin + (1/lapse)*tempshift
nhabmax <- ELmax
}
if (habitat == 'upper') # only upper limit is defined by physiology
{ nhabmin <- ELmin
nhabmax <- ELmax + (1/lapse)*tempshift
nhabmax[nhabmax >= mean(subtaxon$mountmax)] <mean(subtaxon$mountmax)
}
# add in dispersal ability
if (dispersal == 'infinite')
{post.max <- nhabmax
post.min <- nhabmin}
if (class(dispersal) == 'numeric' & length(dispersal)==1)
{ rangesize <- ELmax-ELmin
d.ability <- dispersal*rangesize
post.max <- ELmax + d.ability # with no dispersal, upper range poss: ELmax
post.min <- ELmin - d.ability
nix <- which(nhabmin>post.max) # find spp where dispersed max is less than new
habitable minimum
post.min[nhabmin > post.min] <- nhabmin[nhabmin > post.min]
post.max[nhabmax < post.max] <- nhabmax[nhabmax < post.max]
#remove extinct spp
post.min[nix]<- NA
post.max[nix]<- NA
}
if (dispersal == 'random') # selects from a log-normal distribution
{ # solve for mu and sigma of lognormal distribution from the mean E(x) and
variance Var(x) according to equations found in the rlnorm help file
mu_sd <- function(taxon)
{ data <- subset(cmrange,cmrange$taxa==taxon)
range <- data$maxelev-data$minelev
EX <- mean(range)
VarX <- var(range)
sigma <- sqrt(log((log(VarX)/(2*log(EX)))+1))
mu <- log(EX)-0.5*sigma^2
# hist(range,xlab='range size (m)',freq=FALSE,main=taxon)
# curve((1/(sqrt(2*pi)*sigma*x))*exp(-((log(x) - mu)^2 / (2*sigma^2))),col=2,add=T)
cbind(mu,sigma)
}
lgnrm <- mu_sd(taxon=Taxon)
rangesize <- ELmax-ELmin
d.ability <- rlnorm(length(ELmin), meanlog=lgnrm[1], sdlog=lgnrm[2])
post.min <- ELmin - d.ability
post.max <- ELmax + d.ability
nix <- which(nhabmin>post.max)
post.min[nhabmin > post.min] <- nhabmin[nhabmin > post.min]
post.max[nhabmax < post.max] <- nhabmax[nhabmax < post.max]
#remove extinct spp
post.min[nix]<- NA
post.max[nix]<- NA
dispersal <- 'random'
}
if (length(dispersal) == 2) # selects from a log-normal distribution with dispersal =
c(meanlog,sdlog)
{ rangesize <- ELmax-ELmin
d.ability <- rlnorm(length(ELmin), meanlog=dispersal[1], sdlog=dispersal[2])
post.min <- ELmin - d.ability
post.max <- ELmax + d.ability
nix <- which(nhabmin>post.max)
post.min[nhabmin > post.min] <- nhabmin[nhabmin > post.min]
post.max[nhabmax < post.max] <- nhabmax[nhabmax < post.max]
#remove extinct spp
post.min[nix]<- NA
post.max[nix]<- NA
dispersal <- dispersal[2]
}
post.min[post.min>post.max] <- NA
post.max[post.min>post.max] <- NA
post.min[post.min<0] <- NA
post.max[post.max<0] <- NA
extinct <- sum(is.na(post.min))
# calculate changes in co_occurrences
intI <- int.mat(species,ELmin,ELmax) # create initial co_occurrence matrix
intF <- int.mat(species,post.min,post.max) # create final co_occurrence matrix
intF[post.max==0,] <- 0
intF[,post.max==0] <- 0
Dint <- intF-intI
int.poss <- sum(intI)
int.lost <- sum(Dint==-1)
int.gain <- sum(Dint==1)
#outputs
pre.rangesize <- mean(ELmax-ELmin,na.rm=T)
post.rangesize <- mean(post.max-post.min,na.rm=T)
latit <- mean(subtaxon$lat)
output1 <c(Taxon,Site,latit,habitat,dispersal,mean(lapse),tempshift,length(species),extinct,int.poss,int.lost,
int.gain,pre.rangesize,post.rangesize)
names(output1) <c('taxon','site','latitude','habitat','dispersal','lapse','Tshift','spp','extinct','t_int','lost','gain','pre.range',
'post.range')
output1
} # end range.shift function
# FUNCTION TO RUN range.shift() with predicted temperature shifts for a particular taxon,
habitat=both, and 4 dispersal types (0,1,'infinite', and 10 replicates of 'random')
cm.taxon <- function(cmrange,Taxon,tempshift='predicted')
{ LAT <- tapply(cmrange$lat,list(cmrange$taxa,cmrange$site),mean,na.rm=T)
omitLAT <- na.omit(LAT[Taxon,])
data3 <matrix(NA,nrow=1,ncol=14,dimnames=list('',c('taxon','site','latitude','habitat','dispersal','lapse','Ts
hift','spp','extinct','t_int','lost','gain','pre.range','post.range')))
for (i in 1:length(omitLAT)) # for every site
{temp1<range.shift(cmrange,Site=labels(omitLAT)[i],Taxon=Taxon,tempshift=tempshift,
habitat='both',dispersal=0)
data3 <- rbind(data3,temp1)
temp2<-range.shift(cmrange,Site=labels(omitLAT)[i],Taxon=Taxon,tempshift=tempshift,
habitat='both',dispersal=1)
data3 <- rbind(data3,temp2)
temp3<-range.shift(cmrange,Site=labels(omitLAT)[i],Taxon=Taxon,tempshift=tempshift,
habitat='both',dispersal='infinite')
data3 <- rbind(data3,temp3)
for (j in 1:10) # for 10 replicates of random scenario
{ temp4<-range.shift(cmrange,Site=labels(omitLAT)[i],Taxon=Taxon,tempshift=tempshift,
habitat='both',dispersal='random')
print(Taxon)
print(j)
data3 <- rbind(data3,temp4)
}
} # end for every site
data3
} # end cm.taxon() function
# -- FUNCTIONS
setwd('/Users/sylvia/Documents/Rwork')
cmrange <- read.csv('climaterange_new.csv')
#levels(cmrange$taxa)
# dispersal <- 'infinite','random' or scaling coefficient for range size that describes the proportion
of new range that the animal actually disperses to (0 = does not track, 1 = proportionally tracks
new range), (calls on tempconv, elevconv, int.mat, tempshift = number of degrees shifting;
habitat = 'none', 'upper', 'lower', or 'both' limit(s) to strictly set by physiological tolerance;
dispersal = a coefficient(0,1), 'infinite', or 'random'; subsample = number of spp to control for
biodiversity or 'FALSE')
# simulation runs
dung <- cm.taxon(cmrange,Taxon='dung',tempshift='predicted')
bird <- cm.taxon(cmrange,Taxon='bird',tempshift='predicted')
lizd <- cm.taxon(cmrange,Taxon='lizard',tempshift='predicted')
frog <- cm.taxon(cmrange,Taxon='frog',tempshift='predicted')
rodt <- cm.taxon(cmrange,Taxon='rodentia',tempshift='predicted')
snke <- cm.taxon(cmrange,Taxon='snake',tempshift='predicted')
simdata <- data.frame(rbind(bird,dung,frog,lizd,rodt,snke),row.names=NULL)
simdata
write.csv(simdata,file='climatesim041811.csv', row.names=FALSE)
# --- KEEP PREDICTED temp CHANGE CONSTANT --- #
st <- tapply(cmrange$lat,list(cmrange$site,cmrange$taxa),mean,na.rm=T)
st <- as.data.frame(st)
tax <- labels(st)[[2]]
allsites <- labels(st)[[1]]
taxtempfull <- matrix(NA,ncol=14)
for (k in 1:length(tax)) # for each taxon
{
sites <- allsites[-which(is.na(st[,k]))] # which sites exist with data
for (j in 1:length(sites)) # for each site in taxon
{
sub.lat <- mean(cmrange$lat[cmrange$taxa==tax[k] & cmrange$site==sites[j]],na.rm=T)
print(c(sites[j],tax[k],sub.lat))
taxtemp <- rbind(
range.shift(cmrange,Site=sites[j],Taxon=tax[k],tempshift=0,habitat='both',dispersal=1),
range.shift(cmrange,Site=sites[j],Taxon=tax[k],tempshift=1,habitat='both',dispersal=1),
range.shift(cmrange,Site=sites[j],Taxon=tax[k],tempshift=2,habitat='both',dispersal=1),
range.shift(cmrange,Site=sites[j],Taxon=tax[k],tempshift=3,habitat='both',dispersal=1),
range.shift(cmrange,Site=sites[j],Taxon=tax[k],tempshift=4,habitat='both',dispersal=1),
range.shift(cmrange,Site=sites[j],Taxon=tax[k],tempshift=5,habitat='both',dispersal=1))
taxtempfull <- rbind(taxtempfull,taxtemp)
}
}
taxtempfull
taxtempfull <- as.data.frame(taxtempfull)
write.csv(taxtempfull,file='climatetemp041911.csv',row.names=FALSE)
# --- VARY RANDOM DISPERSAL variance parameter --- #
# solve for mu and sigma of lognormal distribution from the mean E(x) and variance Var(x)
according to equations found in the rlnorm help file
mu_sd <- function(taxon)
{ data <- subset(cmrange,cmrange$taxa==taxon)
range <- data$maxelev-data$minelev
EX <- mean(range)
VarX <- var(range)
sigma <- sqrt(log((log(VarX)/(2*log(EX)))+1))
mu <- log(EX)-0.5*sigma^2
cbind(mu,sigma)
}
st <- tapply(cmrange$lat,list(cmrange$site,cmrange$taxa),mean,na.rm=T)
st <- as.data.frame(st)
tax <- labels(st)[[2]]
allsites <- labels(st)[[1]]
taxSDfull <- matrix(NA,ncol=14)
for (k in 1:length(tax)) # for each taxon
{ sites <- allsites[-which(is.na(st[,k]))] # which sites exist with data
for (j in 1:length(sites)) # for each site in taxon
{
# for (m in 1:3) # number of replicates
# {
sub.lat <- mean(cmrange$lat[cmrange$taxa==tax[k] & cmrange$site==sites[j]],na.rm=T)
print(c(sites[j],tax[k],sub.lat))
taxSD <- rbind(
range.shift(cmrange,Site=sites[j],Taxon=tax[k],tempshift='predicted',habitat='both',dispersal=c(
mu_sd(taxon=tax[k])[1],0.825)),
range.shift(cmrange,Site=sites[j],Taxon=tax[k],tempshift='predicted',habitat='both',dispersal=c(
mu_sd(taxon=tax[k])[1],0.83)),
range.shift(cmrange,Site=sites[j],Taxon=tax[k],tempshift='predicted',habitat='both',dispersal=c(
mu_sd(taxon=tax[k])[1],0.85)),
range.shift(cmrange,Site=sites[j],Taxon=tax[k],tempshift='predicted',habitat='both',dispersal=c(
mu_sd(taxon=tax[k])[1],0.9)),
range.shift(cmrange,Site=sites[j],Taxon=tax[k],tempshift='predicted',habitat='both',dispersal=c(
mu_sd(taxon=tax[k])[1],0.95)),
range.shift(cmrange,Site=sites[j],Taxon=tax[k],tempshift='predicted',habitat='both',dispersal=c(
mu_sd(taxon=tax[k])[1],0.99)),
range.shift(cmrange,Site=sites[j],Taxon=tax[k],tempshift='predicted',habitat='both',dispersal=c(
mu_sd(taxon=tax[k])[1],2)),
range.shift(cmrange,Site=sites[j],Taxon=tax[k],tempshift='predicted',habitat='both',dispersal=c(
mu_sd(taxon=tax[k])[1],4)),
range.shift(cmrange,Site=sites[j],Taxon=tax[k],tempshift='predicted',habitat='both',dispersal=c(
mu_sd(taxon=tax[k])[1],8))
)
taxSDfull <- rbind(taxSDfull,taxSD)
# } # for each replicate
} # for each site
} # for each taxon
taxSDfull <- as.data.frame(taxSDfull)
taxSDfull
write.csv(taxSDfull,file='climatedisp041911.csv',row.names=FALSE)
Download