---
title: "multiWGCNA: the full workflow"
author: "Dario Tommasini"
date: "`r Sys.Date()`"
output: 
  BiocStyle::html_document:
    toc: true
vignette: >
  %\VignetteIndexEntry{General Workflow}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

# Introduction

The multiWGCNA R package is a WGCNA-based procedure designed for RNA-seq datasets with two biologically meaningful variables. We developed this package because we've found that the experimental design for network analysis can be ambiguous. For example, should I analyze my treatment and wildtype samples separately or together? We find that it is informative to perform all the possible design combinations, and subsequently integrate these results. For more information, please see Tommasini and Fogel. BMC Bioinformatics. 2023.

In this vignette, we will be showing how users can perform a full start-to-finish multiWGCNA analysis. We will be using the regional autism data from Voineagu et al. 2011 (https://www.nature.com/articles/nature10110). This dataset has two sample traits: 1) autism versus control, and 2) temporal cortex versus frontal cortex. 

# Install the multiWGCNA R package

```{r eval=FALSE}
if (!require("BiocManager", quietly = TRUE))
    install.packages("BiocManager")

BiocManager::install("multiWGCNA")
```

The development version of multiWGCNA can be installed from GitHub like this:

```{r eval=FALSE}
if (!require("devtools", quietly = TRUE))
    install.packages("devtools")
    
devtools::install_github("fogellab/multiWGCNA")
```

Load multiWGCNA library

```{r}
library(multiWGCNA)
```

# Load microarray data from human post-mortem brains

Since this is purely an example of how to run the entire analysis from start to finish, we are going to limit our analysis to 1500 randomly selected probes. 

Input data: 

* The expression data can be either a SummarizedExperiment object or a data.frame with genes as rows and samples as columns
* The sampleTable should be a data.frame with the first column named 'Sample' (note the capitalized 'S'). The second and third column names can be arbitrary, i.e. "disease" or "Genotype"


```{r}
# Download data from the ExperimentHub
library(ExperimentHub)
eh = ExperimentHub()

# Note: this requires the SummarizedExperiment package to be installed
eh_query = query(eh, c("multiWGCNAdata"))
autism_se = eh_query[["EH8219"]]

# Collect the metadata in the sampleTable
sampleTable = colData(autism_se)

# Randomly sample 1500 genes from the expression matrix
set.seed(1)
autism_se = autism_se[sample(rownames(autism_se), 1500),]

# Check the data
assays(autism_se)[[1]][1:5, 1:5]
sampleTable

# Define our conditions for trait 1 (disease) and 2 (brain region)
conditions1 = unique(sampleTable[,2])
conditions2 = unique(sampleTable[,3])
```

# Perform network construction, module eigengene calculation, module-trait correlation 

Network construction is usually the slowest step. This wrapper also finds the best trait association for each module and identifies outlier modules (i.e. modules driven by a single sample). 

Let's use power = 10 since Voineagu et al. 2011 used that for all their networks. They also constructed "unsigned" networks and a mergeCutHeight of 0.10 so that modules with similar expression are merged. Note that these parameter settings are meant to match Voineagu et al. 2011. For an example of more typical WGCNA settings, see the astrocyte vignette. 

```{r}
# Construct the combined networks and all the sub-networks (autism only, controls only, FC only, and TC only)
autism_networks = constructNetworks(autism_se, sampleTable, conditions1, conditions2,
                                  networkType = "unsigned", power = 10,
                                  minModuleSize = 40, maxBlockSize = 25000,
                                  reassignThreshold = 0, minKMEtoStay = 0.7,
                                  mergeCutHeight = 0.10, numericLabels = TRUE,
                                  pamRespectsDendro = FALSE, verbose=3,
                                  saveTOMs = TRUE)
```

# Compare modules by overlap across conditions

For calculating significance of overlap, we use the hypergeometric test (also known as the one-sided Fisher exact test). We'll save the results in a list. Then, let's take a look at the mutual best matches between autism modules and control modules. 

```{r, fig.height = 4, fig.width = 7}
# Save results to a list
results=list()
results$overlaps=iterate(autism_networks, overlapComparisons, plot=TRUE)

# Check the reciprocal best matches between the autism and control networks
head(results$overlaps$autism_vs_controls$bestMatches)
```

You can use the ModuleFlotPlot to visualize the module overlap across the various networks: 

```{r, fig.height=6, fig.width=8}
ModuleFlowPlot(autism_networks, # WGCNA object list
               comparisonList = results$overlaps, # overlap comparisons
               networks = c('combined', 'autism', 'controls', 'FC', 'TC'), 
               width = 0.3, # width of nodes
               height = 0.2, # height of nodes
               only.signif = TRUE, # only significant overlaps
               only.contiguous = TRUE, # only contiguous comparisons (controlled by order)
               scale.by.size = TRUE, # scale nodes by module size
               spacer = 10, # space between nodes
               label.y = 50, # adjust placement of the network labels
               col = c(autism = 'pink', FC = 'lightgreen', None = 'grey') # color palette
               ) 
```

Of course, this doesn't give you gene-level resolution. To do that, you can use the TOMFlowPlot to plot the recruitment of genes from one network analysis to another. See Figure 6 from Tommasini and Fogel, 2023 for an example. Note that you will need to set saveTOMs = TRUE in the constructNetworks function above. In this example, we will observe the movement of module 5 from the autism network across all five computed networks. Thank you to Xinye Li for generalizing the function to more than two networks!

```{r, fig.height=5, fig.width=8}
networks = c('combined', 'autism', 'controls', 'FC', 'TC')
toms = lapply(networks, function(x) {
  load(paste0(x, '-block.1.RData'))
  get("TOM")
})

tom.df = BuildTOMFlowDF(autism_networks, 
                        networks, 
                        toms, 
                        genes_to_label = topNGenes(autism_networks$autism, "autism_005"))

PlotMultiNodesTOMflow(tom.df, labels = networks)
```

# Perform differential module expression analysis 

This test for an association between the module eigengene (ME) and the two sample traits or their interaction. Therefore, the model is ME = trait1 + trait2 + trait1*trait2 and tests for a significant association to the traits using factorial ANOVA. These results can be stored in the diffModExp component of the results list. It can also perform PERMANOVA, which uses multivariate distances and can thus be applied to the module expression rather than just the first principal component (module eigengene). 

Module combined_004 seems to be the module most significantly associated with disease status using standard ANOVA (module combined_000 represents genes that were unassigned so disregard this module). Let's use the diffModuleExpression function to visually check this module for an association to autism status. 

Note: By setting plot = TRUE, the runDME function generates a PDF file called "combined_DME.pdf" in the current directory with these plots for all the modules. 

```{r, fig.height = 6, fig.width = 7}
# Run differential module expression analysis (DME) on combined networks
results$diffModExp = runDME(autism_networks[["combined"]], 
                            sampleTable, 
                            p.adjust="fdr", 
                            refCondition="Tissue", 
                            testCondition="Status") 
                            # plot=TRUE, 
                            # out="combined_DME.pdf")

# to run PERMANOVA
# library(vegan)
# results$diffModExp = runDME(autism_networks[["combined"]], p.adjust="fdr", refCondition="Tissue", 
#                          testCondition="Status", plot=TRUE, test="PERMANOVA", out="PERMANOVA_DME.pdf")

# Check adjusted p-values for the two sample traits
results$diffModExp

# You can check the expression of a specific module like this. Note that the values reported in the bottom panel title are p-values and not FDR-adjusted like in results$diffModExp
diffModuleExpression(autism_networks[["combined"]], 
                     geneList = topNGenes(autism_networks[["combined"]], "combined_004"), 
                     design = sampleTable,
                     test = "ANOVA",
                     plotTitle = "combined_004",
                     plot = TRUE)
```

# Perform the module preservation analysis

Determine if any modules in the autism data are not preserved in the healthy data (or vice versa). This is the slowest step as the calculation of permuted statistics takes a while. Typically, this can be parallelized using the enableWGCNAThreads function, but for this vignette we'll just do 10 permutations so one core should suffice.   

```{r, fig.height = 3, fig.width = 7}
# To enable multi-threading
# library(doParallel)
# library(WGCNA)
# nCores = 8
# registerDoParallel(cores = nCores)
# enableWGCNAThreads(nThreads = nCores)

# Calculate preservation statistics
results$preservation=iterate(autism_networks[conditions1], # this does autism vs control; change to "conditions2" to perform comparison between FC and TC
                             preservationComparisons, 
                             write=FALSE, 
                             plot=TRUE, 
                             nPermutations=10)
```

# Summarize interesting results from the analyses

These include differentially preserved trait-associated modules and differentially expressed modules. 

```{r}
# Print a summary of the results
summarizeResults(autism_networks, results)
```

# Print the session info

```{r}
sessionInfo()
```
