---
title: "BioNAR: Biological Network Analysis in R"
author:
- name: "Colin Mclean"
- name: "Anatoly Sorokin"
- name: "T. I. Simpson"
- name: "J. Douglas Armstrong"
- name: "Oksana Sorokina"
date: "Edited: October, 2022; Compiled: `r format(Sys.time(), '%B %d, %Y')`"
package: BioNAR
vignette: >
  %\VignetteIndexEntry{BioNAR: Biological Network Analysis in R}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
output:
  BiocStyle::html_document:
    number_sections: yes
    toc: yes
    toc_depth: 4
---

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

```{r setup, echo=FALSE}
library(knitr)
library(BioNAR)
library(ggplot2)
library(pander)
library(ggrepel)
library(randomcoloR)
```

# Introduction

Proteomic studies typically generate a massive list of proteins being identified
within a specific tissue, compartment or cell type, often accompanied by 
additional qualitative and/or quantitative information. Conversion of these data
into meaningful biological insight requires processing in several stages to 
identify possible structural and/or functional dependencies.

One of the most popular ways of representing proteomic data is a protein-protein
interaction network, which allows to study its topology and how it correlates 
with functional annotation mapped onto the network. 

Many existing packages support different steps of the network building and 
analysis process, but few packages combine network analysis methodology into a 
single coherent pipeline. 

We designed BioNAR to support a range of network analysis functionality, 
complementing existing R packages and filling the methodological gaps necessary 
to interrogate biomedical networks with respect to functional and disease 
domains. For that purpose, we do not implement network reconstruction directly 
(unless for synaptic networks), as other tools such as Cytoscape and Network 
Analyst do this already. Rathher, we provide a detailed topologically-based 
network analysis package, enabling the researcher to load networks generated 
from the lab’s own meta-data, thus making the tool as widely applicable and 
flexible as possible. We also provide a synaptic proteome network of our own for
validation.

# Overview of capabilities

The BioNAR’s pipeline starts with importing the graph of interest (typically 
built from nodes/proteins and edges/PPI interactions), and annotating its 
vertices with available metadata [annotate_vertex]. 

This is followed by the analysis of general network properties, such as 
estimating a network’s “scale-free” property. For this we used the R “PoweRlaw” 
package (version 0.50.0) (Gillespie, 2015) [FitDegree] and a network entropy 
analysis
(Teschendorff et al, 2014) [getEntopy].

The package allows estimation of the main network vertex centrality measures: 
degree, betweenness centrality, clustering coefficient, semilocal centrality, 
mean shortest path, page rank, and standard deviation of the shortest path. 
Values for centrality values measures can be added as vertex attributes 
[calcCentrality] or returned as an R matrix [getCentralityMatrix], 
depending on user's preferences. Any other vertex meta-data, which can be 
represented in matrix form, can also be stored as a vertex attribute.

To compare observed networks vertex centrality values against those of 
equivalently sized but randomised graphs, we support three varying randomisation
models including G(n,p) Erdos-Renyi model , Barabasi-Albert model, and new 
random graph from a given graph by randomly adding/removing edges 
[getRandomGraphCentrality].

Additionally, to allow comparison of networks with different structures, we 
implemented normalized modularity measure (Parter et al., 2007, Takemoto, 2012, 
Takemoto, 2013, Takemoto and Borjigin, 2011)[normModularity].

BioNAR then proceeds to analyse the network’s community structure, which can be 
performed via nine different clustering algorithms, simultaneously 
[calcAllClustering] or with a chosen algorithm  [calcClustering], community
membership being stored as a vertex attribute. In situations where the network 
is dense and clusters are large and barely tractable, reclustering can be 
applied [calcReclusterMatrix]. The obtained community structure can be
visualized with [layoutByCluster], and communiities further tested for 
robustness [getRobustness] by comparing against randomised networks. As a 
result, a consensus matrix can be estimated [makeConsensusMatrix], which is 
needed for the next step -identifying the "influential" or "bridging" proteins 
(Nepusz et al., 2008).

For this, we enabled a function for calculating the "bridgeness" 
[getBridgeness] metric, which takes into account the probability a vertex to 
belongs to different communities [getBridgeness], such that a vertex can be 
ranked under assumption the higher its community membership the more influence 
it has to the network topology and signaling (Han et al., 2004). "Bridgeness" 
can be plotted against any other centrality measure, e.g. semi-local centrality 
(plot is implemented), to enable useful indication of vertex (protein) 
importance within the network topology.

To provide a perspective of the molecular signature of multiple diseases (or 
biological functions) and how they might interact or overap at the network 
level, we implemented a disease-disease overlap analysis by measuring the mean 
shortest distance for each disease (⟨d⟩), using the shortest distance between 
each gene-disease association (GDA) to its next nearest GDA neighbor 
(Menche et al., 2015) [calcDiseasePairs], [runPermDisease] to be used for 
obtaining significance values. In the case example of the presynaptic network 
we found a set of neurological disorders to overlap with a high significance, 
e.g. AD-PD, SCH-BP, ASD-ID, and, indeed, their comorbidity was confirmed by the 
literature. Note that while developed for disease-disease correlation, the 
analysis can be performed using any in-house vertex meta-data, including 
biological function terms.

To study the distribution of the specific annotation(s) over a clustered graph 
(typically disease of biologial process/function), we enabled overrepresentation
analysis [clusterORA], which helps identify the network communities enriched for
specific function or disease, or any other annotation.

The case study illustrates the package functionality for the protein-protein 
interaction network for the presynaptic compartment of the synapse generated 
from Synaptic proteome database (Sorokina et al., 2021) with Synaptome.db 
package. The network has 1073 vertices and 6620 edges, step by step analysis is 
shown below.

# Build the network

BioNAR allows building a network from a data frame, where the rows correspond to
the edges of the graph; alternatively for our synaptic proteome exemple, a list 
of vertices (genes) is needed, for which the information will be retrieved from 
SynaptomeDB package.

## Build a network from a given data frame
The command listed below builds a graph from provided data frame, simplifies the
graph (removing multiple edges and loops) and return its MCC (maximum connected 
component)
```{r network_from_scratch}
file <- system.file("extdata", "PPI_Presynaptic.csv", package = "BioNAR")
tbl <- read.csv(file, sep="\t")
head(tbl)
gg <- buildNetwork(tbl)
summary(gg)

```

## Use a predifined network
Any predefined network stored as a graph file (e.g. .gml, .graphml) can be 
loaded for further analysis using Igraph's functionality.

```{r net_predefind}
file <- system.file("extdata", "PPI_Presynaptic.gml", package = "BioNAR")
gg1 <- igraph::read_graph(file,format="gml")
summary(gg1)
```

```{r cluster_predefind, include=FALSE}
file <- system.file("extdata", "PPI_cluster.gml", package = "BioNAR")
ggCluster <- igraph::read_graph(file,format="gml")
summary(ggCluster)
```

# Annotate the nodes with node attributes
As soon as the graph is loaded it can be annotated with any relevant 
annotations, such as protein names [annotateGeneNames], functionality 
[annotateGOont], disease associations [annotateTopOntoOVG], or any customized 
annotation set [annotate_vertex {BioNAR}]. We also provide two functional 
annotations for synaptic graphs based on published synaptic functional studies 
([annotateSCHanno], and [annotatePresynaptic].

## Gene name
Adding gene names to vertices.

```{r annotate_net}
gg<-annotateGeneNames(gg)
summary(gg)
head(V(gg))
head(V(gg)$GeneName)
```

Some of the functions downstream requires non-empty GeneNames, so we have to 
check that annotation assign values to all nodes:
```{r check_genenames_na}
any(is.na(V(gg)$GeneName))
```
The result of this command should be `r FALSE`.

```{r fix.GRPEL1, eval=any(is.na(V(gg)$GeneName))}
idx <- which(V(gg)$name == '80273')
V(gg)$GeneName[idx]<-'GRPEL1'
```


## Diseases

Adding diseases associations to genes linked to Human Disease Ontology (HDO) 
terms extracted from the package 
(topOnto.HDO.db)[https://github.com/hxin/topOnto.HDO.db].
```{r annotate_topOnto}
afile<-system.file("extdata", "flatfile_human_gene2HDO.csv", package = "BioNAR")
dis <- read.table(afile,sep="\t",skip=1,header=FALSE,strip.white=TRUE,quote="")
gg <- annotateTopOntoOVG(gg, dis)
summary(gg)

```

## Schizopherina related synaptic gene functional annotation.
Adding the annotation curated from an external file: Schizophrenia annotaion 
curatedcurated from Lips et al., (2012) doi:10.1038/mp.2011.117.

```{r annotate_Shanno}
sfile<-system.file("extdata", "SCH_flatfile.csv", package = "BioNAR")
shan<- read.table(sfile,sep="\t",skip=1,header=FALSE,strip.white=TRUE,quote="")
sgg<-annotateSCHanno(gg,shan)
summary(sgg)
```

## Presynaptic functional annotation
Adding the presynaptic genes functional annotation derived from 
Boyken at al. (2013) <doi:10.1016/j.neuron.2013.02.027>.

```{r annotate_Chua, eval=FALSE}
sfile<-system.file("extdata", "PresynAn.csv", package = "BioNAR")
pres <- read.csv(sfile,skip=1,header=FALSE,strip.white=TRUE,quote="")
sgg <- annotatePresynaptic(gg, pres)
summary(sgg)
```

## Functional annotation with Gene Ontology (GO)

GO annotation is specifically supported with the function  [annotateGOont]:

```{r annotate_go}

ggGO <- annotateGOont(gg)
```

```{r annotate_file_go}
#however, functionality from GO: BP, MF,CC can be added

sfile<-system.file("extdata", "flatfile.go.BP.csv", package = "BioNAR")
goBP <- read.table(sfile,sep="\t",skip=1,header=FALSE,strip.white=TRUE,quote="")
sgg <- annotateGoBP(gg, goBP)
summary(sgg)

sfile<-system.file("extdata", "flatfile.go.MF.csv", package = "BioNAR")
goMF <- read.table(sfile,sep="\t",skip=1,header=FALSE,strip.white=TRUE,quote="")
sgg <- annotateGoMF(gg, goMF)
summary(sgg)

sfile<-system.file("extdata", "flatfile.go.CC.csv", package = "BioNAR")
goCC <- read.table(sfile,sep="\t",skip=1,header=FALSE,strip.white=TRUE,quote="")
sgg <- annotateGoCC(gg, goCC)
summary(sgg)

```

# Estimate vertex centrality measures

## Estimate centrality measures with values added as vertex attributes. 

BioNAR supports centrality measures as following:
* DEG - degree, 
* BET - betweenness, 
* CC - clustering coefficient, 
* SL - semilocal centrality, 
* mnSP - mean shortest path, 
* PR - page rank, 
* sdSP - standard deviation of the shortest path.
These are saved as vertex atrtributes.

```{r graph_cent}
gg <- calcCentrality(gg)
summary(gg)
```

## Get vertex centralities as a matrix. 

Instead of saving entrality centrality values on the graph, e.g. to provide 
different names for the vertex centrality attributes, they can be obtained in a 
matrix form:

```{r matrix_cent}
mc <- getCentralityMatrix(gg)
head(mc)
```

## Get the centrality measures for random graph

Sometimes one needs to compare the graph properties of the the properties of an 
the observed network to randomised networks of a similar size. The BioNAR 
command below provides three ways of generating  randomization, randomised 
networks given an observed network including: G(n,p) Erdos-Renyi model, 
Barabasi-Albert model and new random graph from a given graph by 
randomly adding/removing edges.

```
{r}
ggrm <- getRandomGraphCentrality(sgg, type = c("cgnp"))
head(ggrm)
```

## Power law fit

To examine a network's underlying structure (i.e. not random), one can test a 
network's degree distribution for evidence of scale-free structure and compare 
this against randomised network models. For this we used the R 
“PoweRlaw” package (version 0.50.0) (Gillespie, 2015). For the case study, i.e. 
our presynaptic PPI network, we found evidence for disassortative mixing 
(Newman, 2002), i.e. a preference for high-degree genes to attach to low-degree 
gene(presynaptic: -0.16).

```{r powerLaw,fig.height=8,fig.width=8,dpi=56}
pFit <- fitDegree( as.vector(igraph::degree(graph=gg)),threads=1,Nsim=5,
                    plot=TRUE,WIDTH=2480, HEIGHT=2480)
```

## Get entropy rate

Evidence for scale-free structure can also be tested by performing a 
perturbation analysis of each of the network's vertices. In this analysis each 
protein is being perturbed through over-expression (red) and under-expression 
(green), with the global graph entropy rate (SR) after each proteins 
perturbation being plotted against the log of the proteins degree, as shown at 
the plot below. 
In our case study of the presynaptic PPI network we observe a bi-modal response,
between gene over-expression and degree, and opposing bi-phasic response 
relative to over/under-expression between global entropy rate and degree. This 
type of bi-modal, bi-phasic behaviour has been observed only in networks with 
scale-free or approximate scale-free topology (Teschendorff et al, 2014). 

```{r ent_rate,fig.height=8,fig.width=8,dpi=56}
ent <- getEntropyRate(gg)
ent
SRprime <- getEntropy(gg, maxSr = NULL)
head(SRprime)
plotEntropy(SRprime, subTIT = "Entropy", SRo = ent$SRo, maxSr = ent$maxSr)
```

## Get modularity. Normalised modularity.
Normalised modularity (Qm) allows the comparison of networks with varying 
structure. Qm based on the previous studies by Parter et al., 2007, Takemoto, 
2012, Takemoto, 2013, Takemoto and Borjigin, 2011, which was defined as:

$$Qm = \frac{Q_{real}-Q_{rand}}{Q_{max}-Q_{rand}}$$

Where $Q_{real}$ is the network modularity of a real-world signaling network 
and, $Q_{rand}$ is the average network modularity value obtained from 10,000 
randomized networks constructed from its real-world network. 
$Q_{max}$ was estimated as: $$Q_{max}=1 − \frac{1}{M}$$, where $M$ is the 
number of modules in the real network.

Randomized networks were generated from a real-world network using the 
edge-rewiring algorithm (Maslov and Sneppen, 2002).
```{r norm_mod}
nm<-normModularity(gg,alg='louvain')
nm
```

# Clustering
Clustering, or community detection, in networks has been well studied in the 
field of statistical physics with particular attention to methods developed for 
social science networks. The underlying assumption(s) of what makes a 
community in social science, translates remarkably well to what we think of as a
community (sub-complex, module or cluster) in PPI networks. The possible 
algorithms of choice implemented in BioNAR are:
* "lec"('Leading-Eigenvector, Newman, 2006), 
* "wt"(Walktrap, Pons & Latapy, 2006), 
* "fc"(Fast-Greedy Community' algorithm, Clauset et al., 2004), 
* "infomap" (InfoMAP, Rosvall et al., 2007; Rosvall et al., 2010), 
* "louvain" (Louvain, Blondel et al., 2008), 
* "sgG1", "sgG2", "sgG5"(SpinGlass, Reichardt & Bornholdt). 
For each algorithm of interest the community membership can be obtained with`
'calcMembership` command. 
All algorithm implementations, apart from Spectral were performed using the 
publicly available R package igraph (Csardi & Nepusz, 2006) (R version 3.4.2, 
igraph version 1.1.2). Parameters used in the fc, lec, sg, wt and lourvain 
algorithms were chosen as to maximise the measure Modularity 
(Newman & Girvan, 2004); infomap seeks the optimal community structure in the 
data by maximising the objective function called the Minimum Description 
Length (Rissanen, 1978; Grwald et al., 2005)

```{r cluster.mem}
# choose one algorithm from the list
alg = "louvain"
mem <- calcMembership(gg, alg)
pander(head(mem))
```

Due to internal random initialisation consecutive invocation of the same 
algorithm could produce slightly different community structures:
```{r cluster.mem2}
mem2 <- calcMembership(gg, alg)
idx<-match(mem$names,mem2$names)
idnx<-which(as.character(mem$membership)!=as.character(mem2$membership[idx]))
pander(head(cbind(mem[idnx,],mem2[idx[idnx],])))
```

To avoid inconsistency in downstream analysis we provide two additional 
functions `calcClustering` and `calcAllClustering` that use calcMembership to 
calculate community memberships and store them within the graph vertices 
attributes named after the algorithm. They also calculate modularity values and 
store them as graph vertex attributes named after the clustering algorithm. 
The difference between `calcClustering` and `calcAllClustering` is that 
`calcAllClustering`allows to calculate memberships for all clustering algorithms
simultaneously (may take time), and store them as graph vertices attributes, 
while `calcClustering`command will work for a specific algorithm. 

```{r cluster}
gg <- calcClustering(gg, alg)
summary(gg)
```

Comminity membership data could be obtained from the graph vertex attribute:

```{r get.attr}
mem.df<-data.frame(names=V(gg)$name,membership=factor(V(gg)$louvain))
```

To compare different clustering algorithms,a summary matrix can be calculated 
with the following properties:
1. maximum Modularity obtained (mod), 
2. number of detected communities (C), 
3. the number of communities with size (Cn1) equal to 1, 
4. the number of communities >= 100 (Cn100), 
5. the fraction of edges lying between communities (mu), 
6. the size of the smallest community (Min. C), 
7. the size of the largest community (Max. C), 
8. the average ( Mean C), median (Median C), 
9. first quartile (1st Qu. C), and 
10. third quartile (3rd Qu. C) of the community size. 

```{r calcAllClustering,eval=FALSE}
ggc <- calcAllClustering(gg)
```
```{r calcAllClustering.hid,eval=TRUE,include=FALSE}
ggc <- ggCluster
```
```{r clusterSummary,eval=TRUE}
m<-clusteringSummary(ggc,att=c('lec','wt','fc',
                                'infomap','louvain',
                                'sgG1','sgG2','sgG5'))
pander(m)
```

It is often useful to be able to visualize clusters of the graph. The simplest 
way to do this is to color each cluster uniquely and plot the graph:
```{r plot.color.graph,fig.height=8,fig.width=8,dpi=56}
palette <- distinctColorPalette(max(as.numeric(mem.df$membership)))
plot(gg,vertex.size=3,layout=layout_nicely,
        vertex.label=NA,
        vertex.color=palette[as.numeric(mem.df$membership)],
        edge.color='grey95')
legend('topright',legend=names(table(mem.df$membership)),
        col=palette,pch=19,ncol = 2)
```

On the plot we can see some distinctive clusters but most verices are 
indistinguishable within the central part of the plot. So we could layout 
graph clusterwise:
```{r plot.clusterwise.graph,fig.height=8,fig.width=8,dpi=56}
lay<-layoutByCluster(gg,mem.df,layout = layout_nicely)
plot(gg,vertex.size=3,layout=lay,
        vertex.label=NA,
        vertex.color=palette[as.numeric(mem.df$membership)],
        edge.color='grey95')
legend('topright',legend=names(table(mem.df$membership)),
        col=palette,pch=19,ncol = 2)
```

It is also possible to visualize the interaction between communities:
```{r ploc.cluster.communities,fig.height=8,fig.width=8,dpi=56}
idx<-match(V(gg)$name,mem.df$names)
cgg<-getCommunityGraph(gg,mem.df$membership[idx])
D0 = unname(degree(cgg))
plot(cgg, vertex.size=sqrt(V(cgg)$size), vertex.cex = 0.8,
vertex.color=round(log(D0))+1,layout=layout_with_kk,margin=0)
```

### Reclustering
Reclustering a clustered graph using the same, or different, clustering 
algorithm:
```{r recluster}
remem<-calcReclusterMatrix(gg,mem.df,alg,10)
head(remem)
```

And we can apply second order clustering layout:
```{r plot.recluster.layout,fig.height=8,fig.width=8,dpi=56}
lay<-layoutByRecluster(gg,remem,layout_nicely)
plot(gg,vertex.size=3,layout=lay,
        vertex.label=NA,
        vertex.color=palette[as.numeric(mem.df$membership)],
        edge.color='grey95')
legend('topright',legend=names(table(mem.df$membership)),
        col=palette,pch=19,ncol = 2)
```


## Consensus matrix
To assess the robustness of obtained clusters, a randomization study can be 
performed, which applies the same clustering algorithm to N perturbed networks. 
The clustering results are returned as a consensus matrix where each matrix 
elements is assigned the frequency with which a pair of nodes vertices is found 
in the same cluster.

Where 'alg' gives the name of the clustering algorithm, 'type' the sampling 
scheme (1 sample edges, and 2 sample verices) used, 'mask' the percentage of 
edges or vertices to mask, and 'reclust' whether reclustering should be 
performed on the community set found, 'Cnmin' minimum cluster size and 
'Cnmax' the maximum cluster size above which reclustering will be 
preformed (if reClust=TRUE). 
```{r cons_mat}
#Build consensus matrix for louvain clustering
conmat <- makeConsensusMatrix(gg, N=5,
                                alg = alg, type = 2, 
                                mask = 10,reclust = FALSE, 
                                Cnmax = 10)

```
For the sake of timing we use only five randomisation rounds, for the real 
analysis you should use at least 500.

##Consensus matrix value distribution

Consensus matrix values can be visualised in the following way:

```{r plot.conmat.ecdf,fig.height=8,fig.width=8,dpi=56}
steps <- 100
Fn  <- ecdf(conmat[lower.tri(conmat)])
X<-seq(0,1,length.out=steps+1)
cdf<-Fn(X)
dt<-data.frame(cons=X,cdf=cdf)
ggplot(dt,aes(x=cons,y=cdf))+geom_line()+
        theme(            
        axis.title.x=element_text(face="bold",size=rel(2.5)),
        axis.title.y=element_text(face="bold",size=rel(2.5)),
        legend.title=element_text(face="bold",size=rel(1.5)),
        legend.text=element_text(face="bold",size=rel(1.5)),
        legend.key=element_blank())+
    theme(panel.grid.major = element_line(colour="grey40",linewidth=0.2),
            panel.grid.minor = element_line(colour="grey40",linewidth=0.1),
            panel.background = element_rect(fill="white"),
            panel.border = element_rect(linetype="solid",fill=NA))
```


## Cluster robustness

Cluster robustness assesses the robustness of obtained clusters and can help 
evaluate the "goodness" of a chosen clustering algorithm.
```{r clcons}
clrob<-getRobustness(gg, alg = alg, conmat)
pander(clrob)
```


# Bridgeness 

Bridging proteins are known to interact with many neighbours simultaneously, 
organise function inside the     communities they belong to, but also 
affect/influence other communities in the network (Nepusz et al., 2008). 
Bridgeness can be estimated from the consensus clustering matrix estimated 
above and vertex degree to calculate the vertex’s community membership, i.e. 
the probability a specific vertex belongs to every community obtained by a given
clustering algorithm.

The Bridgeness measure lies between 0 - implying a vertex clearly belongs in a 
single community, and 1 - implying a vertex forms a 'global bridge' across every
community with the same strength. 

```{r get.bridge}
br<-getBridgeness(gg,alg = alg,conmat)
pander(head(br))
```

```{r calc.bridge}
gg<-calcBridgeness(gg,alg = alg,conmat)
vertex_attr_names(gg)
```

## Bridgeness plot

Semi-local centrality measure (Chen et al., 2011) also lies between 0 and 1 
indicating whether protein is important globally or locally. By plotting 
Bridgeness against semi-local centrality we can categorises the influence 
each protein found in our network has on the overall network structure:
* Region 1, proteins having a 'global' rather than 'local' influence in the 
network (also been called bottle-neck bridges, connector or kinless hubs 
(0<Sl<0.5; 0.5<Br<1). 
* Region 2, proteins having 'global' and 'local' influence (0.5<Sl<1, 0.5<Br<1).
* Region 3, proteins centred within the community they belong to, but also 
communicating with a few other specific communities (0<Sl<0.5; 0.1<Br<0.5). 
* Region 4, proteins with 'local' impact , primarily within one or two 
communities (local or party hubs, 0.5<Sl<1, 0<Br<0.5).
```{r plot.bridgeness,fig.height=8,fig.width=8,dpi=56}
g<-plotBridgeness(gg,alg = alg,
               VIPs=c('8495','22999','8927','8573',
                      '26059','8497','27445','8499'),
               Xatt='SL',
               Xlab = "Semilocal Centrality (SL)",
               Ylab = "Bridgeness (B)",
               bsize = 3,
               spsize =7,
               MainDivSize = 0.8,
               xmin = 0,
               xmax = 1,
               ymin = 0,
               ymax = 1,
               baseColor="royalblue2",
               SPColor="royalblue2")
g
```

#Interactive view of bridgeness plot

```{r plotly,fig.height=6,fig.width=6}
library(plotly)
g<-plotBridgeness(gg,alg = alg,
               VIPs=c('8495','22999','8927','8573',
                      '26059','8497','27445','8499'),
               Xatt='SL',
               Xlab = "Semilocal Centrality (SL)",
               Ylab = "Bridgeness (B)",
               bsize = 1,
               spsize =2,
               MainDivSize = 0.8,
               xmin = 0,
               xmax = 1,
               ymin = 0,
               ymax = 1,
               baseColor="royalblue2",
               SPColor="royalblue2")
ggplotly(g)
```

# Disease/annotation pairs

Given that Disease associated genes are connected within the graph, the common 
question is to check whether the networks for two different diseases are 
overlapping, which may indicate the common molecular mechanisms. Same is valid 
for any pair of annotations, e.g. one would ask if two different biological 
functions are related.

To address this question, we utilise the algorithm from Menche et al, which 
estimates the minimal shortest paths between two distinct annotations and 
compares this to the randomly annotated graph.

Below example shows the estimation of disease separation for the following 
diseases: DOID:10652 (Alzheimer's_disease),  (bipolar_disorder), 
DOID:12849 (autistic_disorder), DOID:1826 (epilepsy). Command 
`calcDiseasePairs` quickly estimates the two annotation separation on 
the graph and compares it with one randomly reannotated graph. This could be 
used for initial guess of the relationships between the annotations.

To assess the significance of the obtained separation values the command `
runPermDisease` should be used, where the user can specify the number of 
permutations. TExecuting this command, which will take time depending of the 
number of permutations, returns table with of p-values, adjusted p-values, 
q-values and Bonferroni test for each disease-disease pair.

```{r disPairs,warning=FALSE,message=FALSE}
p <- calcDiseasePairs(
    gg,
    name = "TopOnto_OVG_HDO_ID",
    diseases = c("DOID:10652","DOID:3312"),
    permute = "r"
)
pander(p$disease_separation)

r <- runPermDisease(
    gg,
    name = "TopOnto_OVG_HDO_ID",
    diseases = c("DOID:10652","DOID:3312"),
    Nperm = 100,
    alpha = c(0.05, 0.01, 0.001)
)

pander(r$Disease_overlap_sig)
```

## Cluster overrepresentation
To identify the clusters with overrepresented function or disease we introduced 
the function which calculates the overrepesentation (enrichment for specified 
annotation). Based on R package fgsea.
```{r ora,warning=FALSE,message=FALSE}
ora <- clusterORA(gg, alg, name = 'TopOnto_OVG_HDO_ID', vid = "name",
                  alpha = 0.1, col = COLLAPSE)
```

# Session Info
```{r sessionInfo, echo=FALSE, results='asis', class='text', warning=FALSE}
library(devtools)
si<-devtools::session_info()
cat('Platform\n\n')
pander::pander(si$platform)
cat('Packages\n\n')
knitr::kable(as.data.frame(si$packages)[,c('ondiskversion',
                                            'loadedversion','date',
                                            'source')],align = c('l','l'))
```