---
title: "permanova"
author: "Stijn Schreven"
date: "14 juni 2018"
output: html_document
---
# Permutational Multivariate Analysis of Variance (PERMANOVA)  

## 1. Loading data  
```{r}
pseq <- readRDS("./phyobjects/ps1.CM.rds")
pseq <- prune_samples(sample_sums(pseq) > 500, pseq)
pseq.com <- pseq
print(pseq.com)
```

## 2. Preparing data at OTU or genus level  
Convert to relative abundances.

At OTU level:
```{r}
pseq.rel <- microbiome::transform(pseq.com, "compositional")

# for UniFrac need phyloseq with phy_tree
pseqphy.r <- microbiome::transform(pseq, "compositional")
```

At genus level:
```{r}
pseq.com@phy_tree <- NULL
gpseq <- aggregate_taxa(pseq.com, "Genus")
print(gpseq)
pseq.rel <- microbiome::transform(gpseq, "compositional")

# for UniFrac and format_to_besthit() need phyloseq with phy_tree
pseqphy <- aggregate_taxa(pseq, "Genus")
pseqphy.r <- microbiome::transform(pseqphy, "compositional")
```



## 2. Distances calculation  
```{r}
# Pick relative abundances (compositional) and sample metadata 
otu <- abundances(pseq.rel)
meta <- meta(pseq.rel)
# if at genus level, include genus names as row names
#rownames(pseq.df) <- tax_table(pseq.rel)[, "Genus"]

# Bray-Curtis: weighted on rel. abundance, but not on phylogeny
dist.bray <- vegdist(t(otu), method="bray")

# UniFrac: weighted on rel. abundance and phylogeny
dist.unifrac <- UniFrac(pseqphy.r, 
                        weighted = TRUE, 
                        normalized = TRUE,  
                        parallel = FALSE, 
                        fast = TRUE)

# visualisation
#heatmap(as.matrix(dist.unifrac))
#pheatmap(as.matrix(dist.unifrac), border_color=NA)

# create distance matrices for next analyses
mat1 <- as.matrix(dist.unifrac)
mat2 <- as.matrix(dist.bray)

# attach sample labels to distance object (first make matrix from dist object)
#attr(dist,"Labels") <- meta(ps1.CF)$Description
```

## 3. PERMANOVA  
### 3.1. PERMANOVA test
```{r}
# samples x species as input (so transpose otu_table)
permanova <- adonis(t(otu) ~ Type + Density + Timepoint,
               data = meta, permutations=99, method = "bray")
# P-value
print(as.data.frame(permanova$aov.tab))

# Permanova test on UniFrac distances
# use block factor (strata) for Type, in order to constrain permutations (nested design: Density and Timepoint within Type)?
permanova <- adonis(dist.unifrac ~ Type / (Density * Timepoint), data = meta, strata = meta$Type, permutations=999)
print(as.data.frame(permanova$aov.tab))
permanova2 <- adonis(dist.unifrac ~ Type * Density * Timepoint, data = meta, permutations=999)
print(as.data.frame(permanova2$aov.tab))
```

### 3.2. Checking the homogeneity condition  
Note the assumption of similar multivariate spread among the groups, i.e. analogous to variance homogeneity.
If the groups have significantly different spreads, then that may explain a significant permanova result.
```{r}
# tests on homogeneity of multivariate spread
anova(betadisper(dist.unifrac, meta$Type))
permutest(betadisper(dist.unifrac, meta$Type), pairwise = TRUE)

anova(betadisper(dist.unifrac, meta$Timepoint))
permutest(betadisper(dist.unifrac, meta$Timepoint), pairwise = TRUE)

anova(betadisper(dist.unifrac, meta$Density))
permutest(betadisper(dist.unifrac, meta$Density), pairwise = TRUE)
```

## 3.3. Check which taxa contribute most to community differences  
```{r}
# in this case, we look which taxa contribute most to substrate community (=Type1)
coef <- coefficients(permanova)["Type1",]
top.coef <- coef[rev(order(abs(coef)))[1:20]]
par(mar = c(3, 14, 2, 1))
barplot(sort(top.coef), horiz = T, las = 1, main = "Top taxa")
```

## 4. Comparing larvae and substrate samples  

### 4.1. Based on dissimilarity  
```{r}
# extract distance values of larvae-substrate pairs from dist object to dataframe
#1: create dataframe
samples <- subset(meta(pseq.com), select = c(Description,Type,ContainerID,Density,Timepoint))
samples$samTime <- samples$ContainerID:samples$Timepoint
substrates <- subset(samples, Type == "substrate" & Density != 0 & Timepoint != 0)
larvae <- subset(samples, Type == "larvae")
dfdist <- merge(substrates,larvae,by="samTime")
dfdist1 <- subset(dfdist, select = -c(Type.x,Type.y,ContainerID.y,Timepoint.y,Density.y))
colnames(dfdist1) <- c("samTime", "substrate", "ContainerID", "Density", "Timepoint", "larvae")
dfdist1$dist.wuf <- NA
dfdist1$dist.bc <- NA
#2: fill the column "distance"" with the value of each pair from matrix "mat"
for(i in 1:nrow(dfdist1)){
  a = match(dfdist1$substrate[i],labels(mat1)[[1]])
  b = match(dfdist1$larvae[i],labels(mat1)[[2]])
  dfdist1$dist.wuf[i] = mat1[a,b]
  dfdist1$dist.bc[i] = mat2[a,b]
}

plot(dfdist1$dist.wuf~dfdist1$dist.bc);abline(0,1)

#analyse effects of Density and Timepoint on larvae-substrate dissimilarity
## first correct factor levels, and convert factors into continuous variables
class(dfdist1$Density)
levels(dfdist1$Timepoint) # for CS only 1, 2, 3 (5, 10, 15)
levels(dfdist1$Density)
levels(dfdist1$Density)[2] <- "50"
levels(dfdist1$Density)[3] <- "100"
levels(dfdist1$Density)[4] <- "200"
levels(dfdist1$Timepoint)[2] <- "5"
levels(dfdist1$Timepoint)[3] <- "10"
levels(dfdist1$Timepoint)[4] <- "15"
dfdist1$Timepoint <- droplevels(dfdist1$Timepoint)
dfdist1$Timepoint <- as.numeric(paste(dfdist1$Timepoint))
#dfdist1$Density <- as.factor(dfdist1$Density)

# visualise patterns
#bargraph.CI(Timepoint, dist.wuf, group=Density, data=dfdist1,
#            xlab= "Time (d)", ylab = "Weighted UniFrac dissimilarity")
#bargraph.CI(Timepoint, dist.bc, group=Density, data=dfdist1,
#            xlab= "Time (d)", ylab = "Bray-Curtis dissimilarity")
#p <- ggplot(dfdist1, aes(x=Timepoint, y=distance, colour=ContainerID)) + geom_point(aes(shape=Density)) + geom_line()
#p


## model regression: lm seems unfit (heavy tails...)
# lm or gamma glm (heavy right tail?)
#...lmdist <- lm(distance~Timepoint*Density, data=dfdist1)
#lme1 <- gls(distance~1+Timepoint*Density, data=dfdist1, method="REML")
#lme2 <- lme(distance~1+Timepoint*Density, data=dfdist1, method="REML", random=~1|ContainerID)
#validation
#...anova(lmdist)
#summary(lmdist)
#plot(lmdist)
#hist(residuals(lmdist))
```

### 4.2. Comparing larvae and substrate samples, based on Spearman correlations  
```{r}
#1: add correlation data to dfdist1 dataframe
dfdist1$r <- NA
dfdist1$P <- NA

#2: run rcorr function on otu data
pcor <- rcorr(as.matrix(otu), type = "spearman")
#pheatmap(pcor[["r"]], border_color=NA)

#3: fill the columns "r" and "P" with the value of each pair from matrix "prho" and "ppval"
prho <- pcor[["r"]]
ppval <- pcor[["P"]]
for(i in 1:nrow(dfdist1)){
  a = match(dfdist1$substrate[i],labels(prho)[[1]])
  b = match(dfdist1$larvae[i],labels(prho)[[2]])
  dfdist1$r[i] = prho[a,b]
  dfdist1$P[i] = ppval[a,b]
}

# visualize
#bargraph.CI(Timepoint, r, group=Density, data=dfdist1,
#            xlab= "Time (d)", ylab = "Spearman correlation r")

# preliminary (unoptimized) test
lm.r <- lm(r~Timepoint*Density, data=dfdist1)
anova(lm.r)
```

### 4.3. Visualisation of distances and correlations in ggplot
```{r}
# summarize metrics
dist.sum <- ddply(dfdist1, ~Density+Timepoint, summarise, BCmean=mean(dist.bc), BCsd=sd(dist.bc), BCse=se(dist.bc), WUFmean = mean(dist.wuf), WUFsd=sd(dist.wuf),WUFse=se(dist.wuf),rmean=mean(r),rsd=sd(r),rse=se(r))

# Weighted UniFrac distance
pWUF <- ggplot(dist.sum, aes(x=Timepoint, y=WUFmean, group=Density))
pWUF <- pWUF + geom_line(aes(linetype=Density), size=.6) + 
     geom_point(aes(shape=Density), size=2, position=pd) +
     expand_limits(y = 0) +
     #scale_alpha_discrete(name = "Density", range = c(0.4, 1)) +
     scale_color_brewer(name = "Density", palette = "Greens") +
     geom_errorbar(aes(ymin=WUFmean-WUFse, ymax=WUFmean+WUFse), width=.1, position=pd) +
     ylab("Weighted UniFrac distance") + xlab("Time (d)") +
     #facet_grid(rows = vars(Type), cols = vars(Diet)) +
     theme_classic() + theme(text = element_text(size=20), panel.grid.major = element_line(colour = "grey80"),
                             panel.margin = unit(.5,"lines"),
                             panel.border = element_rect(color = "black", fill = NA, size = .3))

# Bray-Curtis dissimilarity
pBC <- ggplot(dist.sum, aes(x=Timepoint, y=BCmean, group=Density))
pBC <- pBC + geom_line(aes(linetype=Density), size=.6) + 
     geom_point(aes(shape=Density), size=2, position=pd) +
     expand_limits(y = 0) +
     #scale_alpha_discrete(name = "Density", range = c(0.4, 1)) +
     scale_color_brewer(name = "Density", palette = "Greens") +
     geom_errorbar(aes(ymin=BCmean-BCse, ymax=BCmean+BCse), width=.1, position=pd) +
     ylab("Bray-Curtis dissimilarity") + xlab("Time (d)") +
     #facet_grid(rows = vars(Type), cols = vars(Diet)) +
     theme_classic() + theme(text = element_text(size=20), panel.grid.major = element_line(colour = "grey80"),
                             panel.margin = unit(.5,"lines"),
                             panel.border = element_rect(color = "black", fill = NA, size = .3))

# Spearman correlation
pR <- ggplot(dist.sum, aes(x=Timepoint, y=rmean, group=Density))
pR <- pR + geom_line(aes(linetype=Density), size=.6) + 
     geom_point(aes(shape=Density), size=2, position=pd) +
     expand_limits(y = 0) +
     #scale_alpha_discrete(name = "Density", range = c(0.4, 1)) +
     scale_color_brewer(name = "Density", palette = "Greens") +
     geom_errorbar(aes(ymin=rmean-rse, ymax=rmean+rse), width=.1, position=pd) +
     ylab(expression("Spearman "~rho)) + xlab("Time (d)") +
     #facet_grid(rows = vars(Type), cols = vars(Diet)) +
     theme_classic() + theme(text = element_text(size=20), panel.grid.major = element_line(colour = "grey80"),
                             panel.margin = unit(.5,"lines"),
                             panel.border = element_rect(color = "black", fill = NA, size = .3))

pWUF; pBC; pR
```

### 4.4. Saving figures  
```{r}
# Weighted UniFrac distance
png("./figures/Larv-sub_CM_gen_WUF.png", width = 10, height = 7, units = "in", res=200)
pWUF
dev.off()

# Bray-Curtis dissimilarity
png("./figures/Larv-sub_CM_gen_BC.png", width = 10, height = 7, units = "in", res=200)
pBC
dev.off()

# Spearman's correlation rho
png("./figures/Larv-sub_CM_gen_rho.png", width = 10, height = 7, units = "in", res=200)
pR
dev.off()
```



## 5. Principal Response Curves  
```{r}
# vegan::prc

# subset only substrate data
pseq.rel.sub <- subset_samples(pseqphy.r, Type == "substrate")
pseq.rel.sub <- prune_taxa(taxa_sums(otu_table(pseq.rel.sub))>0, pseq.rel.sub)
pseq.rel.sub.f <- microbiomeutilities::format_to_besthit(pseq.rel.sub) # need physeq object with phylogeny (tree)!
otu1 <- abundances(pseq.rel.sub.f)
meta1 <- meta(pseq.rel.sub.f)
tax1 <- tax_table(pseq.rel.sub.f)

# rename levels
class(meta1$Timepoint)
levels(meta1$Timepoint) # for CS only 1, 2, 3 (5, 10, 15)
levels(meta1$Timepoint)[2] <- "5"
levels(meta1$Timepoint)[3] <- "10"
levels(meta1$Timepoint)[4] <- "15"
levels(meta1$Density)
levels(meta1$Density)[2] <- "50"
levels(meta1$Density)[3] <- "100"
levels(meta1$Density)[4] <- "200"

# PRC
mod <- prc(t(otu1), treatment = meta1$Density, time = meta1$Timepoint)

# Model output
mod            # RDA
#summary(mod)   # PRC

# Visualisation and interpretation, see http://edild.github.io/prc1/ andhttp://edild.github.io/prc2/
#plot(mod)
# For better display, display only taxa with species score > 0.01 or < -0.01
## (option in Canoco 5: select by significant correlation, Vendrig et al. 2017)
sum_prc <- summary(mod)
head(sum_prc$sp)
pprc <- plot(mod, select = abs(sum_prc$sp) > 0.05, scaling = 3, xlab = "Day") # scaling=1 means sites scores are scaled by eigenvalues, but what is the actual function scaling?
# display top 15 most abundant taxa
##plot(mod, select=top_taxa(pseq.rel.sub, n=15), xlab = "Day")

# use "labels=" argument in plot() to match genus names to OTUs...

# to get variance explained per axis, divide eigenvalues by their sum
mod$CCA$eig/sum(mod$CCA$eig) # variance explained by RDA axes
mod$CCA$tot.chi/mod$tot.chi  # variance explained by treatment (Density)
mod$pCCA$tot.chi/mod$tot.chi # variance explained by time (Timepoint)

# Permutations should be done only within one timepoint (strata), and we only are interested in the first axis
aov1 <- anova(mod, strata = meta1$Timepoint, first=TRUE)
aov1
# Posthoc comparisons...
#posthoc <- TukeyHSD(aov1, which = meta1$Timepoint, conf.level=0.95) # not working
```

### 5.2. Save PRC plot  
```{r}
# not working yet...
png("./figures/PRC_CM_otu.png", width = 10, height = 7, units = "in", res=200)
pprc
dev.off()
```


## 6. RDA  

### 6.1. RDA using vegan::rda  
```{r}
# do RDA with factors Diet, Type, Density, Timepoint, or per diet separately.
#ps1.exp <- readRDS("./phyobjects/ps1.exp.rds")
#psrda <- prune_samples(sample_sums(pseq.rel) > 500, ps1.exp)
#print(psrda)
#relative abundances at OTU level
#psrda.r <- microbiome::transform(psrda, "compositional")
# if constraining for both diet and timepoint, we get all samples on the lines of the first 2 axes

# per diet separately, CM as example
# Pick relative abundances (compositional) and sample metadata 
otur <- abundances(pseq.rel)
metar <- meta(pseq.rel)

# rename factor levels
levels(metar$Timepoint) # for CS only 1, 2, 3 (5, 10, 15)
levels(metar$Timepoint)[2] <- "5"
levels(metar$Timepoint)[3] <- "10"
levels(metar$Timepoint)[4] <- "15"
levels(metar$Density)
levels(metar$Density)[2] <- "50"
levels(metar$Density)[3] <- "100"
levels(metar$Density)[4] <- "200"

#below code works, but I chose to use ordinate() function from phyloseq package, in order to use plot_ordination with more visualisation options

#rda(t(otur) ~ Timepoint *
#              (Type + Density) +
#              Condition(Timepoint),
#            data = metar)
# visualise
#plot(rda1, display = c("sp", "wa", "cn"), scaling = 3, type = "points")
# look for customizing plot using ggplot or options under plot.cca
# needs more work here...
```

### 6.2. RDA using phyloseq::ordinate  
```{r}
# RDA
rda1 <- ordinate(pseq.rel, method = "RDA", formula = ~ Timepoint * (Type + Density) + Condition(Timepoint))

# visualize
plot_ordination(pseq.rel, rda1, type = "samples", color = "Type", shape = "Density") +
  geom_text(aes(label = Timepoint), size = 4) +
  geom_hline(yintercept=0, linetype="dotted") +
  geom_vline(xintercept=0, linetype="dotted")

##########################
## NB use % explained variance from plot above in axis labels below! (do manually!!)
##########################

# extract as dataframe for customized display
prda1.df <- plot_ordination(pseq.rel, rda1, type = "samples", color = "Type", shape = "Density", justDF=T)
# rename levels
levels(prda1.df$Timepoint) # for CS only 1, 2, 3 (5, 10, 15)
levels(prda1.df$Timepoint)[2] <- "5"
levels(prda1.df$Timepoint)[3] <- "10"
levels(prda1.df$Timepoint)[4] <- "15"
levels(prda1.df$Density)
levels(prda1.df$Density)[2] <- "50"
levels(prda1.df$Density)[3] <- "100"
levels(prda1.df$Density)[4] <- "200"
# summarize RDA scores in means, SE and SD using ddply
prda1.sum <- ddply(prda1.df, ~Type+Density+Timepoint, summarise,
                   mRDA1=mean(RDA1), sdRDA1=sd(RDA1), seRDA1=se(RDA1),
                   mRDA2=mean(RDA2), sdRDA2=sd(RDA2), seRDA2=se(RDA2))
# sort by timepoint, necessary for geom_line in next plot
prda1.sum <- with(prda1.sum,prda1.sum[order(Density, Type, Timepoint),])

# customize display: means and SE errorbars
prda <- ggplot(prda1.sum, aes(x=mRDA1, y=mRDA2, colour=Type, alpha = Density,
                              group=interaction(Type,Density))) +
     geom_path(aes(linetype = "solid"), arrow = arrow(angle = 15, length = unit(0.1, "inches"),
                                                      ends = "last", type = "closed"), size=.6) + 
     scale_linetype(guide=F) +
     geom_text_repel(aes(label = Density), size = 4) +
     geom_point(aes(shape=Timepoint), size=2) +
     scale_alpha_discrete(name = "Density", range = c(0.4, 1)) +
     scale_color_manual(name = "Sample type", values = c("#1f78b4", "#33a02c")) +
     geom_errorbar(aes(ymin=mRDA2-seRDA2, ymax=mRDA2+seRDA2), width=.01) +
     geom_errorbarh(aes(xmin=mRDA1-seRDA1,xmax=mRDA1+seRDA1), height=.02) +
     xlab("RDA1 (11.8%)") + ylab("RDA2 (5.8%)") +
     geom_hline(yintercept=0, linetype="dotted") +
     geom_vline(xintercept=0, linetype="dotted") +
     theme(text = element_text(size=12),axis.text=element_text(size=12))
prda

# customize display: individual samples
prda1.df <- prda1.df[order(prda1.df$Density),]
prda2 <- ggplot(prda1.df, aes(x=RDA1, y=RDA2, colour=Type, alpha = Timepoint,
                              group=interaction(Type,Density,ContainerID))) +
     #geom_path(aes(linetype = "solid"), arrow = arrow(angle = 15, length = unit(0.1, "inches"),
     #                                                 ends = "last", type = "closed"), size=.6) + 
     #scale_linetype(guide=F) +
     geom_text_repel(aes(label = Density), size = 2.5) +
     geom_point(aes(shape=Density), size=2) +
     scale_alpha_discrete(name = "Day", range = c(0.4, 1)) +
     scale_color_manual(name = "Sample type", values = c("#1f78b4", "#33a02c")) +
     xlab("RDA1 (11.8%)") + ylab("RDA2 (5.8%)") +
     geom_hline(yintercept=0, linetype="dotted") +
     geom_vline(xintercept=0, linetype="dotted") +
     theme(text = element_text(size=12),axis.text=element_text(size=12))
prda2
```

### 6.3. Weighted UniFrac distance-based RDA (dbRDA/CAP), using phyloseq::ordinate  
```{r}
# distance-based RDA, weighted unifrac
cap1 <- ordinate(pseqphy.r, method = "CAP", formula = ~ Timepoint * (Type + Density) + Condition(Timepoint),
                 distance = "unifrac", weighted = T)
# visualize
plot_ordination(pseq.rel, cap1, type = "samples", color = "Type", shape = "Density") +
  geom_text(aes(label = Timepoint), size = 4) +
  geom_hline(yintercept=0, linetype="dotted") +
  geom_vline(xintercept=0, linetype="dotted")

##########################
## NB use % explained variance from plot above in axis labels below! (do manually!!)
##########################

# extract CAP as dataframe for customized display
pcap1.df <- plot_ordination(pseq.rel, cap1, type = "samples", color = "Type", shape = "Density", justDF=T)
# rename levels
levels(pcap1.df$Timepoint) # for CS only 1, 2, 3 (5, 10, 15)
levels(pcap1.df$Timepoint)[2] <- "5"
levels(pcap1.df$Timepoint)[3] <- "10"
levels(pcap1.df$Timepoint)[4] <- "15"
levels(pcap1.df$Density)
levels(pcap1.df$Density)[2] <- "50"
levels(pcap1.df$Density)[3] <- "100"
levels(pcap1.df$Density)[4] <- "200"
# summarize dbRDA scores in means, SE and SD using ddply
pcap1.sum <- ddply(pcap1.df, ~Type+Density+Timepoint, summarise,
                   mCAP1=mean(CAP1), sdCAP1=sd(CAP1), seCAP1=se(CAP1),
                   mCAP2=mean(CAP2), sdCAP2=sd(CAP2), seCAP2=se(CAP2))
# sort by timepoint, necessary for geom_line in next plot
pcap1.sum <- with(pcap1.sum, pcap1.sum[order(Density,Type,Timepoint),])

# customize display: means and SE errorbars
pcap <- ggplot(pcap1.sum, aes(x=mCAP1, y=mCAP2, colour=Type, alpha = Density,
                              group=interaction(Type,Density))) +
     geom_path(aes(linetype = "solid"), arrow = arrow(angle = 15, length = unit(0.1, "inches"),
                                                      ends = "last", type = "closed"), size=.6) + 
     scale_linetype(guide=F) +
     geom_text_repel(aes(label = Density), size = 4) +
     geom_point(aes(shape=Timepoint), size=2) +
     scale_alpha_discrete(name = "Density", range = c(0.4, 1)) +
     scale_color_manual(name = "Sample type", values = c("#1f78b4", "#33a02c")) +
     geom_errorbar(aes(ymin=mCAP2-seCAP2, ymax=mCAP2+seCAP2), width=.01) +
     geom_errorbarh(aes(xmin=mCAP1-seCAP1,xmax=mCAP1+seCAP1), height=.02) +
     xlab("CAP1 (9.1%)") + ylab("CAP2 (6.3%)") +
     geom_hline(yintercept=0, linetype="dotted") +
     geom_vline(xintercept=0, linetype="dotted") +
     theme(text = element_text(size=12),axis.text=element_text(size=12))
pcap

# customize display: individual samples
pcap1.df <- with(pcap1.df, pcap1.df[order(ContainerID,Timepoint),])
pcap2 <- ggplot(pcap1.df, aes(x=CAP1, y=CAP2, colour=Type, alpha = Timepoint,
                              group=interaction(Type,Density,ContainerID))) +
     #geom_path(aes(linetype = "solid"),arrow = arrow(angle = 15, length = unit(0.1, "inches"),
     #                                                ends = "last", type = "closed"), size=.6) + 
     #scale_linetype(guide=F) +
     geom_text_repel(aes(label = Density), size = 3) +
     geom_point(aes(shape=Density), size=2) +
     scale_alpha_discrete(name = "Day", range = c(0.3, 1)) +
     scale_color_manual(name = "Sample type", values = c("#1f78b4", "#33a02c")) +
     xlab("CAP1 (9.1%)") + ylab("CAP2 (6.3%)") + 
     geom_hline(yintercept=0, linetype="dotted") +
     geom_vline(xintercept=0, linetype="dotted") +
     theme(text = element_text(size=12),axis.text=element_text(size=12))
pcap2
```

### 6.4. Saving RDA and dbRDA plots  
```{r}
# RDA: errorbars
png("./figures/RDA_CM_errorbars.png", width = 10, height = 7, units = "in", res=200)
prda
dev.off()

# RDA: individual samples
png("./figures/RDA_CM.png", width = 10, height = 7, units = "in", res=200)
prda2
dev.off()

# WUF-dbRDA: errorbars
png("./figures/dbRDA_CM_errorbars.png", width = 10, height = 7, units = "in", res=200)
pcap
dev.off()

# WUF-dbRDA: individual samples
png("./figures/dbRDA_CM.png", width = 10, height = 7, units = "in", res=200)
pcap2
dev.off()
```

### 6.5. Accessing RDA output  
```{r}
# not much worked out yet...
# Access directly constrained weighted orthonormal species and site scores, constrained eigenvalues and margin sums.
pec <- rda1$CCA$v
sites <- rda1$CCA$u
eig <- rda1$CCA$eig
rsum <- rda1$rowsum
csum <- rda1$colsum
# and for pCCA...
```




