## ----setup, include = FALSE---------------------------------------------------
knitr::knit_hooks$set(optipng = knitr::hook_optipng)

## ----load-libs, message = FALSE,  warning = FALSE, results = FALSE------------
library(BulkSignalR)
library(igraph)
library(STexampleData)

## ----parallel, message=FALSE, warning=FALSE-----------------------------------
library(doParallel)
n.proc <- 1
cl <- makeCluster(n.proc)
registerDoParallel(cl)

# To add at the end of your script:
# stopCluster(cl)

## ----loading, eval=TRUE-------------------------------------------------------
data(sdc)
head(sdc)

## ----BSRDataModel, eval=TRUE,cache=FALSE--------------------------------------
bsrdm <- BSRDataModel(counts = sdc)
bsrdm

## ----learnParameters,eval=TRUE,warning=FALSE,fig.dim = c(7,3)-----------------
bsrdm <- learnParameters(bsrdm, quick=TRUE)
bsrdm

## ----BSRInference,eval=TRUE---------------------------------------------------

# We use a subset of the reference to speed up
# inference in the context of the vignette.
subset <- c("REACTOME_BASIGIN_INTERACTIONS",
"REACTOME_SYNDECAN_INTERACTIONS",
"REACTOME_ECM_PROTEOGLYCANS",
"REACTOME_CELL_JUNCTION_ORGANIZATION")

reactSubset <- BulkSignalR:::.SignalR$BulkSignalR_Reactome[
BulkSignalR:::.SignalR$BulkSignalR_Reactome$`Reactome name` %in% subset,]

resetPathways(dataframe = reactSubset,
              resourceName = "Reactome")

bsrinf <- BSRInference(bsrdm,
    min.cor = 0.3,
    reference="REACTOME")

LRinter.dataframe <- LRinter(bsrinf)

head(LRinter.dataframe[
    order(LRinter.dataframe$qval),
    c("L", "R", "LR.corr", "pw.name", "qval")])


## ----BSRInferenceTfile, eval=FALSE--------------------------------------------
# write.table(LRinter.dataframe[order(LRinter.dataframe$qval), ],
#     "./sdc_LR.tsv",
#     row.names = FALSE,
#     sep = "\t",
#     quote = FALSE
# )

## ----ReduceToPathway, eval=TRUE-----------------------------------------------
bsrinf.redP <- reduceToPathway(bsrinf)

## ----ReduceToBestPathway, eval=TRUE-------------------------------------------
bsrinf.redBP <- reduceToBestPathway(bsrinf)

## ----ReduceToLigand,eval=TRUE-------------------------------------------------
bsrinf.L <- reduceToLigand(bsrinf)
bsrinf.R <- reduceToReceptor(bsrinf)

## ----doubleReduction, eval=TRUE-----------------------------------------------
bsrinf.redP <- reduceToPathway(bsrinf)
bsrinf.redPBP <- reduceToBestPathway(bsrinf.redP)

## ----scoringLR,eval=TRUE,fig.dim = c(5,4)-------------------------------------
bsrsig.redBP <- BSRSignature(bsrinf.redBP, qval.thres=0.001)

scoresLR <- scoreLRGeneSignatures(bsrdm, bsrsig.redBP,
    name.by.pathway=FALSE
)

simpleHeatmap(scoresLR[1:20, ],
    hcl.palette="Cividis",
    pointsize=8)


## ----scoringPathway,eval=TRUE,fig.dim = c(7,3)--------------------------------

bsrsig.redPBP <- BSRSignature(bsrinf.redPBP, qval.thres=0.01)

scoresPathway <- scoreLRGeneSignatures(bsrdm, bsrsig.redPBP,
    name.by.pathway=TRUE
)

simpleHeatmap(scoresPathway,
    hcl.palette="Blue-Red 2",
    pointsize=8)

## ----heatmapMulti,eval=TRUE,fig.dim = c(7,10)---------------------------------
pathway1 <- pathways(bsrsig.redPBP)[1]
signatureHeatmaps(
    pathway = pathway1,
    bsrdm = bsrdm,
    heights = c(3,2,15),
    bsrsig = bsrsig.redPBP
)

## ----AlluvialPlot,eval=TRUE,fig.dim = c(8,3)----------------------------------
alluvialPlot(bsrinf,
    keywords = c("LAMC1"),
    type = "L",
    qval.thres = 0.01
)

## ----BubblePlot,eval=TRUE,fig.dim = c(8,4)------------------------------------

pathways <- LRinter(bsrinf)[1,c("pw.name")]
bubblePlotPathwaysLR(bsrinf,
    pathways = pathways,
    qval.thres = 0.001,
    color = "red",
    pointsize = 8
)

## ----Chordiagram,eval=TRUE,fig.dim = c(6,4.5)---------------------------------
chordDiagramLR(bsrinf,
    pw.id.filter = "R-HSA-210991",
    limit = 20,
    ligand="FYN", 
    receptor="SPN"
)

## ----network1, eval=TRUE------------------------------------------------------
# Generate a ligand-receptor network and export it in .graphML
# for Cytoscape or similar tools
gLR <- getLRNetwork(bsrinf.redBP, qval.thres = 1e-3)

# save to file
# write.graph(gLR,file="SDC-LR-network.graphml",format="graphml")

# As an alternative to Cytoscape, you can play with igraph package functions.
plot(gLR,
    edge.arrow.size = 0.1,
    vertex.label.color = "black",
    vertex.label.family = "Helvetica",
    vertex.label.cex = 0.1
)

## ----network2,  eval=TRUE-----------------------------------------------------
# You can apply other functions.


# Community detection
u.gLR <- as_undirected(gLR) # most algorithms work for undirected graphs only
comm <- cluster_edge_betweenness(u.gLR)
# plot(comm,u.gLR,
#     vertex.label.color="black",
#     vertex.label.family="Helvetica",
#     vertex.label.cex=0.1)

# Cohesive blocks
cb <- cohesive_blocks(u.gLR)
plot(cb, u.gLR,
    vertex.label.color = "black",
    vertex.label.family = "Helvetica",
    vertex.label.cex = 0.1,
    edge.color = "black"
)

## ----network3, eval=FALSE,warning=FALSE---------------------------------------
# # For the next steps, we just share the code below, but graph generation
# # functions are commented to lighten the vignette.
# 
# # Generate a ligand-receptor network complemented with intra-cellular,
# # receptor downstream pathways [computations are a bit longer here]
# #
# # You can save to a file for cystoscape or plot with igraph.
# 
# gLRintra <- getLRIntracellNetwork(bsrinf.redBP, qval.thres = 1e-3)
# 
# lay <- layout_with_kk(gLRintra)
# # plot(gLRintra,
# #     layout=lay,
# #     edge.arrow.size=0.1,
# #     vertex.label.color="black",
# #     vertex.label.family="Helvetica",
# #     vertex.label.cex=0.1)
# 
# # Reduce complexity by focusing on strongly targeted pathways
# pairs <- LRinter(bsrinf.redBP)
# top <- unique(pairs[pairs$pval <  1e-3, c("pw.id", "pw.name")])
# top
# gLRintra.res <- getLRIntracellNetwork(bsrinf.redBP,
#     qval.thres = 0.01,
#     restrict.pw = top$pw.id
# )
# lay <- layout_with_fr(gLRintra.res)
# 
# # plot(gLRintra.res,
# #     layout=lay,
# #     edge.arrow.size=0.1,
# #     vertex.label.color="black",
# #     vertex.label.family="Helvetica",
# #     vertex.label.cex=0.4)

## ----mouse,eval=TRUE,warning=FALSE--------------------------------------------
data(bodyMap.mouse)

ortholog.dict <- findOrthoGenes(
    from_organism = "mmusculus",
    from_values = rownames(bodyMap.mouse)
)

matrix.expression.human <- convertToHuman(
    counts = bodyMap.mouse,
    dictionary = ortholog.dict
)

bsrdm <- BSRDataModel(
    counts = matrix.expression.human,
    species = "mmusculus",
    conversion.dict = ortholog.dict
)

bsrdm <- learnParameters(bsrdm,quick=TRUE)

bsrinf <- BSRInference(bsrdm,reference="REACTOME")

bsrinf <- resetToInitialOrganism(bsrinf, conversion.dict = ortholog.dict)

# For example, if you want to explore L-R interactions
# you can proceed as shown above for a human dataset.

bsrinf.redBP <- reduceToBestPathway(bsrinf)
bsrsig.redBP <- BSRSignature(bsrinf.redBP, qval.thres=0.001)
scoresLR <- scoreLRGeneSignatures(bsrdm, bsrsig.redBP, name.by.pathway=FALSE)
head(LRinter(bsrinf.redBP))
#simpleHeatmap(scoresLR, column.names=TRUE,
#              pointsize=8)

## ----spatial1,eval=TRUE,message=FALSE-----------------------------------------
# load data =================================================

# We re-initialize the environment variable of Reactome
# to have all the pathways (we reduced it to a subset above to fasten
# example computations)
reactSubset <- getResource(resourceName = "Reactome",
cache = TRUE)

resetPathways(dataframe = reactSubset,
resourceName = "Reactome")

# Few steps of pre-process to subset a spatialExperiment object
# from STexampleData package ==================================

spe <- Visium_humanDLPFC()
set.seed(123)

speSubset <- spe[, colData(spe)$ground_truth%in%c("Layer1","Layer2")]

idx <- sample(ncol(speSubset), 10)
speSubset <- speSubset[, idx]

my.image.as.raster <- SpatialExperiment::imgRaster(speSubset, 
    sample_id = imgData(spe)$sample_id[1], image_id = "lowres")

colData(speSubset)$idSpatial <- paste(colData(speSubset)[[4]],
                colData(speSubset)[[5]],sep = "x")


annotation <- colData(speSubset)


## ----spatial2,eval=TRUE,warning=FALSE-----------------------------------------
# prepare data =================================================

bsrdm <- BSRDataModel(speSubset,
    min.count = 1,
    prop = 0.01,
    method = "TC",
    symbol.col = 2,
    x.col = 4,
    y.col = 5, 
    barcodeID.col = 1)

bsrdm <- learnParameters(bsrdm,
    quick = TRUE,
    min.positive = 2,
    verbose = TRUE)

bsrinf <- BSRInference(bsrdm, min.cor = -1,reference="REACTOME")

# spatial analysis ============================================

bsrinf.red <- reduceToBestPathway(bsrinf)
pairs.red <- LRinter(bsrinf.red)

thres <- 0.01
min.corr <- 0.01
pairs.red <- pairs.red[pairs.red$qval < thres & pairs.red$LR.corr > min.corr,]

head(pairs.red[
    order(pairs.red$qval),
    c("L", "R", "LR.corr", "pw.name", "qval")])

s.red  <- BSRSignature(bsrinf.red, qval.thres=thres)
scores.red <- scoreLRGeneSignatures(bsrdm,s.red)

head(scores.red)


## ----spatialPlot3,eval=TRUE,fig.dim = c(6,4.5)--------------------------------
# Visualization ============================================

# plot one specific interaction

# we have to follow the syntax with {} 
# to be compatible with the reduction functions
inter <- "{SLIT2} / {GPC1}"

# with raw tissue reference
spatialPlot(scores.red[inter, ], annotation, inter,
    ref.plot = TRUE, ref.plot.only = FALSE,
    image.raster = NULL, dot.size = 1,
    label.col = "ground_truth"
)

# or with synthetic image reference
spatialPlot(scores.red[inter, ], annotation, inter,
    ref.plot = TRUE, ref.plot.only = FALSE,
    image.raster = my.image.as.raster, dot.size = 1,
    label.col = "ground_truth"

)

## ----spatialPlot4,eval=TRUE,fig.dim = c(6,4.5)--------------------------------

separatedLRPlot(scores.red, "SLIT2", "GPC1", 
    ncounts(bsrdm), 
    annotation,
    label.col = "ground_truth")


## ----spatialPlot5,eval=TRUE---------------------------------------------------

# generate a visual index in a pdf file directly
spatialIndexPlot(scores.red, annotation,  
    label.col = "ground_truth",
    out.file="spatialIndexPlot")


## ----spatialPlot6,eval=TRUE,fig.dim = c(6,4.5)--------------------------------

# statistical association with tissue areas based on correlations
# For display purpose, we only use a subset here
assoc.bsr.corr <- spatialAssociation(scores.red[c(1:17), ],
annotation, label.col = "ground_truth",test = "Spearman")

head(assoc.bsr.corr)

spatialAssociationPlot(assoc.bsr.corr)


## ----inferCells,eval=FALSE,include=FALSE--------------------------------------
# 
# ## Additional functions
# 
# # This is not part of the main workflow for analyzing L-R interactions but
# # we offer convenience functions for inferring cell types. However
# # we recommend using other software packages specifically dedicated to this
# # purpose.
# 
# # Inferring cell types
# 
# 
# data(sdc, package = "BulkSignalR")
# bsrdm <- BSRDataModel(counts = sdc)
# bsrdm <- learnParameters(bsrdm)
# bsrinf <- BSRInference(bsrdm)
# 
# # Common TME cell type signatures
# data(immune.signatures, package = "BulkSignalR")
# unique(immune.signatures$signature)
# immune.signatures <- immune.signatures[immune.signatures$signature %in% c(
#     "B cells", "Dentritic cells", "Macrophages",
#     "NK cells", "T cells", "T regulatory cells"
# ), ]
# data("tme.signatures", package = "BulkSignalR")
# signatures <- rbind(immune.signatures,
# tme.signatures[tme.signatures$signature %in%
# c("Endothelial cells", "Fibroblasts"), ])
# tme.scores <- scoreSignatures(bsrdm, signatures)
# 
# # assign cell types to interactions
# lr2ct <- assignCellTypesToInteractions(bsrdm, bsrinf, tme.scores)
# head(lr2ct)
# 
# # cellular network computation and plot
# g.table <- cellularNetworkTable(lr2ct)
# 
# gCN <- cellularNetwork(g.table)
# 
# plot(gCN, edge.width = 5 * E(gCN)$score)
# 
# gSummary <- summarizedCellularNetwork(g.table)
# plot(gSummary, edge.width = 1 + 30 * E(gSummary)$score)
# 
# # relationship with partial EMT---
# # Should be tested HNSCC data instead of SDC!!
# 
# # find the ligands
# data(p.EMT, package = "BulkSignalR")
# gs <- p.EMT$gene
# triggers <- relateToGeneSet(bsrinf, gs)
# triggers <- triggers[triggers$n.genes > 1, ] # at least 2 target genes in the gs
# ligands.in.gs <- intersect(triggers$L, gs)
# triggers <- triggers[!(triggers$L %in% ligands.in.gs), ]
# ligands <- unique(triggers$L)
# 
# # link to cell types
# cf <- cellTypeFrequency(triggers, lr2ct, min.n.genes = 2)
# missing <- setdiff(rownames(tme.scores), names(cf$s))
# cf$s[missing] <- 0
# cf$t[missing] <- 0
# 
# op <- par(mar = c(2, 10, 2, 2))
# barplot(cf$s, col = "lightgray", horiz = T, las = 2)
# par(op)
# 
# # random selections based on random gene sets
# qval.thres <- 1e-3
# inter <- LRinter(bsrinf)
# tg <- tgGenes(bsrinf)
# tcor <- tgCorr(bsrinf)
# good <- inter$qval <= qval.thres
# inter <- inter[good, ]
# tg <- tg[good]
# tcor <- tcor[good]
# all.targets <- unique(unlist(tg))
# r.cf <- list()
# for (k in 1:100) { # should 1000 or more
#     r.gs <- sample(all.targets, length(intersect(gs, all.targets)))
#     r.triggers <- relateToGeneSet(bsrinf, r.gs, qval.thres = qval.thres)
#     r.triggers <- r.triggers[r.triggers$n.genes > 1, ]
#     r.ligands.in.gs <- intersect(r.triggers$L, r.gs)
#     r.triggers <- r.triggers[!(r.triggers$L %in% r.ligands.in.gs), ]
#     r <- cellTypeFrequency(r.triggers, lr2ct, min.n.genes = 2)
#     missing <- setdiff(rownames(tme.scores), names(r$s))
#     r$s[missing] <- 0
#     r$t[missing] <- 0
#     o <- order(names(r$t))
#     r$s <- r$s[o]
#     r$t <- r$t[o]
#     r.cf <- c(r.cf, list(r))
# }
# r.m.s <- foreach(i = seq_len(length(r.cf)), .combine = rbind) %do% {
#     r.cf[[i]]$s
# }
# 
# # plot results
# op <- par(mar = c(2, 10, 2, 2))
# boxplot(r.m.s, col = "lightgray", horizontal = T, las = 2)
# pts <- data.frame(x = as.numeric(cf$s[colnames(r.m.s)]), cty = colnames(r.m.s))
# stripchart(x ~ cty, data = pts, add = TRUE, pch = 19, col = "red")
# par(op)
# for (cty in rownames(tme.scores)) {
#     cat(cty, ": P=", sum(r.m.s[, cty] >= cf$s[cty]) / nrow(r.m.s),
#     "\n", sep = "")
# }

## ----session-info-------------------------------------------------------------
sessionInfo()

