---
title: "Using mascarade package"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Using mascarade package}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, fig.width = 7, fig.height=5)
```

This is a vignette describing usage of `mascarade` to generate masks for clusters
on 2D dimensional reduction plots like UMAP or t-SNE.

### Package installation

The most recent version of the package can be installed from GitHub:

```{r eval=FALSE}
remotes::install_github("alserglab/mascarade")
```

### Loading necessary libraries

```{r}
library(mascarade)
library(data.table)
library(ggplot2)
library(ggforce)
```

### Example run

Loading example data from PBMC 3K processed with Seurat (see below for more details).

```{r}
data("exampleMascarade")
```

UMAP coordinates:

```{r}
head(exampleMascarade$dims)
```

Cluster annotations:
```{r}
head(exampleMascarade$clusters)
```

Expression table for several genes:
```{r}
head(exampleMascarade$features)
```

Let's plot these data:

```{r}
data <- data.table(exampleMascarade$dims, 
                   cluster=exampleMascarade$clusters,
                   exampleMascarade$features)
ggplot(data, aes(x=UMAP_1, y=UMAP_2)) + 
    geom_point(aes(color=cluster)) + 
    coord_fixed() + 
    theme_classic()
                               
```

Now let's generate cluster masks:

```{r}
maskTable <- generateMask(dims=exampleMascarade$dims, 
                          clusters=exampleMascarade$clusters)
```

The `maskTable` is actually a table of cluster borders. 
A single cluster can have multiple connected parts, and
one a single part can contain multiple border lines (groups).

```{r}
head(maskTable)
```

Now we can use this table to draw the borders with `geom_path` (`group` column should be used as the group aesthetics):

```{r}
ggplot(data, aes(x=UMAP_1, y=UMAP_2)) + 
    geom_point(aes(color=cluster)) + 
    geom_path(data=maskTable, aes(group=group)) +
    coord_fixed() + 
    theme_classic()
```

Or we can color the borders instead of points:

```{r}
ggplot(data, aes(x=UMAP_1, y=UMAP_2)) + 
    geom_point(color="grey") + 
    geom_path(data=maskTable, aes(group=group, color=cluster), linewidth=1) +
    coord_fixed() + 
    theme_classic()
```

We can use `ggforce` package to make the borders touch instead of overlap:

```{r}
ggplot(data, aes(x=UMAP_1, y=UMAP_2)) + 
    geom_point(color="grey") + 
    ggforce::geom_shape(data=maskTable, aes(group=group, color=cluster),
                        linewidth=1, fill=NA, expand=unit(-1, "pt")) +
    coord_fixed() + 
    theme_classic()
```

In the presence of small clusters it can help to expand the borders a bit further
away from the points.

```{r}
maskTable <- generateMask(dims=exampleMascarade$dims, 
                          clusters=exampleMascarade$clusters,
                          expand=0.02)
ggplot(data, aes(x=UMAP_1, y=UMAP_2)) + 
    geom_point(color="grey") + 
    ggforce::geom_shape(data=maskTable, aes(group=group, color=cluster),
                        linewidth=1, fill=NA, expand=unit(-1, "pt")) +
    coord_fixed() + 
    theme_classic()
```

With the help of `ggforce`-based function `geom_mark_shape` we can also put the labels within the plot itself.


```{r}
myMask <- list(
    geom_mark_shape(data=maskTable, aes(group=cluster, color=cluster, label = cluster),
                    fill = NA,
                   linewidth=1, expand=unit(-1, "pt"),
                   con.cap=0, con.type = "straight",
                   label.fontsize = 10, label.buffer = unit(0, "cm"),
                   label.fontface = "plain",
                   label.minwidth = 0,
                   label.margin = margin(2, 2, 2, 2, "pt"),
                   label.lineheight = 0,
                   con.colour = "inherit",
                   show.legend = FALSE),
    # expanding to give a bit more space for labels
    scale_x_continuous(expand = expansion(mult = 0.1)),
    scale_y_continuous(expand = expansion(mult = 0.1))
)

ggplot(data, aes(x=UMAP_1, y=UMAP_2)) +
    geom_point(color="grey") +
    myMask +
    coord_fixed() +
    theme_classic()
```

The same can be achived with the `fancyMask()` helper function:

```{r}
ggplot(data, aes(x=UMAP_1, y=UMAP_2)) +
    geom_point(color="grey") +
    fancyMask(maskTable, ratio=1) +
    theme_classic()
```

Now we can easily show association between cell types and 
expression of particular genes, such as GNLY being a good marker
for NK cells in this dataset.

```{r}
ggplot(data, aes(x=UMAP_1, y=UMAP_2)) + 
    geom_point(aes(color=GNLY), size=0.5) +
    scale_color_gradient2(low = "#404040", high="red") + 
    fancyMask(maskTable, ratio=1) +
    theme_classic()
```

We can focus on a single cluster too:

```{r}
ggplot(data, aes(x=UMAP_1, y=UMAP_2)) + 
    geom_point(aes(color=GNLY), size=0.5) + 
    scale_color_gradient2(low = "#404040", high="red") + 
    geom_path(data=maskTable[cluster=="NK"], aes(group=group)) +
    coord_fixed() + 
    theme_classic()
```


### Working with Seurat

For this part of the vignette you need `Seurat`package. 

```{r message=FALSE}
library(Seurat)
```

Let's get the example PBMC3K dataset:
```{r}
pbmc3k <- readRDS(url("https://alserglab.wustl.edu/files/mascarade/examples/pbmc3k_seurat5.rds"))
pbmc3k <- NormalizeData(pbmc3k)
pbmc3k
```

The same object can be obtained using `SeuratData` package (can be installed with `remotes::install_github('satijalab/seurat-data')`):

```{r eval=FALSE, message=FALSE, warning=FALSE}
if (requireNamespace("SeuratData")) {
    if (!AvailableData()["pbmc3k", "Installed"]) {
        InstallData("pbmc3k")    
    }
    LoadData("pbmc3k")
    
    pbmc3k <- UpdateSeuratObject(pbmc3k.final)    
    pbmc3k
}
```

Generate masks using a helper function:

```{r}
maskTable <- generateMaskSeurat(pbmc3k)
```

We can use `fancyMask()` now:

```{r seurat-dimplot}
DimPlot(pbmc3k) + NoLegend() +
    fancyMask(maskTable, ratio=1)
```

For the `DimPlot`, the borders can be viewed as redundant and removed:

```{r seurat-dimplot-noborder}
DimPlot(pbmc3k) + NoLegend() +
    fancyMask(maskTable, linewidth = 0, ratio=1)
```

Let's plot an NK cell marker:

```{r seurat-gnly}
FeaturePlot(pbmc3k, "GNLY", cols=c("grey90", "red")) +
    fancyMask(maskTable, ratio=1)
```

Or multiple markers (skipping the labels to save space):

```{r message=FALSE, warning=FALSE}
featureList <- c("MS4A1", "GNLY", "CD3E", "CD14")
plots <- FeaturePlot(pbmc3k, features=featureList, cols=c("grey90", "red"), combine = FALSE)
plots <- lapply(plots, `+`, fancyMask(maskTable, ratio=1, linewidth=0.5, label=FALSE))
patchwork::wrap_plots(plots)
```


Works with t-SNE too:

```{r message=FALSE, warning=FALSE}
pbmc3k <- RunTSNE(pbmc3k)

maskTable <- generateMaskSeurat(pbmc3k, reduction = "tsne")

plots <- FeaturePlot(pbmc3k, 
                     features=featureList,
                     reduction = "tsne",
                     cols=c("grey90", "red"),
                     combine = FALSE)
plots <- lapply(plots, `+`, fancyMask(maskTable, ratio=1, linewidth=0.5, label=FALSE))

patchwork::wrap_plots(plots)
```

### Session info

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