-
Francesco Sabatini authoredFrancesco Sabatini authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
01b_MesobromionCluster.R 7.37 KiB
#Functions to define correlations between Beals, SYNCSA, ENV
# W - Sp. composition
# X - fuzzy weighted
# Y - Beals
# B - traits
# E - Environment
require(tidyverse)
require(SYNCSA)
require(vegan)
require(abind)
require(ade4)
require(parallel)
require(doParallel)
source("99_HIDDEN_functions.R")
get.ci <- function(corXY){
corXY %>%
filter(bootstr.n==0) %>%
dplyr::select(-bootstr.n) %>%
group_by(Trait.comb) %>%
slice(1) %>%
left_join(corXY %>%
filter(bootstr.n!=0) %>%
group_by(Trait.comb) %>%
summarize(q025=quantile(Coef.obs, 0.025),
q975=quantile(Coef.obs, 0.975),
greater.than.perm=mean(Coef.obs>Coef.perm),
n=n())) %>%
#calculate significance using permuted correlations
mutate(sign_plus=greater.than.perm>0.995) %>%
mutate(sign_minus=greater.than.perm<0.005) %>%
ungroup() %>%
mutate(Trait.comb=as.character(Trait.comb)) %>%
rowwise() %>%
mutate(ntraits= length(unlist(strsplit(Trait.comb, split = "_")))) %>%
ungroup() %>%
arrange(ntraits, Coef.obs)
}
get.best <- function(x, N){
out <- x %>%
filter(ntraits==N) %>%
filter(sign_plus==TRUE) %>%
arrange(desc(Coef.obs)) %>%
slice(1) %>%
pull(Trait.comb)
return(out)
}
Mesobromion <- function(species.path, traits.path, output, myfunction="get.corXY.bootstrap",
combinations=c("all", "sequential"), max.inter.t, chunkn, chunk.i, nperm=199, ncores=1){
if(ncores>1){
require(parallel)
require(doParallel)
cl <- makeForkCluster(ncores, outfile="" )
registerDoParallel(cl)
`%myinfix%` <- `%dopar%`
} else {
`%myinfix%` <- `%do%`
}
myfunction <- get(myfunction)
## calculate corr between species composition matrix and traits
species <- read_delim(species.path, delim="\t") %>%
as.data.frame()
traits <- read_delim(traits.path, delim="\t") %>%
as.data.frame() %>%
### TEMPORARY FOR TESTING!
dplyr::select(1:11)
traits <- traits %>%
column_to_rownames("species0") %>%
rename_all(.funs=~gsub(pattern=".mean$", replacement="", x=.)) #%>%
#temporary ### Use only a subset of traits
#dplyr::select(LeafArea:Disp.unit.leng)
if(combinations=="all") {
## create list of indices for each combination of traits up to a max number of interactions
n.traits <- ncol(traits)
allcomb.t <- NULL
for(n.inter in 1:max.inter.t){
allcomb.t <- c(allcomb.t, combn(1:n.traits, n.inter, simplify=F))
}
nall <- length(allcomb.t)
## Divide in chunks if requested
if(chunkn>1 & !is.na(chunk.i)){
print(paste("Test all Combo - divide in", chunkn, "chunks and run on chunk n.", chunk.i))
indices <- 1:length(allcomb.t)
chunks <- split(indices, sort(indices%%chunkn))
allcomb.t <- allcomb.t[chunks[[chunk.i]]]
}
print(paste("Running on", length(allcomb.t),"out of", nall, "combinations"))
#names.t <- unlist(lapply(allcomb.t, paste, collapse="_"))
print("Start main loop")
corXY.output <- NULL
corXY.output <- foreach(i=1:length(allcomb.t), .combine=rbind) %myinfix% {
tt <- unlist(allcomb.t[i])
corXY.output <- rbind(corXY.output,
get.corXY.bootstrap(comm=species, trait=traits,
trait.sel=tt, bootstrap=nperm))
}
save(corXY.output, file = paste(output, "_.RData", sep=""))
}
if(combinations=="sequential"){
corXY.output <- NULL
for(nround in 1:max.inter.t){
## select combination of traits based on best
if(nround==1) {
allcomb.t <- lapply(1:ncol(traits), function(x){return(x)})
nall <- length(allcomb.t)
} else {
best.split <- as.numeric(unlist(strsplit(best, "_")))
max.inter.t <- nround-1
#n.traits <- ncol(traits)
list.traits <- as.numeric(traits.sign.alone)
list.traits <- list.traits[-which(list.traits %in% best.split)] ## list of remaining traits without best
if(length(list.traits) < max.inter.t) {
save(corXY.output, file = paste(output, ".RData", sep=""))
if(ncores>1) {stopCluster(cl)}
stop("Tested all combo of significant traits")
}
allcomb.t <- NULL
#for(n.inter in 1:max.inter.t){
allcomb.t <- c(allcomb.t, combn(list.traits, max.inter.t, simplify=F))
#}
#add best to all combo
allcomb.t <- lapply(allcomb.t, function(x){return(c(best.split, x))})
nall <- length(allcomb.t)
}
## Divide in chunks if requested
if(chunkn>1){
print(paste("nround", nround, "--- divide in", chunkn, "chunks"))
indices <- 1:length(allcomb.t)
chunks <- split(indices, sort(indices%%chunkn))
} else {chunks <- list(1:length(allcomb.t))}
#names.t <- unlist(lapply(allcomb.t, paste, collapse="_"))
## start main foreach loop
print(paste("Start main loop - round", nround))
corXY.output <- foreach(ch=chunks, .combine=rbind) %myinfix% {
allcomb.i <- allcomb.t[unlist(ch)]
print(paste("Running on", length(allcomb.i),"out of", nall, "combinations"))
for(i in 1:length(allcomb.i)){
tt <- unlist(allcomb.i[i])
corXY.output <- rbind(corXY.output,
get.corXY.bootstrap(comm=species, trait=traits,
trait.sel=tt, bootstrap=nperm))
}
return(corXY.output)
}
#Intermediate save
#save(corXY.output, file = paste(output, "_", nround, ".RData", sep=""))
print(paste("Summarize after round", nround, "and find best, significant trait combos"))
corXY.ci <- get.ci(corXY.output)
##get best or new best
if(nround==1) {
traits.sign.alone <- corXY.ci %>%
filter(ntraits==1) %>%
filter(sign_plus==T) %>%
pull(Trait.comb)
if(length(traits.sign.alone)==0) {
stop("No trait is significant taken singularly")}
print(paste("Traits significant taken singularly:", paste(traits.sign.alone, collapse=" ")))
best <- get.best(corXY.ci, N=1)
best.row <- corXY.ci %>%
filter(Trait.comb==best)
upper <- best.row$q975
lower <- best.row$q025
print(paste("new best at nround=", nround, "is trait combination", best))
}
if(nround>1){
better <- corXY.ci %>%
filter(ntraits==nround) %>%
filter(q025>upper) %>%
arrange(desc(Coef.obs)) %>%
slice(1) %>%
pull(Trait.comb)
if(length(better>0)){
new.best.row <- corXY.ci %>%
#rowwise() %>%
#mutate(nmatching= sum(unlist(strsplit(Trait.comb, "_")) %in%
# unlist(strsplit(better, "_")),
# na.rm=T)) %>%
#ungroup() %>%
#filter(nmatching==nround) %>%
filter(Trait.comb==better)
upper <- new.best.row$q975
lower <- new.best.row$q025
best <- better
print(paste("new best at round=", nround, "is trait combination", best))
} else {print(paste("no new best at round=", nround))}
}
}
save(corXY.output, file = paste(output, ".RData", sep=""))
}
if(ncores>1){stopCluster(cl)}
}