---
output:
  html_document:
    toc: true
    self_contained: yes
    toc_float: true
    toc_depth: 4
    theme: flatly
    highlight: tango
version: 0.3.0
author: Tamas Ryszard Sztanka-Toth, Nikolaos Karaiskos
email: tamasryszard.sztanka-toth@mdc-berlin.de, nikolaos.karaiskos@mdc.berlin.de
license: GPL
---

```{r knitr_options, include=FALSE, cache=FALSE}
knitr::opts_chunk$set(
  autodep = TRUE,
  message = FALSE,
  warning = FALSE,
  comment = NA
)
```

```{r libraries, include = F, cache=F}
library(tidyverse)
library(yaml)
library(knitr)
library(magrittr)
library(kableExtra)
library(cowplot)

theme_set(theme_cowplot(18))

cpalette <- list('orange' = '#D55E00', 'blue' = '#0072B2', 'green' = '#009E73', 'black' = '#000000', 'yellow' = '#F0E442', 
				 'grey' = '#999999', 'light_orange' = "#E69F00", 'light_blue' = "#56B4E9")

readStarLog <- function(log_file){

		out = list()
		lines = readLines(log_file)
	
		out$input_reads = (lines[6] %>% strsplit('\t') %>% unlist)[2] %>% as.integer

		out$uniq_mapped_reads = (lines[9] %>% strsplit('\t') %>% unlist)[2] %>% as.integer

        out$multi_mapped_reads = (lines[24] %>% strsplit('\t') %>% unlist)[2] %>% as.integer

		out$avg_mapped_length = (lines[11] %>% strsplit('\t') %>% unlist)[2] %>% as.numeric

        out$unmapped_too_short = (lines[31] %>% strsplit('\t') %>% unlist)[2] %>% as.integer
		
        tibble(observation=names(out), value=unlist(unname(out)))
	}
```

```{r read_sample_information_tables, echo = F}
run_mode_settings <- bind_rows(snakemake@params$run_mode) %>%
    nest(umi_cutoff = c(umi_cutoff)) %>%
    bind_cols(tibble(run_mode = names(snakemake@params$run_mode))) %>%
    gather('variable_name', 'value', -run_mode) %>%
    spread(run_mode, value)

run_mode_names <- run_mode_settings[-1] %>% names
run_mode_n <- length(run_mode_names)
normal_run_mode_names <- run_mode_settings %>%
    gather('run_mode','val', -variable_name) %>%
    filter(variable_name == 'mesh_data') %>%
    unnest(val) %>%
    filter(val == 0) %$%
    run_mode

meshed_run_mode_names <- run_mode_settings %>%
    gather('run_mode','val', -variable_name) %>%
    filter(variable_name == 'mesh_data') %>%
    unnest(val) %>%
    filter(val == 1) %$%
    run_mode

sample_info <- bind_rows(snakemake@params$sample_info) %>%
    select(species, sequencing_date, investigator, experiment) %>%
    unique %>%
    gather('info_name', 'value') %>%
    add_row(info_name = 'project_id',
            value = snakemake@wildcards$project, .before=1)%>%
    add_row(info_name = 'sample_id',
            value = snakemake@wildcards$sample, .after=1)%>%
    add_row(info_name = 'puck_id',
            value = snakemake@wildcards$puck, .after=2)

cPalette = list('grey'= "#999999", 'light_orange'="#E69F00",
         'light_blue'="#56B4E9", 'green' = "#009E73",
         'yellow' = "#F0E442", 'blue'= "#0072B2", 'orange'="#D55E00",
         'pink'="#CC79A7")

clrs = c('umis'=cPalette$light_orange, 'genes' = cPalette$light_blue, 'reads'=cPalette$green,
         'pcr'=cPalette$pink)

summarised_clrs = c(clrs, 'black')
names(summarised_clrs) = c(paste0('median_', names(clrs)), 'n_beads')

nucl_clrs = c('A'='#F5C900',
              'C'='#F55D59',
              'T'='#3AA861',
              'G'='#7772F5',
              'N'='#999999')

# loading the dge summaries
dge_summary <- tibble(run_mode = run_mode_names,
                      obs_df = snakemake@input[paste0(run_mode, '.dge_summary')]) %>%
    unnest(obs_df) %>%
    mutate(dat = map(obs_df, ~ read_csv(.) %>%
        mutate(cell_bc = as.character(cell_bc)))) %>%
    unnest(dat) %>%
    select(-obs_df) %>%
    rename(pcr = reads_per_counts,
           umis = total_counts,
           genes = n_genes_by_counts,
           reads = n_reads) %>%
    group_by(run_mode) %>%
    filter(grepl('^[0-9]+|^[ACTGAN]+$', cell_bc))
```

## Overview {.tabset}

### Sample info

```{r show_sample_info, echo = F}
sample_info %>%
    kbl(col.names=NULL) %>%
    kable_classic_2(full_width=F, position='left')
```

### Run modes

This sample was processed using the following run modes, and run mode variables

```{r plot_run_modes, echo = F}
col_names_to_show <- colnames(run_mode_settings)[-1]

run_mode_settings %>%
    kbl(col.names = c('', col_names_to_show)) %>%
    kable_classic_2(full_width=F, position='left') %>%
    add_header_above(c(" ", "Run modes" = length(col_names_to_show))) %>%
    column_spec(1, border_right=T) %>%
    row_spec(0, bold=T)
```

```{r load_read_statistics, echo =F}
rRNA_stats <- read_table2(snakemake@input$ribo_log, col_names=c('observation', 'value')) %>%
    spread(observation, value) %>%
    mutate(mapped_to_rRNA = aligned_reads) %>%
    gather('observation', 'value') %>%
    filter(observation == 'mapped_to_rRNA') %>%
    mutate(value = ifelse(value == 'None', 0, value))
 
read_stats <- tibble(star_logs = snakemake@input$star_log,
                     reads_type_out = snakemake@input$reads_type_out) %>%
    mutate(trimmed = ifelse(grepl('polyA_adapter_trimmed', reads_type_out, fixed=TRUE),
                            'polyA_adapter_trimmed', 'untrimmed')) %>%
    mutate(star_log_dat = map(star_logs, ~ readStarLog(.)),
           reads_type_out_dat = map(reads_type_out, ~ read_table2(.,
                                                                  col_names = c('observation',
                                                                                'value')))) %>%
    mutate(rRNA_stats_dat = map(star_logs, ~ rbind(rRNA_stats))) %>%
    select(-star_logs, -reads_type_out) %>%
    gather('dat_type', 'dat', -trimmed) %>%
    select(-dat_type) %>%
    unnest(dat) %>%
    group_by(trimmed) %>%
    #rbind(rRNA_stats) %>%
    # convert to millions
    mutate(value = ifelse(observation != 'avg_mapped_length',
                          round(value / 1e6, 2), value)) %>%
    # add input_reads as a column per group
    spread(observation, value) %>%
    mutate(inp_reads = input_reads) %>%
    gather('observation', 'value', -trimmed, -inp_reads) %>%
    mutate(label = ifelse(observation %in% c('input_reads', 'avg_mapped_length'),
                          value, paste0(value, ' (', round(value/inp_reads*100, 1), '%)'))) %>%
    dplyr::select(observation, label) %>%
    spread(observation, label) %>%
    dplyr::rename(as.utr = UTR,
                  intronic = INTRONIC,
                  intergenic = INTERGENIC,
                  ambiguous = AMB,
                  as.cds = CODING) %>%
    # reorder columns
    dplyr::select(input_reads, uniq_mapped_reads, avg_mapped_length, multi_mapped_reads, 
                  unmapped_too_short, intergenic, intronic, as.cds, ambiguous, as.utr,
                  mapped_to_rRNA) %>%
    gather('metric', 'value', -trimmed) %>%
    spread(trimmed, value) %>%
    # change order
    slice(5, 10, 2,3,7,6,1,4,9,11,8)

map_types = colnames(select(read_stats, -metric))
```

### Mapping statistics

The sample was mapped using `r map_types` reads. The mapping statistics are shown here for each method:

```{r show_read_stats, echo = F}
col_names_to_show <- colnames(read_stats)[-1]
read_stats %>%
    kbl(col.names = c('', col_names_to_show)) %>%
    kable_classic_2(full_width=F, position='left') %>%
    add_header_above(c(" ", "Mapping mode" = length(col_names_to_show))) %>%
    column_spec(1, border_right=T) %>%
    row_spec(0, bold=T) %>%
    add_indent(c(3,4,5,6,7)) %>%
    footnote(general ='All values, except avg_mapped_length, shown in millions')
```

### Summarised metrics over beads

```{r calculate_summarised_metrics_over_beads, echo = F}
col_names_to_show <- colnames(run_mode_settings)[-1]

dge_summary %>%
    group_by(run_mode) %>%
    summarise(sum_reads = sum(reads, na.rm=T),
              median_reads = median(reads, na.rm=T),
              median_umis = median(umis, na.rm=T),
              median_pcr = median(pcr, na.rm=T),
              median_genes = median(genes, na.rm=T),
              n_beads = n()) %>%
    mutate(sum_reads = paste0(round(sum_reads / 1e6, 2), ' (1e6)')) %>%
    gather('obs', 'value', -run_mode) %>%
    spread(run_mode, value) %>%
    kbl(col.names = c('', col_names_to_show)) %>%
    kable_classic_2(full_width=F, position='left') %>%
    add_header_above(c(" ", "Run modes" = length(col_names_to_show))) %>%
    column_spec(1, border_right=T) %>%
    row_spec(0, bold=T)

```

## QC plots

Each of the QC plots we show on a per run mode basis, to see if there are any downstream differences based on the run mode variable settings.

### 'Knee'-plot {.tabset}

Below we plot a so called 'Knee-plot': on the y-axis is the Cummulative sum of reads, on the x-axis are the bead barcodes sorted by number of reads. For single-cell samples, this plot tells you roughly how many beads are in the sample.

```{r knee_plot, echo = F, fig.height=4, fig.width=7, results='asis'}
read_counts <- dge_summary %>%
    select(run_mode, cell_bc, reads) %>%
    mutate(reads_cumsum = cumsum(reads),
           ix = 1:n())

for (run_mode_in in unique(dge_summary$run_mode)){
    cat (paste0('\n\n #### ', run_mode_in, '\n\n'))

    pl_knee <- read_counts %>%
        filter(run_mode == run_mode_in) %>%
        ggplot(aes(ix, reads_cumsum)) +
            geom_line() +
            labs(x='Beads sorted by number of reads', y='Cummulative\nsum of reads')

    print(pl_knee)
    cat('\n\n')
}
```

### Umi-cutoff plots

```{r create_umi_cutoffs, echo = F, fig.width = 10, fig.height=5}
umi_cutoffs <- seq(10, 20000, 10)

dge_summary <- dge_summary %>%
    group_by(run_mode) %>%
    mutate(reads_cumsum = cumsum(reads)) %>%
    mutate(quartile = cut(reads_cumsum,
                          breaks = 4,
                          include.lowest= T,
                          labels = c('Q1', 'Q2', 'Q3', 'Q4'))) %>%
    select(-reads_cumsum)

summarise_dge_summary <- function(umi_cutoff){
    dge_summary %>%
        filter(umis > umi_cutoff) %>%
        summarise(median_reads = median(reads),
                  median_umis = median(umis),
                  median_genes = median(genes),
                  median_pcr = median(pcr),
                  n_beads = n())
}

umi_cutoff_data <- tibble(umi_cutoffs = umi_cutoffs) %>%
    mutate(dat = map(umi_cutoffs, ~ summarise_dge_summary(.))) %>%
    unnest(dat)

```


```{r plot_umi_cutoff_plot, echo = F, fig.height=7.5, fig.width=12}
metric_names <- list('umis' = 'UMIs', 'genes' = 'genes', 'pcr' = 'reads / UMIs',
                     'reads'='reads')
umi_cutoff_plot <- function(metric, y_log_transform = F, legend_pos='none'){
    y_label <- strsplit(metric, '_')
    y_label <- paste0(y_label[[1]][1], ' ', metric_names[[y_label[[1]][2]]])

    pl <- umi_cutoff_data %>%
        gather('obs', 'value', -umi_cutoffs, -run_mode) %>%
        filter(obs == metric) %>%
        ggplot(aes(umi_cutoffs, value, color=obs, linetype = run_mode)) +
            geom_line() +
            scale_color_manual(values=summarised_clrs) +
            scale_x_log10(breaks = c(1e1, 1e2, 1e3, 1e4)) +
            theme(strip.background=element_blank(), strip.text.x=element_blank(),
                  text = element_text(size=18, face = 'plain'), legend.position=legend_pos,
                  legend.title = element_blank(), legend.margin = margin(t=0.5, b=0.5,l=0.5,
                                                                         r=0.5, unit = 'cm'),
                  legend.spacing = unit(0, 'cm'), plot.margin = unit(c(1,1,1,1), "lines")) +
            labs(color='', linetype='', y=paste0(y_label, '\nper spatial unit'), x='minimum UMI') +
            guides(linetype = guide_legend(override.aes = list(size = 1), ncol=2),
                   color = guide_legend(override.aes = list(size = 2)))

    if (y_log_transform){
        pl <- pl + scale_y_log10() +
            annotation_logticks(sides='bl')
    } else {
        pl <- pl +
            annotation_logticks(sides='b')
    }

    return(pl)
}

pl1 <- umi_cutoff_plot('n_beads', y_log_transform = T)
pl2 <- umi_cutoff_plot('median_reads')
pl3 <- umi_cutoff_plot('median_genes')
pl4 <- umi_cutoff_plot('median_umis')
pl5 <- umi_cutoff_plot('median_pcr', legend_pos = 'right')

plt_legend <- get_legend(pl5)

plot_grid(pl1, pl2, pl3,
        pl4, pl5 + theme(legend.position='none'), plt_legend,
        align='vh', hjust=-1, labels="", nrow=3)
```

### Histogram of metrics over beads {.tabset}

Next we show mertics such as number of UMIs, genes, reads and pcr per physical spot. We further distinguish between each run mode, showing one histogram for each. 

```{r plot_n_reads_bead_hist, echo = F, fig.width=10, fig.height=4.5, dpi=300, results='asis'}
library(scales)
to_plot <- dge_summary %>%
    gather('obs', 'val', -cell_bc, -quartile, -run_mode)

min_difference <- to_plot %>% group_by(obs) %>%
    filter(!is.na(val)) %>%
    summarise(min_val = min(val,na.rm=T ),
              max_val = max(val,na.rm=T),
              difference = max_val - min_val) %>%
    summarise(min_difference = min(difference)) %$%
    min_difference

metric_plot <- function(run_mode_in, metric, legend_pos='none'){
    y_label <- metric_names[[metric]]
    to_plot <- to_plot %>%
        filter(obs == metric)

    pl <-  to_plot %>%
       filter(run_mode == run_mode_in) %>% 
       ggplot(aes(x = val, fill=obs)) +
            geom_histogram(bins=100) +
            scale_x_log10(breaks = c(1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6),
                          labels=trans_format('log10',math_format(10^.x))) +
            scale_fill_manual(values=clrs) +
            labs(fill='', x=paste0('# of ', y_label),
                 y=paste0('# of\n',
                          'spatial units')) +
            theme(legend.position = legend_pos, strip.background=element_rect(fill='white'),
                  text = element_text(size =18 ))

    if(min_difference > 1){
        pl <- pl + 
            annotation_logticks(sides='b')
    }

    return(pl)
}
for (run_mode in unique(dge_summary$run_mode)){
    cat (paste0('\n\n #### ', run_mode, '\n\n'))

    pl1 = metric_plot(run_mode, 'reads')
    pl2 = metric_plot(run_mode, 'pcr')
    pl3 = metric_plot(run_mode, 'genes')
    pl4 = metric_plot(run_mode, 'umis')

    print(plot_grid(pl1, pl2, pl3,
            pl4, align='vh', hjust=-1, labels="", nrow=2))

    cat('\n\n')
}
```

### Nucleotide distribution per beads {.tabset}

Next we bin the data based on reads into quartile. For each run\_mode the data is divided into 4 beads, by reads. This means, that the first bin will contain beads which account 25% of the reads, the second will contain beads which account for the second 25% of reads and so on. 

For each run mode we plot the nucleotide distribution per quartile.

**You can pick the run\_mode to be shown from the dropdown list**

**Only not-meshed run\_mode(s) are shown**

```{r plot_nucl_freq, results='asis', fig.width=10, fig.height = 4.5, echo=F, dpi=300}
plot_nucl_freq <- function(dge_s){
    cell_bc_len <- nchar((dge_s %$% cell_bc)[1])

    nucls <- dge_s %$%
        cell_bc %>% strsplit("")

    nucls <- dge_s %>%
        select(cell_bc, quartile, run_mode) %>%
        bind_cols(tibble(nucl=nucls)) %>%
        unnest(nucl) %>%
        # group by run_mode and cell_bc, so each nt is on the correct pos
        group_by(run_mode, cell_bc) %>%
        mutate(pos = paste0('pos_', 100+1:n())) %>%
        group_by(run_mode, pos, nucl, quartile) %>%
        summarise(nucl_count = n()) %>%
        ungroup() %>%
        tidyr::complete(run_mode, pos, nucl, quartile, fill=list(nucl_count=0))

    lbl_df <- dge_s %>%
        ungroup() %>%
        group_by(quartile) %>%
        summarise(lbl = n()) %>%
        mutate(lbl = paste0(quartile, ' (n=', lbl, ')'))

    lbls <- lbl_df$lbl
    names(lbls) <- lbl_df$quartile

    nucls %>%
        ggplot(aes(pos, nucl_count, fill = nucl)) +
            geom_bar(stat='identity', position='dodge') +
            scale_fill_manual(values=nucl_clrs) +
            scale_x_discrete(labels=seq(1, cell_bc_len, 1)) +
            facet_wrap(~quartile, ncol=2, scales='free_y',
                       labeller=as_labeller(lbls)) +
            labs(x='nucleotide position in the barcode',
                 y='nucleotide count')+
            theme(text = element_text(size =18 ))
}

for (run_mode_in in unique(normal_run_mode_names)){
    cat (paste0('\n\n #### ', run_mode_in, '\n\n'))
    dge_summary %>%
        filter(run_mode == run_mode_in) %>%
        plot_nucl_freq() %>%
        print()
}
```

### Shannon entropy and string compression {.tabset}

```{r plot_shannon, echo = F, fig.height=5, fig.width=10, results='asis', dpi=300}
plot_shannon_scompression <- function(run_mode_in){
    dat <- dge_summary %>%
        filter(run_mode == run_mode_in) %>%
        select(cell_bc, run_mode, ends_with('compression') | ends_with('entropy')) %>%
        gather('observation', 'value', -cell_bc, -run_mode) %>%
        # replace first _ with |, so we can separate later
        mutate(observation = str_replace(observation, '_', ' '),
               observation = str_replace(observation, '\\s', '|'),
               observation = str_replace(observation, ' ', '_')) %>%
        separate(observation, into = c('type', 'observation'), sep = '\\|')

    pl1 <- dat %>%
        filter(observation == 'entropy') %>%
        ggplot(aes(value, fill = type)) +
            geom_histogram(bins=30, color='black', position='dodge') +
            scale_fill_manual(values=c(cpalette$grey, cpalette$orange),labels=c('theoretical', 'observed')) +
            labs(fill='', y='# of barcodes', x='Shannon entropy of barcodes') +
            theme(legend.position = c(0.1, 0.8), text = element_text(size=18, face='plain'))

    pl2 <- dat %>%
        filter(observation == 'compression') %>%
        ggplot(aes(value, fill = type)) +
            geom_histogram(bins=30, color='black', position='dodge') +
            scale_fill_manual(values=c(cpalette$grey, cpalette$orange)) +
            scale_x_continuous(limits=c(0, NA)) +
            labs(fill='', y='# of barcodes', x='Length of barcodes after compression') +
            theme(text = element_text(size=18, face='plain'), legend.position='none')

    plt_legend <- get_legend(pl2)

    plot_grid(pl1, pl2,
              align='vh', hjust=-1, labels="", nrow=2)

}

for (run_mode in unique(dge_summary$run_mode)){
    cat (paste0('\n\n #### ', run_mode, '\n\n'))

    print(plot_shannon_scompression(run_mode))
}
```

```{r prepare_spatial, echo =F}
# barcode file attached at the python level
is_spatial <- snakemake@params$is_spatial
```

```{r spatial_header, eval=is_spatial, echo=F, results='asis'}
cat('## Spatial QC {.tabset}\n\n')
```

```{r prepare_spatial_data, eval=is_spatial, echo =F}
run_mode_info <- dge_summary %>%
    select(run_mode) %>%
    summarise(n_cells=n()) %>%
    mutate(def_plot_bead_size = ifelse(n_cells > 5000, 0.4, 0.75)) %>%
    mutate(def_plot_bead_size = ifelse(n_cells > 10000, 0.1, def_plot_bead_size)) %>%
    mutate(def_plot_bead_size = ifelse(n_cells > 25000, 0.05, def_plot_bead_size))

plot_bead_size <- run_mode_settings %>%
    filter(variable_name %in% c('mesh_data', 'mesh_spot_diameter_um')) %>%
    gather('run_mode', 'variable_value', -variable_name) %>%
    unnest(variable_value) %>%
    add_row(variable_name = 'spot_diameter_um', run_mode = run_mode_names,
            variable_value = snakemake@params$puck_variables$spot_diameter_um) %>%
    spread(variable_name, variable_value) %>%
    inner_join(run_mode_info, by='run_mode') %>%
    mutate(mesh_data = as.logical(mesh_data)) %>%
    group_by(run_mode) %>%
    mutate(plot_bead_size = min(ifelse(mesh_data, mesh_spot_diameter_um / 40,
                              spot_diameter_um / 40), def_plot_bead_size)) %>%
    select(run_mode, plot_bead_size)

x_limits <- dge_summary$x_pos %>% {c(min(.), max(.))}
y_limits <- dge_summary$y_pos %>% {c(min(.), max(.))}


ratio <- (x_limits[2] - x_limits[1] ) / (y_limits[2] - y_limits[1])

puck_width_um <- snakemake@params$puck_variables$width_um
scale_factor <- ifelse(puck_width_um < 3000, 2, 3)
mm_dist <- max(10^scale_factor, round(puck_width_um/3, digits =-scale_factor))
mm_diff <- mm_dist / 1000

x_mm_breaks <- seq(0, puck_width_um, mm_dist)
x_mm_breaks <- paste0(x_mm_breaks * mm_diff / mm_dist, 'mm')
y_mm_breaks <- seq(0, puck_width_um / ratio, mm_dist)
y_mm_breaks <- paste0(y_mm_breaks * mm_diff / mm_dist, 'mm')

px_to_um <- (x_limits[2] - x_limits[1]) / snakemake@params$puck_variables$width_um

x_breaks <- seq(x_limits[1], x_limits[2], px_to_um * mm_dist)
y_breaks <- seq(y_limits[1], y_limits[2], px_to_um * mm_dist)

plot_spatial_qc <- function(variable, dat_in, plot_bead_size=0.1, ttl='', cut_dist=T, min_value=0, is_hexagonal=F){
    spatial_qc_dat <- dat_in %>%
        mutate(qnt = quantile(val, 0.9, na.rm=T)) %>%
        arrange(val)

    if(cut_dist){
    spatial_qc_dat <- spatial_qc_dat %>%
        mutate(val = ifelse(val > qnt, qnt, val))
    }

    limits <- c(min_value, quantile(spatial_qc_dat$val, 0.91, na.rm=T))

    if(is_hexagonal){
        pl <- spatial_qc_dat %>%
            ggplot(aes(x_pos, y_pos, fill = val, group=1)) +
                geom_hex(stat='identity', color='gray95') +
                guides(fill = guide_colorbar(barheight = 10)) + 
                labs(fill=ttl, x='', y='')
        if(cut_dist){
            pl <- pl +
                scale_fill_viridis_c(option =  "magma", limits = limits)
        } else {
            pl <- pl + 
                scale_fill_viridis_c(option =  "magma") 
        }
    } else{
        pl <- spatial_qc_dat %>%
            ggplot(aes(x_pos, y_pos, color = val)) +
                geom_point(size=plot_bead_size) + 
                guides(color = guide_colorbar(barheight = 10)) + 
                labs(color=ttl, x='', y='')
        if(cut_dist){
            pl <- pl +
                scale_color_viridis_c(option =  "magma", limits = limits)
        } else {
            pl <- pl + 
                scale_color_viridis_c(option =  "magma") 
        }
    }

    pl <- pl + 
        scale_x_continuous(labels = x_mm_breaks, breaks = x_breaks, limits=x_limits) +
        scale_y_continuous(labels = y_mm_breaks, breaks = y_breaks, limits=y_limits) +
        coord_fixed()+
        theme(panel.background = element_rect(fill = 'gray95'), 
             legend.spacing = unit(0.1, 'cm'),
            axis.line = element_line(color = 'black'),
            text = element_text(color='black', size=18))

    return(pl)
}

qc_vars <- c('n_joined', 'reads', 'genes', 'umis', 'pcr',
               'pct_counts_mt', 'exact_entropy',
               'exact_compression')

qc_var_info <- dge_summary %>%
    ungroup() %>%
    select(-cell_bc, -x_pos, -y_pos, -total_counts_mt, -run_mode,
           -theoretical_entropy, -theoretical_compression, -quartile) %>%
    unique() %>%
    colnames() %>%
    tibble(qc_vars = .) %>%
    inner_join(tibble(qc_vars = qc_vars,
               ttl = c('# beads joined\nper spatial unit',
                       '# of reads\nper spatial unit',
                       '# of genes\nper spatial unit',
                       '# of UMIs\nper spatial unit',
                       'reads / UMIs\nper spatial unit',
                       '% mt counts\nper spatial unit',
                       'Shannon\nentropy\nper spatial unit',
                       'barcode length\nafter\ncompression\nper spatial unit'),
               cut_dist = c(F, T, T, T, T, T, F, F),
               min_value = c(0, 0, 0, 0, 1, 0, 0, 0)),
               by='qc_vars') %>%
    mutate(qc_vars = factor(qc_vars, levels= qc_vars))
```


```{r plot_per_run_mode, echo =F, results='asis', fig.width=7, fig.height=6, eval=is_spatial, dpi=300}
for (run_mode_name in run_mode_names){
    cat(paste0('\n\n### ', run_mode_name, '\n\n'))

    for (qc_var in qc_var_info$qc_vars){
        pbs = filter(plot_bead_size, run_mode == run_mode_name)$plot_bead_size
        dat_in = dge_summary %>%
            filter(run_mode == run_mode_name) %>%
            ungroup() %>%
            select(x_pos, y_pos, matches(qc_var)) %>%
            rename(val = qc_var) %>%
            filter(!is.na(val))

        if (qc_var %in% colnames(dge_summary) & nrow(dat_in) > 0){
            qc_var_info %>%
                filter(qc_vars == qc_var) %>%
                {
                    plot_spatial_qc(
                       qc_var,
                       dat_in,
                       plot_bead_size = pbs,
                       ttl = .$ttl,
                       cut_dist = .$cut_dist,
                       min_value = .$min_value,
                       is_hexagonal=snakemake@params$run_modes[[run_mode_name]]$mesh_type == 'hexagon')
                } %>%
                print()
        }

    }
}
```

