Prepare analysis workflow

Set filepaths and parameters

set.seed(42)
knitr::opts_knit$set(root.dir = rprojroot::find_rstudio_root_file())
options(
  readr.show_progress = FALSE,
  digits = 2
)

Load packages

suppressPackageStartupMessages({
  library(scater)
  library(scran)
  library(tidyverse)
  library(DESeq2)
  library(ashr)
  library(EnhancedVolcano)
  library(BiocParallel)
  library(hypeR)
  library(zinbwave)
  theme_set(theme_bw())
})

Define file paths

data_dir <- "./data"
figures_dir <- file.path("./figures")
get_counts_stats <- function(sce10x_fap, cluster_to_remove) {
  gene_counts_by_cluster <-
    t(assay(sce10x_fap)) %>%
    as.matrix() %>%
    as_tibble() %>%
    group_by(cluster = colData(sce10x_fap)$clusters_condition) %>%
    summarise_all(list(~ mean(.)))

  umi_counts_max<-
    gene_counts_by_cluster[, -1] %>%
    summarize_all(list(~ max(.))) %>%
    mutate(dummy = "dummy") %>%
    pivot_longer(-dummy, names_to = "gene_name", values_to = "max_expr") %>%
    select(-dummy)

  stats <-
    perFeatureQCMetrics(sce10x_fap,
      exprs_values = c("counts"),
      flatten = TRUE
    ) %>%
    as_tibble() %>%
    bind_cols(., rowData(sce10x_fap) %>%
      as_tibble()) %>%
    bind_cols(., umi_counts_max)

  return(stats)
}

get_lfc <- function(contrast, name, dds) {
  lfcShrink(dds,
    contrast = contrast,
    type = "ashr",
    svalue = T
  ) %>%
    as_tibble() %>%
    dplyr::select(-baseMean) %>%
    mutate(svalue = abs(svalue)) %>%
    set_names(paste(c("lfc", "lfc_se", "svalue"), name, sep = "_"))
}

plot_expression <- function(gene) {
  plotExpression(sce10x_fap,
    features = gene,
    x = "sample",
    exprs_values = "logcounts",
    colour_by = "condition",
    point_size = 1
  ) +
    facet_wrap(~ colData(sce10x_fap)$clusters, ncol = 1)
}

plot_volcano <- function(var_name, lfc_thresh, svalue_thresh, lfc, suffix, label=NULL) {
 p <- EnhancedVolcano(lfc,
    lab =lfc %>% pull(gene_id),
    x = paste0("lfc_", var_name),
    selectLab = label,
    y = paste0("svalue_", var_name),
    xlab = bquote(~ italic(Moderated) ~ Log[2] ~ FC),
    ylab = bquote(~ -Log[10] ~ italic(svalue)),
    col = c("grey30", "forestgreen", "red2", "royalblue"),
    pCutoff = svalue_thresh,
    FCcutoff = lfc_thresh,
    legendLabels = c(
      "NS",
      expression(Log[2] ~ FC),
      "s-value",
      expression(s - value ~ and ~ log[2] ~ FC)
    )
  )
  
  ggsave(file.path(figures_dir, paste0("volcano_sc", var_name,"_effect_", suffix, ".pdf")), p)
  return(p)
}

Load data

sce10x <-
  readRDS(file.path(
    data_dir,
    "preprocessed",
    "sce10x_filtered_final.rds"
  ))
sce10x_fap <- sce10x[, colData(sce10x)$celltype == "fap"]
rm(sce10x)
table(colData(sce10x_fap)$clusters, colData(sce10x_fap)$sample)
       
        yng1 yng2 yng3 aged1 aged2 aged3 aged4
  fap_1  295  284  389  1630  1585  1134   833
  fap_2  203  106  248   390   424   434   194

Discard low counts genes

n_exprs_genes <-
  nexprs(sce10x_fap,
    detection_limit = 5,
    byrow = TRUE
  )
keep <- n_exprs_genes >= 10
table(keep)
keep
FALSE  TRUE 
29144  4330 
sce10x_fap <- sce10x_fap[keep, ]
batch_genes_remove <- c("Chad", "Cxcl13", "Spp1", "Cilp2", "Kcnq5", "Tnc", "Krtdap")
map(batch_genes_remove, plot_expression)
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

[[7]]

sce10x_fap <- sce10x_fap[!(rownames(sce10x_fap) %in% batch_genes_remove), ]

Discard low cluster mean expression genes

stats <- get_counts_stats(sce10x_fap)
stats
max_thresh <- .3
stats %>%
  count(max_expr > max_thresh)
ggplot(stats) +
  geom_histogram(aes(max_expr), bins = 100) +
  scale_x_log10() +
  facet_wrap(~top_hvg_fap) +
  geom_vline(xintercept = max_thresh)

genes_to_plot <-
  stats %>%
  filter(max_expr <= max_thresh) %>%
  arrange(-max_expr)%>%
  pull(gene_name) 
map(genes_to_plot[1:5], plot_expression)
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

genes_keep <-
  stats %>%
  filter(max_expr > max_thresh) %>%
  pull(gene_name)
length(genes_keep)
[1] 4133
sce10x_fap <- sce10x_fap[genes_keep, ]
ggplot(
  stats,
  aes(
    mean,
    detected
  )
) +
  scale_x_log10() +
  geom_point(size = 0.3, aes(color = max_expr <1)) +
  geom_text(aes(
    label = gene_name
  ),
  check_overlap = TRUE, nudge_y = -0.1, size = 2.5
  )

Create Design Matrix

design_fap <-
  model.matrix(~ -1 + clusters_condition + sample,
    data = colData(sce10x_fap)
  )[, -c(7)]
colnames(design_fap) <- str_replace(colnames(design_fap), "clusters_condition|sample", "")
# colnames(design_fap) <- str_replace(colnames(design_fap), ":condition", "")

design_fap[1:3, ]
                    fap_1_aged fap_1_yng fap_2_aged fap_2_yng yng2 yng3 aged2 aged3 aged4
GACTATGTCCGGCTTT_d1          1         0          0         0    0    0     0     0     0
GATTGGTAGGGAGTGG_d1          0         0          1         0    0    0     0     0     0
AAGACAATCTTCCAGC_d1          0         0          1         0    0    0     0     0     0

Compute Observational Weights

assay(sce10x_fap, "counts") <- round(assay(sce10x_fap, "counts"))
system.time({
  zinb <-
    zinbFit(sce10x_fap,
      K = 0,
      X = design_fap,
      verbose = TRUE,
      BPPARAM = MulticoreParam(3),
      epsilon = 1e12
    )
})
Create model:
ok
Initialize parameters:
ok
Optimize parameters:
Iteration 1
penalized log-likelihood = -59958111.6221251
After dispersion optimization = -107505848.923134
   user  system elapsed 
    244       3     125 
After right optimization = -107495622.381593
After orthogonalization = -107495622.381593
   user  system elapsed 
  208.3     3.5   114.5 
After left optimization = -99050659.2138885
After orthogonalization = -99050659.2138885
Iteration 2
penalized log-likelihood = -99050659.2138885
After dispersion optimization = -99050659.1494286
   user  system elapsed 
  229.7     2.5   121.4 
After right optimization = -99050483.8513361
After orthogonalization = -99050483.8513361
   user  system elapsed 
   44.0     1.8    23.4 
After left optimization = -99050483.4421824
After orthogonalization = -99050483.4421824
Iteration 3
penalized log-likelihood = -99050483.4421824
ok
   user  system elapsed 
   1821     105     948 
weights <- computeObservationalWeights(zinb, as.matrix(assay(sce10x_fap)))
dimnames(weights) <- dimnames(sce10x_fap)
assay(sce10x_fap, "weights") <- weights

convert to SCE to DESeqDataSet object

dds_fap <-
  convertTo(sce10x_fap, type = c("DESeq2"))
converting counts to integer mode
design(dds_fap) <- design_fap
assay(dds_fap, "weights") <- assay(sce10x_fap, "weights")
dds_fap <- estimateSizeFactors(dds_fap, type = "poscounts")
dds_fap <-
  DESeq(dds_fap,
    test = "LRT",
    useT = TRUE,
    reduced = design_fap[, 1:4],
    minmu = 1e-6,
    parallel = TRUE,
    BPPARAM = MulticoreParam(3),
    minRep = Inf
  )
using supplied model matrix
using pre-existing size factors
estimating dispersions
gene-wise dispersion estimates: 3 workers
mean-dispersion relationship
final dispersion estimates, fitting model and testing: 3 workers
plotDispEsts(dds_fap)

resultsNames(dds_fap)
[1] "fap_1_aged" "fap_1_yng"  "fap_2_aged" "fap_2_yng"  "yng2"       "yng3"       "aged2"      "aged3"      "aged4"     

Plot batch effects

batch_dt <-
  rowData(dds_fap) %>%
  as_tibble(rownames = "gene_id") %>%
  select("gene_id", "yng2":"aged4")
ggplot(
  batch_dt,
  aes(
    x = yng2,
    y = yng3
  )
) +
  geom_point(
    size = .2,
    alpha = 0.3
  ) +
  geom_text(aes(
    label = gene_id
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  )

ggplot(
  batch_dt,
  aes(
    x = aged2,
    y = aged3
  )
) +
  geom_point(
    size = .2,
    alpha = 0.3
  ) +
  geom_text(aes(
    label = gene_id
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  )

ggplot(
  batch_dt,
  aes(
    x = aged2,
    y = aged4
  )
) +
  geom_point(
    size = .2,
    alpha = 0.3
  ) +
  geom_text(aes(
    label = gene_id
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  )

Test contrasts

c1 <- c(1, -1, 1, -1, 0, 0, 0, 0, 0) / 2
c2 <- c(-1, -1, 1, 1, 0, 0, 0, 0, 0) / 2
c3 <- c(1, -1, 0, 0, 0, 0, 0, 0, 0)
c4 <- c(0, 0, 1, -1, 0, 0, 0, 0, 0)
c5 <- c(-1, 0, 1, 0, 0, 0, 0, 0, 0)
c6 <- c(0, -1, 0, 1, 0, 0, 0, 0, 0)


fap_contrast_vec <- list(
  fap_aging = c1,
  fap2_1 = c2,
  fap1_aging = c3,
  fap2_aging = c4,
  fap2_1a = c5,
  fap2_1y = c6
)
lfc_fap <-
  imap_dfc(fap_contrast_vec,
    get_lfc,
    dds = dds_fap
  ) %>%
  bind_cols(
    gene_id = rownames(dds_fap),
    .
  )
using 'ashr' for LFC shrinkage. If used in published research, please cite:
    Stephens, M. (2016) False discovery rates: a new deal. Biostatistics, 18:2.
    https://doi.org/10.1093/biostatistics/kxw041
using 'ashr' for LFC shrinkage. If used in published research, please cite:
    Stephens, M. (2016) False discovery rates: a new deal. Biostatistics, 18:2.
    https://doi.org/10.1093/biostatistics/kxw041
using 'ashr' for LFC shrinkage. If used in published research, please cite:
    Stephens, M. (2016) False discovery rates: a new deal. Biostatistics, 18:2.
    https://doi.org/10.1093/biostatistics/kxw041
using 'ashr' for LFC shrinkage. If used in published research, please cite:
    Stephens, M. (2016) False discovery rates: a new deal. Biostatistics, 18:2.
    https://doi.org/10.1093/biostatistics/kxw041
using 'ashr' for LFC shrinkage. If used in published research, please cite:
    Stephens, M. (2016) False discovery rates: a new deal. Biostatistics, 18:2.
    https://doi.org/10.1093/biostatistics/kxw041
using 'ashr' for LFC shrinkage. If used in published research, please cite:
    Stephens, M. (2016) False discovery rates: a new deal. Biostatistics, 18:2.
    https://doi.org/10.1093/biostatistics/kxw041
lfc_fap <-
  left_join(lfc_fap,
    rowData(dds_fap) %>%
      as_tibble(rownames = "gene_id"),
    by = "gene_id"
  )
lfc_fap

Save data

write_tsv(
  lfc_fap,
  file.path(
    data_dir,
    "preprocessed",
    "fap_scrnaseq_moderated_lfc.txt"
  )
)
rowData(sce10x_fap) <-
  left_join(rowData(sce10x_fap) %>%
    as_tibble(rownames = "gene_id") %>%
    select(gene_id), lfc_fap, by = "gene_id") %>%
  DataFrame(.)

rownames(rowData(sce10x_fap)) <- rowData(sce10x_fap)$gene_id
saveRDS(
  sce10x_fap,
  file.path(
    data_dir,
    "preprocessed",
    "sce10x_fap_filtered_final.rds"
  )
)

Make volcano plots

lfc_thresh <- 1
svalue_thresh <- 10e-8
volcano_plots <-
  map(names(fap_contrast_vec)[1:2],
    plot_volcano,
    lfc_thresh = lfc_thresh,
    svalue_thresh = svalue_thresh,
    lfc = lfc_fap,
  suffix="fap_labeled"
  )
Saving 7 x 7 in image
volcano_plots
[[1]]

[[2]]

lfc_thresh <- 1
svalue_thresh <- 10e-8
volcano_plots_unlabeled <-
  map(names(fap_contrast_vec)[1:2],
    plot_volcano,
    lfc_thresh = lfc_thresh,
    svalue_thresh = svalue_thresh,
    lfc = lfc_fap,
  suffix="fap_unlabeled",
  label=c("")
  )
Saving 7 x 7 in image
volcano_plots_unlabeled
[[1]]

[[2]]

genes_hits_aging_up <-
  lfc_fap %>%
  filter(lfc_fap_aging > 1) %>%
  arrange(-lfc_fap_aging) %>%
  pull(gene_id)
genes_hits_aging_up
 [1] "Apod"          "Csmd1"         "Fetub"         "Trf"           "Sbno2"         "Apoe"          "9030624G23Rik" "Cebpb"         "Runx1"        
[10] "C4b"           "Arih1"         "H2-Q4"         "Dbp"           "Cstf3"         "Rtn1"          "Gm13307"       "Galnt15"       "Nr1d2"        
[19] "Prg4"          "0610043K17Rik" "Gpx3"          "Spats2"        "Col12a1"       "Dram1"         "Dpyd"          "Marchf3"       "Sugct"        
[28] "Irak3"         "Il1r1"         "Gm20400"       "Cxcl1"         "Gm49767"       "Nop58"         "Aff1"          "Ell2"          "Abca6"        
map(genes_hits_aging_up[1:10], plot_expression)
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

[[7]]

[[8]]

[[9]]

[[10]]

genes_hits_aging_down <-
  lfc_fap %>%
  filter(lfc_fap_aging < -1) %>%
  arrange(lfc_fap_aging) %>%
  pull(gene_id)
genes_hits_aging_down
  [1] "Col3a1"                "Col1a1"                "Cpz"                   "Sparc"                 "Col1a2"                "H19"                  
  [7] "C430049B03Rik"         "Nrk"                   "Itm2a"                 "Col6a1"                "Col6a2"                "Col5a1"               
 [13] "Col6a3"                "Col5a2"                "Unc13c"                "Adamts16"              "Col5a3"                "Col4a1"               
 [19] "Adamts17"              "Serpinh1"              "Sfrp2"                 "Mfap5"                 "mt-Nd3"                "Plac9a"               
 [25] "Tppp3"                 "Meg3"                  "Pcolce"                "mt-Co2"                "C1qtnf3"               "S100a10"              
 [31] "Lpl"                   "Nrep"                  "Hspg2"                 "Serpinf1"              "Nid1"                  "mt-Atp6"              
 [37] "Fbn1"                  "C1qtnf6"               "Marcks"                "Gm49450"               "Fstl1"                 "Dpt"                  
 [43] "Cd248"                 "B830012L14Rik"         "Ppic"                  "Sbsn"                  "Fam155a"               "Col15a1"              
 [49] "Col4a2"                "mt-Co3"                "Gm28438"               "S100a11"               "Maged2"                "Stmn4"                
 [55] "Adamts19"              "Fn1"                   "Mmp2"                  "Gm37899"               "Tmsb10"                "Adamtsl2"             
 [61] "Adamts2"               "Tmsb4x"                "Stmn1"                 "Calr"                  "Thy1"                  "mt-Rnr2"              
 [67] "Clec3b"                "Gm9780"                "Serf2"                 "Sphkap"                "Lamc1"                 "Ret"                  
 [73] "Ace"                   "Nupr1"                 "Ptn"                   "Ccdc80"                "Anxa2"                 "Adam12"               
 [79] "Cd34"                  "Angptl1"               "Gap43"                 "mt-Rnr1"               "Igfbp6"                "Lgals1"               
 [85] "Cd81"                  "Bcat1"                 "Ednra"                 "Gas1"                  "Tuba1a"                "Cavin3"               
 [91] "Islr"                  "Crip1"                 "Mfap4"                 "Htra1"                 "Vim"                   "Rcn3"                 
 [97] "Myl6"                  "Hhip"                  "Diaph3"                "Oaf"                   "Bmp1"                  "Ifi27l2a"             
[103] "Ppib"                  "Spon2"                 "Esrrg"                 "Gnas"                  "Rps18"                 "Ucp2"                 
[109] "Nme2"                  "H3f3a"                 "Pmp22"                 "Itih5"                 "Loxl2"                 "Ifi27"                
[115] "Robo2"                 "ENSMUSG00000002900.16" "Ppp2r2b"               "Timp2"                 "Rps14"                 "Rian"                 
[121] "Rps6"                  "mt-Nd4"                "Anxa5"                 "Fam167a"               "Rps23"                 "Ptms"                 
[127] "Rpl13a"                "Rps17"                 "Gm45213"               "Tmem119"               "Hsp90b1"               "Nrxn3"                
[133] "Lamb2"                 "Adarb2"                "Rpl41"                 "Calu"                  "ENSMUSG00000001175.15" "Tmed3"                
[139] "Cdkn1c"                "Creb3l1"              
map(genes_hits_aging_down[1:10], plot_expression)
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

[[7]]

[[8]]

[[9]]

[[10]]

genes_hits_fap2_up <-
  lfc_fap %>%
  filter(lfc_fap2_1 > 1) %>%
  arrange(-lfc_fap2_1) %>%
  pull(gene_id)
genes_hits_fap2_up
 [1] "Sema3e"                "Adamts16"              "Sema3c"                "Dact2"                 "Pi16"                  "Cmah"                 
 [7] "Car8"                  "Sbsn"                  "Fbn1"                  "Cd55"                  "Ugdh"                  "Opcml"                
[13] "Limch1"                "Anxa3"                 "Sv2c"                  "Gpr1"                  "Fam167a"               "Pdgfc"                
[19] "Ano3"                  "Gap43"                 "Efemp1"                "Rorb"                  "Efhd1"                 "H19"                  
[25] "Stmn4"                 "Fn1"                   "Duox1"                 "Creb5"                 "Efna5"                 "Gfpt2"                
[31] "Krt80"                 "Uap1"                  "Robo1"                 "Cd248"                 "Adarb2"                "Adgrd1"               
[37] "Pcolce2"               "Heg1"                  "Tmem100"               "Dpp4"                  "Ildr2"                 "Igfbp5"               
[43] "Ackr3"                 "Grm7"                  "Flnb"                  "Axl"                   "Mfap5"                 "Ntrk3"                
[49] "ENSMUSG00000071984.10" "Adamts5"               "Pcsk6"                 "Emilin2"               "Ptprj"                 "Ly6c1"                
[55] "Pla1a"                 "Lurap1l"               "Itgb7"                 "Procr"                 "Kank1"                 "Ppp1r14b"             
[61] "Sdk1"                  "Pde8a"                 "Smpd3"                 "Ppp2r2b"               "Il18"                  "Aldh1a3"              
map(genes_hits_fap2_up[1:10], plot_expression)
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

[[7]]

[[8]]

[[9]]

[[10]]

genes_hits_fap1_up <-
  lfc_fap %>%
  filter(lfc_fap2_1 < -1) %>%
  arrange(lfc_fap2_1) %>%
  pull(gene_id)
genes_hits_fap1_up
 [1] "Mgp"                   "Cxcl14"                "Dlk1"                  "Kcnb2"                 "Apod"                  "Fmod"                 
 [7] "Ednra"                 "Smoc2"                 "Cst3"                  "Clu"                   "Mfap4"                 "Col15a1"              
[13] "Fetub"                 "Thbs4"                 "Nrk"                   "Lum"                   "Necab1"                "Fbln7"                
[19] "9530026P05Rik"         "Frmpd4"                "Sparcl1"               "Adamtsl2"              "Ptn"                   "Gm4804"               
[25] "Sphkap"                "Igfbp7"                "Cilp"                  "Mylk"                  "Cfh"                   "Rasgrp2"              
[31] "Comp"                  "Crlf1"                 "Trf"                   "Gdf10"                 "Cdh11"                 "Apoe"                 
[37] "Bgn"                   "Piezo2"                "Hsd11b1"               "G0s2"                  "Meox1"                 "Cxcl9"                
[43] "Steap4"                "Lsamp"                 "Lpl"                   "Srpx"                  "Pde4d"                 "Csmd1"                
[49] "Cpe"                   "Alpl"                  "Mdk"                   "Col4a1"                "Cpxm2"                 "Olfml3"               
[55] "Adamts17"              "Inpp4b"                "Sorl1"                 "Col4a2"                "Angptl7"               "Kcnma1"               
[61] "Pdgfrl"                "Spry1"                 "Actn1"                 "Gas1"                  "Lepr"                  "Nrxn2"                
[67] "Dgkb"                  "Crispld1"              "Nup210l"               "Lrrtm3"                "Adamts9"               "Tmem176b"             
[73] "Ccl2"                  "Cp"                    "Gfra2"                 "Fmo2"                  "Gm29216"               "ENSMUSG00000031842.14"
[79] "Lama2"                 "Cygb"                  "Slc1a3"                "Adam12"               
map(genes_hits_fap1_up[1:10], plot_expression)
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

[[7]]

[[8]]

[[9]]

[[10]]

p1 <- ggplot(lfc_fap,
  aes(
    x = lfc_fap_aging,
    y = lfc_fap2_1
  )
) +
  geom_point(
    size = 0.5,
    alpha=0.5
  )  +
  geom_smooth(alpha=0.2, colour="grey")+
  coord_fixed(ratio = 1) +
  geom_text(aes(
    label = gene_id
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  ) +
  theme_classic()
p1

ggsave(file.path(figures_dir, "fap_aging_vs_clusters_labelled.pdf"), p1)
Saving 12 x 7.41 in image
p2 <-ggplot(
  lfc_fap,
  aes(
    x = lfc_fap_aging,
    y = lfc_fap2_1
  )
) +
  geom_point(
    size = 0.5,
    alpha=0.5
  )  +
  geom_smooth(alpha=0.2, colour="grey")+
  coord_fixed(ratio = 1) +
  theme_classic()
p2

ggsave(file.path(figures_dir, "fap_aging_vs_clusters_unlabelled.pdf"), p2)
Saving 12 x 7.41 in image
ggplot(
  lfc_fap,
  aes(
    x = lfc_fap1_aging,
    y = lfc_fap2_aging
  )
) +
  geom_point(
    size = 0.5,
    alpha=0.5
  )  +
  geom_smooth(alpha=0.2, colour="grey")+
  coord_fixed(ratio = 1) +
  geom_text(aes(
    label = gene_id
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  ) +
  theme_classic()

ggplot(
  lfc_fap,
  aes(
    x = lfc_fap2_1a,
    y = lfc_fap2_1y
  )
) +
  geom_point(
    size = 0.5,
    alpha=0.5
  )  +
  geom_smooth(alpha=0.2, colour="grey")+
  coord_fixed(ratio = 1) +
  geom_text(aes(
    label = gene_id
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  ) +
  theme_classic()

map(c("Nrk", "Clu", "Sbsn"), plot_expression)
[[1]]

[[2]]

[[3]]

Enrichment analysis

HALLMARK <- msigdb_gsets(species = "Mus musculus", "H")
weighted_signatures <- vector("list", length = 4)
weighted_signatures[[1]] <- genes_hits_aging_down
weighted_signatures[[2]] <- genes_hits_aging_up
weighted_signatures[[3]] <- genes_hits_fap2_up
weighted_signatures[[4]] <- genes_hits_fap1_up
names(weighted_signatures) <- c("aging_down", "aging_up ", "fap2_up", "fap1_up")
hyp_obj <- hypeR(weighted_signatures, 
                 HALLMARK, 
                 test = "hypergeometric",
                 fdr = .9,
                 plotting = TRUE)
aging_down
aging_up 
fap2_up
fap1_up
hyp_obj$data
$aging_down
(hyp) 

  data: 

  plots: 26 Figures

  args: signature
        genesets
        test
        background
        power
        absolute
        pval
        fdr
        plotting
        quiet
$`aging_up `
(hyp) 

  data: 

  plots: 23 Figures

  args: signature
        genesets
        test
        background
        power
        absolute
        pval
        fdr
        plotting
        quiet
$fap2_up
(hyp) 

  data: 

  plots: 28 Figures

  args: signature
        genesets
        test
        background
        power
        absolute
        pval
        fdr
        plotting
        quiet
$fap1_up
(hyp) 

  data: 

  plots: 18 Figures

  args: signature
        genesets
        test
        background
        power
        absolute
        pval
        fdr
        plotting
        quiet
hyp_dots(hyp_obj, val = "fdr")
$aging_down

$`aging_up `

$fap2_up

$fap1_up

hyp_to_excel(hyp_obj, 
             file_path=file.path(data_dir, "preprocessed", "hallmark_enrichment_fap.xlsx"))
sessionInfo()
R version 4.0.2 (2020-06-22)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 18.04.5 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.7.1
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.7.1

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8     LC_MONETARY=en_US.UTF-8   
 [6] LC_MESSAGES=en_US.UTF-8    LC_PAPER=en_US.UTF-8       LC_NAME=C                  LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] parallel  stats4    stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] zinbwave_1.10.0             hypeR_1.4.0                 BiocParallel_1.22.0         EnhancedVolcano_1.6.0       ggrepel_0.8.2              
 [6] ashr_2.2-47                 DESeq2_1.28.1               forcats_0.5.0               stringr_1.4.0               dplyr_1.0.2                
[11] purrr_0.3.4                 readr_1.3.1                 tidyr_1.1.2                 tibble_3.0.3                tidyverse_1.3.0            
[16] scran_1.16.0                scater_1.16.2               ggplot2_3.3.2               SingleCellExperiment_1.10.1 SummarizedExperiment_1.18.2
[21] DelayedArray_0.14.1         matrixStats_0.56.0          Biobase_2.48.0              GenomicRanges_1.40.0        GenomeInfoDb_1.24.2        
[26] IRanges_2.22.2              S4Vectors_0.26.1            BiocGenerics_0.34.0        

loaded via a namespace (and not attached):
  [1] readxl_1.3.1              backports_1.1.9           igraph_1.2.5              splines_4.0.2             digest_0.6.25            
  [6] invgamma_1.1              htmltools_0.5.0           viridis_0.5.1             SQUAREM_2020.4            fansi_0.4.1              
 [11] magrittr_1.5              memoise_1.1.0             openxlsx_4.1.5            limma_3.44.3              annotate_1.66.0          
 [16] modelr_0.1.8              colorspace_1.4-1          blob_1.2.1                rvest_0.3.6               haven_2.3.1              
 [21] xfun_0.17                 crayon_1.3.4              RCurl_1.98-1.2            jsonlite_1.7.1            genefilter_1.70.0        
 [26] survival_3.1-12           glue_1.4.2                kableExtra_1.2.1          polyclip_1.10-0           gtable_0.3.0             
 [31] zlibbioc_1.34.0           XVector_0.28.0            webshot_0.5.2             BiocSingular_1.4.0        scales_1.1.1             
 [36] msigdbr_7.1.1             DBI_1.1.0                 edgeR_3.30.3              Rcpp_1.0.5                viridisLite_0.3.0        
 [41] xtable_1.8-4              dqrng_0.2.1               bit_4.0.4                 rsvd_1.0.3                truncnorm_1.0-8          
 [46] htmlwidgets_1.5.1         httr_1.4.2                RColorBrewer_1.1-2        ellipsis_0.3.1            pkgconfig_2.0.3          
 [51] XML_3.99-0.5              farver_2.0.3              dbplyr_1.4.4              locfit_1.5-9.4            labeling_0.3             
 [56] tidyselect_1.1.0          rlang_0.4.7               softImpute_1.4            AnnotationDbi_1.50.3      munsell_0.5.0            
 [61] cellranger_1.1.0          tools_4.0.2               visNetwork_2.0.9          cli_2.0.2                 generics_0.0.2           
 [66] RSQLite_2.2.0             broom_0.7.0               evaluate_0.14             yaml_2.2.1                knitr_1.29               
 [71] bit64_4.0.5               fs_1.5.0                  zip_2.1.1                 packrat_0.5.0             nlme_3.1-149             
 [76] reactable_0.2.1           xml2_1.3.2                compiler_4.0.2            rstudioapi_0.11           beeswarm_0.2.3           
 [81] reprex_0.3.0              statmod_1.4.34            tweenr_1.0.1              geneplotter_1.66.0        stringi_1.5.3            
 [86] lattice_0.20-41           Matrix_1.2-18             vctrs_0.3.4               pillar_1.4.6              lifecycle_0.2.0          
 [91] BiocNeighbors_1.6.0       cowplot_1.1.0             bitops_1.0-6              irlba_2.3.3               R6_2.4.1                 
 [96] gridExtra_2.3             vipor_0.4.5               MASS_7.3-52               assertthat_0.2.1          rprojroot_1.3-2          
[101] withr_2.2.0               GenomeInfoDbData_1.2.3    mgcv_1.8-33               hms_0.5.3                 grid_4.0.2               
[106] rmarkdown_2.3             DelayedMatrixStats_1.10.1 mixsqp_0.3-43             ggforce_0.3.2             lubridate_1.7.9          
[111] base64enc_0.1-3           ggbeeswarm_0.6.0         
LS0tCnRpdGxlOiAiTW91c2UgTXVzY2xlIFN0ZW0gQ2VsbCBQcm9qZWN0ICIKc3VidGl0bGU6ICJQYXJ0IDViOiBydW4gZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXMgb24gZmFwIGNlbGxzIgphdXRob3I6IAotIG5hbWU6IFJpY2sgRmFyb3VuaQogIGFmZmlsaWF0aW9uOgogIC0gJmNydWsgR8Opbm9tZSBRdcOpYmVjIElubm92YXRpb24gQ2VudHJlLCBNY0dpbGwgVW5pdmVyc2l0eSwgTW9udHJlYWwsIENhbmFkYQpkYXRlOiAnYHIgZm9ybWF0KFN5cy5EYXRlKCksICIlWS0lQi0lZCIpYCcKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBkZl9wcmludDogcGFnZWQKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgdG9jOiBubwogICAgdG9jX2Zsb2F0OiAKICAgICAgY29sbGFwc2VkOiBmYWxzZQogICAgICBzbW9vdGhfc2Nyb2xsOiBmYWxzZQotLS0KCgojIFByZXBhcmUgYW5hbHlzaXMgd29ya2Zsb3cKCiMjIFNldCBmaWxlcGF0aHMgYW5kIHBhcmFtZXRlcnMKCmBgYHtyIHNldHVwfQpzZXQuc2VlZCg0MikKa25pdHI6Om9wdHNfa25pdCRzZXQocm9vdC5kaXIgPSBycHJvanJvb3Q6OmZpbmRfcnN0dWRpb19yb290X2ZpbGUoKSkKb3B0aW9ucygKICByZWFkci5zaG93X3Byb2dyZXNzID0gRkFMU0UsCiAgZGlnaXRzID0gMgopCmBgYAoKIyMgTG9hZCBwYWNrYWdlcwpgYGB7cn0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKHsKICBsaWJyYXJ5KHNjYXRlcikKICBsaWJyYXJ5KHNjcmFuKQogIGxpYnJhcnkodGlkeXZlcnNlKQogIGxpYnJhcnkoREVTZXEyKQogIGxpYnJhcnkoYXNocikKICBsaWJyYXJ5KEVuaGFuY2VkVm9sY2FubykKICBsaWJyYXJ5KEJpb2NQYXJhbGxlbCkKICBsaWJyYXJ5KGh5cGVSKQogIGxpYnJhcnkoemluYndhdmUpCiAgdGhlbWVfc2V0KHRoZW1lX2J3KCkpCn0pCmBgYAoKIyMgRGVmaW5lIGZpbGUgcGF0aHMKCmBgYHtyfQpkYXRhX2RpciA8LSAiLi9kYXRhIgpmaWd1cmVzX2RpciA8LSBmaWxlLnBhdGgoIi4vZmlndXJlcyIpCmBgYAoKYGBge3J9CmdldF9jb3VudHNfc3RhdHMgPC0gZnVuY3Rpb24oc2NlMTB4X2ZhcCwgY2x1c3Rlcl90b19yZW1vdmUpIHsKICBnZW5lX2NvdW50c19ieV9jbHVzdGVyIDwtCiAgICB0KGFzc2F5KHNjZTEweF9mYXApKSAlPiUKICAgIGFzLm1hdHJpeCgpICU+JQogICAgYXNfdGliYmxlKCkgJT4lCiAgICBncm91cF9ieShjbHVzdGVyID0gY29sRGF0YShzY2UxMHhfZmFwKSRjbHVzdGVyc19jb25kaXRpb24pICU+JQogICAgc3VtbWFyaXNlX2FsbChsaXN0KH4gbWVhbiguKSkpCgogIHVtaV9jb3VudHNfbWF4PC0KICAgIGdlbmVfY291bnRzX2J5X2NsdXN0ZXJbLCAtMV0gJT4lCiAgICBzdW1tYXJpemVfYWxsKGxpc3QofiBtYXgoLikpKSAlPiUKICAgIG11dGF0ZShkdW1teSA9ICJkdW1teSIpICU+JQogICAgcGl2b3RfbG9uZ2VyKC1kdW1teSwgbmFtZXNfdG8gPSAiZ2VuZV9uYW1lIiwgdmFsdWVzX3RvID0gIm1heF9leHByIikgJT4lCiAgICBzZWxlY3QoLWR1bW15KQoKICBzdGF0cyA8LQogICAgcGVyRmVhdHVyZVFDTWV0cmljcyhzY2UxMHhfZmFwLAogICAgICBleHByc192YWx1ZXMgPSBjKCJjb3VudHMiKSwKICAgICAgZmxhdHRlbiA9IFRSVUUKICAgICkgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIGJpbmRfY29scyguLCByb3dEYXRhKHNjZTEweF9mYXApICU+JQogICAgICBhc190aWJibGUoKSkgJT4lCiAgICBiaW5kX2NvbHMoLiwgdW1pX2NvdW50c19tYXgpCgogIHJldHVybihzdGF0cykKfQoKZ2V0X2xmYyA8LSBmdW5jdGlvbihjb250cmFzdCwgbmFtZSwgZGRzKSB7CiAgbGZjU2hyaW5rKGRkcywKICAgIGNvbnRyYXN0ID0gY29udHJhc3QsCiAgICB0eXBlID0gImFzaHIiLAogICAgc3ZhbHVlID0gVAogICkgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoLWJhc2VNZWFuKSAlPiUKICAgIG11dGF0ZShzdmFsdWUgPSBhYnMoc3ZhbHVlKSkgJT4lCiAgICBzZXRfbmFtZXMocGFzdGUoYygibGZjIiwgImxmY19zZSIsICJzdmFsdWUiKSwgbmFtZSwgc2VwID0gIl8iKSkKfQoKcGxvdF9leHByZXNzaW9uIDwtIGZ1bmN0aW9uKGdlbmUpIHsKICBwbG90RXhwcmVzc2lvbihzY2UxMHhfZmFwLAogICAgZmVhdHVyZXMgPSBnZW5lLAogICAgeCA9ICJzYW1wbGUiLAogICAgZXhwcnNfdmFsdWVzID0gImxvZ2NvdW50cyIsCiAgICBjb2xvdXJfYnkgPSAiY29uZGl0aW9uIiwKICAgIHBvaW50X3NpemUgPSAxCiAgKSArCiAgICBmYWNldF93cmFwKH4gY29sRGF0YShzY2UxMHhfZmFwKSRjbHVzdGVycywgbmNvbCA9IDEpCn0KCnBsb3Rfdm9sY2FubyA8LSBmdW5jdGlvbih2YXJfbmFtZSwgbGZjX3RocmVzaCwgc3ZhbHVlX3RocmVzaCwgbGZjLCBzdWZmaXgsIGxhYmVsPU5VTEwpIHsKIHAgPC0gRW5oYW5jZWRWb2xjYW5vKGxmYywKICAgIGxhYiA9bGZjICU+JSBwdWxsKGdlbmVfaWQpLAogICAgeCA9IHBhc3RlMCgibGZjXyIsIHZhcl9uYW1lKSwKICAgIHNlbGVjdExhYiA9IGxhYmVsLAogICAgeSA9IHBhc3RlMCgic3ZhbHVlXyIsIHZhcl9uYW1lKSwKICAgIHhsYWIgPSBicXVvdGUofiBpdGFsaWMoTW9kZXJhdGVkKSB+IExvZ1syXSB+IEZDKSwKICAgIHlsYWIgPSBicXVvdGUofiAtTG9nWzEwXSB+IGl0YWxpYyhzdmFsdWUpKSwKICAgIGNvbCA9IGMoImdyZXkzMCIsICJmb3Jlc3RncmVlbiIsICJyZWQyIiwgInJveWFsYmx1ZSIpLAogICAgcEN1dG9mZiA9IHN2YWx1ZV90aHJlc2gsCiAgICBGQ2N1dG9mZiA9IGxmY190aHJlc2gsCiAgICBsZWdlbmRMYWJlbHMgPSBjKAogICAgICAiTlMiLAogICAgICBleHByZXNzaW9uKExvZ1syXSB+IEZDKSwKICAgICAgInMtdmFsdWUiLAogICAgICBleHByZXNzaW9uKHMgLSB2YWx1ZSB+IGFuZCB+IGxvZ1syXSB+IEZDKQogICAgKQogICkKICAKICBnZ3NhdmUoZmlsZS5wYXRoKGZpZ3VyZXNfZGlyLCBwYXN0ZTAoInZvbGNhbm9fc2MiLCB2YXJfbmFtZSwiX2VmZmVjdF8iLCBzdWZmaXgsICIucGRmIikpLCBwKQogIHJldHVybihwKQp9CgpgYGAKCgoKIyMgTG9hZCBkYXRhCgoKYGBge3J9CnNjZTEweCA8LQogIHJlYWRSRFMoZmlsZS5wYXRoKAogICAgZGF0YV9kaXIsCiAgICAicHJlcHJvY2Vzc2VkIiwKICAgICJzY2UxMHhfZmlsdGVyZWRfZmluYWwucmRzIgogICkpCmBgYAoKCmBgYHtyfQpzY2UxMHhfZmFwIDwtIHNjZTEweFssIGNvbERhdGEoc2NlMTB4KSRjZWxsdHlwZSA9PSAiZmFwIl0Kcm0oc2NlMTB4KQpgYGAKCmBgYHtyfQp0YWJsZShjb2xEYXRhKHNjZTEweF9mYXApJGNsdXN0ZXJzLCBjb2xEYXRhKHNjZTEweF9mYXApJHNhbXBsZSkKYGBgCgoKCiMjIERpc2NhcmQgbG93IGNvdW50cyBnZW5lcwoKYGBge3J9Cm5fZXhwcnNfZ2VuZXMgPC0KICBuZXhwcnMoc2NlMTB4X2ZhcCwKICAgIGRldGVjdGlvbl9saW1pdCA9IDUsCiAgICBieXJvdyA9IFRSVUUKICApCmtlZXAgPC0gbl9leHByc19nZW5lcyA+PSAxMAp0YWJsZShrZWVwKQpgYGAKCmBgYHtyfQpzY2UxMHhfZmFwIDwtIHNjZTEweF9mYXBba2VlcCwgXQpgYGAKCmBgYHtyfQpiYXRjaF9nZW5lc19yZW1vdmUgPC0gYygiQ2hhZCIsICJDeGNsMTMiLCAiU3BwMSIsICJDaWxwMiIsICJLY25xNSIsICJUbmMiLCAiS3J0ZGFwIikKYGBgCgoKYGBge3J9Cm1hcChiYXRjaF9nZW5lc19yZW1vdmUsIHBsb3RfZXhwcmVzc2lvbikKYGBgCgpgYGB7cn0Kc2NlMTB4X2ZhcCA8LSBzY2UxMHhfZmFwWyEocm93bmFtZXMoc2NlMTB4X2ZhcCkgJWluJSBiYXRjaF9nZW5lc19yZW1vdmUpLCBdCmBgYAoKIyMgIERpc2NhcmQgbG93IGNsdXN0ZXIgbWVhbiBleHByZXNzaW9uIGdlbmVzCgpgYGB7cn0Kc3RhdHMgPC0gZ2V0X2NvdW50c19zdGF0cyhzY2UxMHhfZmFwKQpzdGF0cwpgYGAKCgoKCmBgYHtyfQptYXhfdGhyZXNoIDwtIC4zCnN0YXRzICU+JQogIGNvdW50KG1heF9leHByID4gbWF4X3RocmVzaCkKYGBgCgoKCmBgYHtyIGZpZy53aWR0aD03fQpnZ3Bsb3Qoc3RhdHMpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMobWF4X2V4cHIpLCBiaW5zID0gMTAwKSArCiAgc2NhbGVfeF9sb2cxMCgpICsKICBmYWNldF93cmFwKH50b3BfaHZnX2ZhcCkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1heF90aHJlc2gpCmBgYAoKCgpgYGB7cn0KZ2VuZXNfdG9fcGxvdCA8LQogIHN0YXRzICU+JQogIGZpbHRlcihtYXhfZXhwciA8PSBtYXhfdGhyZXNoKSAlPiUKICBhcnJhbmdlKC1tYXhfZXhwciklPiUKICBwdWxsKGdlbmVfbmFtZSkgCmBgYAoKYGBge3J9Cm1hcChnZW5lc190b19wbG90WzE6NV0sIHBsb3RfZXhwcmVzc2lvbikKYGBgCgoKCmBgYHtyfQpnZW5lc19rZWVwIDwtCiAgc3RhdHMgJT4lCiAgZmlsdGVyKG1heF9leHByID4gbWF4X3RocmVzaCkgJT4lCiAgcHVsbChnZW5lX25hbWUpCmxlbmd0aChnZW5lc19rZWVwKQpgYGAKCmBgYHtyfQpzY2UxMHhfZmFwIDwtIHNjZTEweF9mYXBbZ2VuZXNfa2VlcCwgXQpgYGAKCmBgYHtyIGZpZy53aWR0aD0xMn0KZ2dwbG90KAogIHN0YXRzLAogIGFlcygKICAgIG1lYW4sCiAgICBkZXRlY3RlZAogICkKKSArCiAgc2NhbGVfeF9sb2cxMCgpICsKICBnZW9tX3BvaW50KHNpemUgPSAwLjMsIGFlcyhjb2xvciA9IG1heF9leHByIDwxKSkgKwogIGdlb21fdGV4dChhZXMoCiAgICBsYWJlbCA9IGdlbmVfbmFtZQogICksCiAgY2hlY2tfb3ZlcmxhcCA9IFRSVUUsIG51ZGdlX3kgPSAtMC4xLCBzaXplID0gMi41CiAgKQpgYGAKIyMgQ3JlYXRlIERlc2lnbiBNYXRyaXgKCmBgYHtyfQpkZXNpZ25fZmFwIDwtCiAgbW9kZWwubWF0cml4KH4gLTEgKyBjbHVzdGVyc19jb25kaXRpb24gKyBzYW1wbGUsCiAgICBkYXRhID0gY29sRGF0YShzY2UxMHhfZmFwKQogIClbLCAtYyg3KV0KY29sbmFtZXMoZGVzaWduX2ZhcCkgPC0gc3RyX3JlcGxhY2UoY29sbmFtZXMoZGVzaWduX2ZhcCksICJjbHVzdGVyc19jb25kaXRpb258c2FtcGxlIiwgIiIpCiMgY29sbmFtZXMoZGVzaWduX2ZhcCkgPC0gc3RyX3JlcGxhY2UoY29sbmFtZXMoZGVzaWduX2ZhcCksICI6Y29uZGl0aW9uIiwgIiIpCgpkZXNpZ25fZmFwWzE6MywgXQpgYGAKIyMgQ29tcHV0ZSBPYnNlcnZhdGlvbmFsIFdlaWdodHMKCmBgYHtyfQphc3NheShzY2UxMHhfZmFwLCAiY291bnRzIikgPC0gcm91bmQoYXNzYXkoc2NlMTB4X2ZhcCwgImNvdW50cyIpKQpgYGAKCmBgYHtyfQpzeXN0ZW0udGltZSh7CiAgemluYiA8LQogICAgemluYkZpdChzY2UxMHhfZmFwLAogICAgICBLID0gMCwKICAgICAgWCA9IGRlc2lnbl9mYXAsCiAgICAgIHZlcmJvc2UgPSBUUlVFLAogICAgICBCUFBBUkFNID0gTXVsdGljb3JlUGFyYW0oMyksCiAgICAgIGVwc2lsb24gPSAxZTEyCiAgICApCn0pCmBgYAoKCmBgYHtyfQp3ZWlnaHRzIDwtIGNvbXB1dGVPYnNlcnZhdGlvbmFsV2VpZ2h0cyh6aW5iLCBhcy5tYXRyaXgoYXNzYXkoc2NlMTB4X2ZhcCkpKQpkaW1uYW1lcyh3ZWlnaHRzKSA8LSBkaW1uYW1lcyhzY2UxMHhfZmFwKQphc3NheShzY2UxMHhfZmFwLCAid2VpZ2h0cyIpIDwtIHdlaWdodHMKYGBgCgojIyBjb252ZXJ0IHRvIFNDRSB0byBERVNlcURhdGFTZXQgb2JqZWN0CgpgYGB7cn0KZGRzX2ZhcCA8LQogIGNvbnZlcnRUbyhzY2UxMHhfZmFwLCB0eXBlID0gYygiREVTZXEyIikpCmRlc2lnbihkZHNfZmFwKSA8LSBkZXNpZ25fZmFwCmFzc2F5KGRkc19mYXAsICJ3ZWlnaHRzIikgPC0gYXNzYXkoc2NlMTB4X2ZhcCwgIndlaWdodHMiKQpgYGAKCgoKYGBge3J9CmRkc19mYXAgPC0gZXN0aW1hdGVTaXplRmFjdG9ycyhkZHNfZmFwLCB0eXBlID0gInBvc2NvdW50cyIpCmRkc19mYXAgPC0KICBERVNlcShkZHNfZmFwLAogICAgdGVzdCA9ICJMUlQiLAogICAgdXNlVCA9IFRSVUUsCiAgICByZWR1Y2VkID0gZGVzaWduX2ZhcFssIDE6NF0sCiAgICBtaW5tdSA9IDFlLTYsCiAgICBwYXJhbGxlbCA9IFRSVUUsCiAgICBCUFBBUkFNID0gTXVsdGljb3JlUGFyYW0oMyksCiAgICBtaW5SZXAgPSBJbmYKICApCmBgYAoKYGBge3J9CnBsb3REaXNwRXN0cyhkZHNfZmFwKQpgYGAKYGBge3J9CnJlc3VsdHNOYW1lcyhkZHNfZmFwKQpgYGAKCgojIyMgUGxvdCBiYXRjaCBlZmZlY3RzCgpgYGB7cn0KYmF0Y2hfZHQgPC0KICByb3dEYXRhKGRkc19mYXApICU+JQogIGFzX3RpYmJsZShyb3duYW1lcyA9ICJnZW5lX2lkIikgJT4lCiAgc2VsZWN0KCJnZW5lX2lkIiwgInluZzIiOiJhZ2VkNCIpCmBgYAoKCmBgYHtyIGZpZy53aWR0aD0xMn0KZ2dwbG90KAogIGJhdGNoX2R0LAogIGFlcygKICAgIHggPSB5bmcyLAogICAgeSA9IHluZzMKICApCikgKwogIGdlb21fcG9pbnQoCiAgICBzaXplID0gLjIsCiAgICBhbHBoYSA9IDAuMwogICkgKwogIGdlb21fdGV4dChhZXMoCiAgICBsYWJlbCA9IGdlbmVfaWQKICApLAogIGNoZWNrX292ZXJsYXAgPSBUUlVFLCBudWRnZV95ID0gLTAuMTUsIHNpemUgPSAzCiAgKQpgYGAKCgoKCmBgYHtyIGZpZy53aWR0aD0xMn0KZ2dwbG90KAogIGJhdGNoX2R0LAogIGFlcygKICAgIHggPSBhZ2VkMiwKICAgIHkgPSBhZ2VkMwogICkKKSArCiAgZ2VvbV9wb2ludCgKICAgIHNpemUgPSAuMiwKICAgIGFscGhhID0gMC4zCiAgKSArCiAgZ2VvbV90ZXh0KGFlcygKICAgIGxhYmVsID0gZ2VuZV9pZAogICksCiAgY2hlY2tfb3ZlcmxhcCA9IFRSVUUsIG51ZGdlX3kgPSAtMC4xNSwgc2l6ZSA9IDMKICApCmBgYAoKCmBgYHtyIGZpZy53aWR0aD0xMn0KZ2dwbG90KAogIGJhdGNoX2R0LAogIGFlcygKICAgIHggPSBhZ2VkMiwKICAgIHkgPSBhZ2VkNAogICkKKSArCiAgZ2VvbV9wb2ludCgKICAgIHNpemUgPSAuMiwKICAgIGFscGhhID0gMC4zCiAgKSArCiAgZ2VvbV90ZXh0KGFlcygKICAgIGxhYmVsID0gZ2VuZV9pZAogICksCiAgY2hlY2tfb3ZlcmxhcCA9IFRSVUUsIG51ZGdlX3kgPSAtMC4xNSwgc2l6ZSA9IDMKICApCmBgYAoKIyMgVGVzdCBjb250cmFzdHMgCgpgYGB7cn0KYzEgPC0gYygxLCAtMSwgMSwgLTEsIDAsIDAsIDAsIDAsIDApIC8gMgpjMiA8LSBjKC0xLCAtMSwgMSwgMSwgMCwgMCwgMCwgMCwgMCkgLyAyCmMzIDwtIGMoMSwgLTEsIDAsIDAsIDAsIDAsIDAsIDAsIDApCmM0IDwtIGMoMCwgMCwgMSwgLTEsIDAsIDAsIDAsIDAsIDApCmM1IDwtIGMoLTEsIDAsIDEsIDAsIDAsIDAsIDAsIDAsIDApCmM2IDwtIGMoMCwgLTEsIDAsIDEsIDAsIDAsIDAsIDAsIDApCgoKZmFwX2NvbnRyYXN0X3ZlYyA8LSBsaXN0KAogIGZhcF9hZ2luZyA9IGMxLAogIGZhcDJfMSA9IGMyLAogIGZhcDFfYWdpbmcgPSBjMywKICBmYXAyX2FnaW5nID0gYzQsCiAgZmFwMl8xYSA9IGM1LAogIGZhcDJfMXkgPSBjNgopCgpgYGAKCmBgYHtyfQpsZmNfZmFwIDwtCiAgaW1hcF9kZmMoZmFwX2NvbnRyYXN0X3ZlYywKICAgIGdldF9sZmMsCiAgICBkZHMgPSBkZHNfZmFwCiAgKSAlPiUKICBiaW5kX2NvbHMoCiAgICBnZW5lX2lkID0gcm93bmFtZXMoZGRzX2ZhcCksCiAgICAuCiAgKQpgYGAKCmBgYHtyfQpsZmNfZmFwIDwtCiAgbGVmdF9qb2luKGxmY19mYXAsCiAgICByb3dEYXRhKGRkc19mYXApICU+JQogICAgICBhc190aWJibGUocm93bmFtZXMgPSAiZ2VuZV9pZCIpLAogICAgYnkgPSAiZ2VuZV9pZCIKICApCmBgYAoKYGBge3J9CmxmY19mYXAKYGBgCgojIyBTYXZlIGRhdGEKCmBgYHtyfQp3cml0ZV90c3YoCiAgbGZjX2ZhcCwKICBmaWxlLnBhdGgoCiAgICBkYXRhX2RpciwKICAgICJwcmVwcm9jZXNzZWQiLAogICAgImZhcF9zY3JuYXNlcV9tb2RlcmF0ZWRfbGZjLnR4dCIKICApCikKYGBgCgpgYGB7cn0Kcm93RGF0YShzY2UxMHhfZmFwKSA8LQogIGxlZnRfam9pbihyb3dEYXRhKHNjZTEweF9mYXApICU+JQogICAgYXNfdGliYmxlKHJvd25hbWVzID0gImdlbmVfaWQiKSAlPiUKICAgIHNlbGVjdChnZW5lX2lkKSwgbGZjX2ZhcCwgYnkgPSAiZ2VuZV9pZCIpICU+JQogIERhdGFGcmFtZSguKQoKcm93bmFtZXMocm93RGF0YShzY2UxMHhfZmFwKSkgPC0gcm93RGF0YShzY2UxMHhfZmFwKSRnZW5lX2lkCmBgYAoKYGBge3J9CnNhdmVSRFMoCiAgc2NlMTB4X2ZhcCwKICBmaWxlLnBhdGgoCiAgICBkYXRhX2RpciwKICAgICJwcmVwcm9jZXNzZWQiLAogICAgInNjZTEweF9mYXBfZmlsdGVyZWRfZmluYWwucmRzIgogICkKKQpgYGAKCgoKIyMjIE1ha2Ugdm9sY2FubyBwbG90cwoKCgpgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTR9CmxmY190aHJlc2ggPC0gMQpzdmFsdWVfdGhyZXNoIDwtIDEwZS04CnZvbGNhbm9fcGxvdHMgPC0KICBtYXAobmFtZXMoZmFwX2NvbnRyYXN0X3ZlYylbMToyXSwKICAgIHBsb3Rfdm9sY2FubywKICAgIGxmY190aHJlc2ggPSBsZmNfdGhyZXNoLAogICAgc3ZhbHVlX3RocmVzaCA9IHN2YWx1ZV90aHJlc2gsCiAgICBsZmMgPSBsZmNfZmFwLAogIHN1ZmZpeD0iZmFwX2xhYmVsZWQiCiAgKQp2b2xjYW5vX3Bsb3RzCmBgYAoKCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNH0KbGZjX3RocmVzaCA8LSAxCnN2YWx1ZV90aHJlc2ggPC0gMTBlLTgKdm9sY2Fub19wbG90c191bmxhYmVsZWQgPC0KICBtYXAobmFtZXMoZmFwX2NvbnRyYXN0X3ZlYylbMToyXSwKICAgIHBsb3Rfdm9sY2FubywKICAgIGxmY190aHJlc2ggPSBsZmNfdGhyZXNoLAogICAgc3ZhbHVlX3RocmVzaCA9IHN2YWx1ZV90aHJlc2gsCiAgICBsZmMgPSBsZmNfZmFwLAogIHN1ZmZpeD0iZmFwX3VubGFiZWxlZCIsCiAgbGFiZWw9YygiIikKICApCnZvbGNhbm9fcGxvdHNfdW5sYWJlbGVkCmBgYAoKYGBge3J9CmdlbmVzX2hpdHNfYWdpbmdfdXAgPC0KICBsZmNfZmFwICU+JQogIGZpbHRlcihsZmNfZmFwX2FnaW5nID4gMSkgJT4lCiAgYXJyYW5nZSgtbGZjX2ZhcF9hZ2luZykgJT4lCiAgcHVsbChnZW5lX2lkKQpnZW5lc19oaXRzX2FnaW5nX3VwCmBgYAoKYGBge3J9Cm1hcChnZW5lc19oaXRzX2FnaW5nX3VwWzE6MTBdLCBwbG90X2V4cHJlc3Npb24pCmBgYAoKYGBge3J9CmdlbmVzX2hpdHNfYWdpbmdfZG93biA8LQogIGxmY19mYXAgJT4lCiAgZmlsdGVyKGxmY19mYXBfYWdpbmcgPCAtMSkgJT4lCiAgYXJyYW5nZShsZmNfZmFwX2FnaW5nKSAlPiUKICBwdWxsKGdlbmVfaWQpCmdlbmVzX2hpdHNfYWdpbmdfZG93bgpgYGAKCmBgYHtyfQptYXAoZ2VuZXNfaGl0c19hZ2luZ19kb3duWzE6MTBdLCBwbG90X2V4cHJlc3Npb24pCmBgYAoKCgpgYGB7cn0KZ2VuZXNfaGl0c19mYXAyX3VwIDwtCiAgbGZjX2ZhcCAlPiUKICBmaWx0ZXIobGZjX2ZhcDJfMSA+IDEpICU+JQogIGFycmFuZ2UoLWxmY19mYXAyXzEpICU+JQogIHB1bGwoZ2VuZV9pZCkKZ2VuZXNfaGl0c19mYXAyX3VwCmBgYAoKYGBge3J9Cm1hcChnZW5lc19oaXRzX2ZhcDJfdXBbMToxMF0sIHBsb3RfZXhwcmVzc2lvbikKYGBgCgpgYGB7cn0KZ2VuZXNfaGl0c19mYXAxX3VwIDwtCiAgbGZjX2ZhcCAlPiUKICBmaWx0ZXIobGZjX2ZhcDJfMSA8IC0xKSAlPiUKICBhcnJhbmdlKGxmY19mYXAyXzEpICU+JQogIHB1bGwoZ2VuZV9pZCkKZ2VuZXNfaGl0c19mYXAxX3VwCmBgYAoKYGBge3J9Cm1hcChnZW5lc19oaXRzX2ZhcDFfdXBbMToxMF0sIHBsb3RfZXhwcmVzc2lvbikKYGBgCgoKYGBge3IgZmlnLndpZHRoPTEyfQpwMSA8LSBnZ3Bsb3QobGZjX2ZhcCwKICBhZXMoCiAgICB4ID0gbGZjX2ZhcF9hZ2luZywKICAgIHkgPSBsZmNfZmFwMl8xCiAgKQopICsKICBnZW9tX3BvaW50KAogICAgc2l6ZSA9IDAuNSwKICAgIGFscGhhPTAuNQogICkgICsKICBnZW9tX3Ntb290aChhbHBoYT0wLjIsIGNvbG91cj0iZ3JleSIpKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkgKwogIGdlb21fdGV4dChhZXMoCiAgICBsYWJlbCA9IGdlbmVfaWQKICApLAogIGNoZWNrX292ZXJsYXAgPSBUUlVFLCBudWRnZV95ID0gLTAuMTUsIHNpemUgPSAzCiAgKSArCiAgdGhlbWVfY2xhc3NpYygpCnAxCmdnc2F2ZShmaWxlLnBhdGgoZmlndXJlc19kaXIsICJmYXBfYWdpbmdfdnNfY2x1c3RlcnNfbGFiZWxsZWQucGRmIiksIHAxKQpgYGAKYGBge3IgZmlnLndpZHRoPTEyfQpwMiA8LWdncGxvdCgKICBsZmNfZmFwLAogIGFlcygKICAgIHggPSBsZmNfZmFwX2FnaW5nLAogICAgeSA9IGxmY19mYXAyXzEKICApCikgKwogIGdlb21fcG9pbnQoCiAgICBzaXplID0gMC41LAogICAgYWxwaGE9MC41CiAgKSAgKwogIGdlb21fc21vb3RoKGFscGhhPTAuMiwgY29sb3VyPSJncmV5IikrCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSArCiAgdGhlbWVfY2xhc3NpYygpCnAyCmdnc2F2ZShmaWxlLnBhdGgoZmlndXJlc19kaXIsICJmYXBfYWdpbmdfdnNfY2x1c3RlcnNfdW5sYWJlbGxlZC5wZGYiKSwgcDIpCmBgYAoKYGBge3IgZmlnLndpZHRoPTEyfQpnZ3Bsb3QoCiAgbGZjX2ZhcCwKICBhZXMoCiAgICB4ID0gbGZjX2ZhcDFfYWdpbmcsCiAgICB5ID0gbGZjX2ZhcDJfYWdpbmcKICApCikgKwogIGdlb21fcG9pbnQoCiAgICBzaXplID0gMC41LAogICAgYWxwaGE9MC41CiAgKSAgKwogIGdlb21fc21vb3RoKGFscGhhPTAuMiwgY29sb3VyPSJncmV5IikrCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSArCiAgZ2VvbV90ZXh0KGFlcygKICAgIGxhYmVsID0gZ2VuZV9pZAogICksCiAgY2hlY2tfb3ZlcmxhcCA9IFRSVUUsIG51ZGdlX3kgPSAtMC4xNSwgc2l6ZSA9IDMKICApICsKICB0aGVtZV9jbGFzc2ljKCkKYGBgCgpgYGB7ciBmaWcud2lkdGg9MTJ9CmdncGxvdCgKICBsZmNfZmFwLAogIGFlcygKICAgIHggPSBsZmNfZmFwMl8xYSwKICAgIHkgPSBsZmNfZmFwMl8xeQogICkKKSArCiAgZ2VvbV9wb2ludCgKICAgIHNpemUgPSAwLjUsCiAgICBhbHBoYT0wLjUKICApICArCiAgZ2VvbV9zbW9vdGgoYWxwaGE9MC4yLCBjb2xvdXI9ImdyZXkiKSsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpICsKICBnZW9tX3RleHQoYWVzKAogICAgbGFiZWwgPSBnZW5lX2lkCiAgKSwKICBjaGVja19vdmVybGFwID0gVFJVRSwgbnVkZ2VfeSA9IC0wLjE1LCBzaXplID0gMwogICkgKwogIHRoZW1lX2NsYXNzaWMoKQpgYGAKCgpgYGB7cn0KbWFwKGMoIk5yayIsICJDbHUiLCAiU2JzbiIpLCBwbG90X2V4cHJlc3Npb24pCmBgYAoKIyBFbnJpY2htZW50IGFuYWx5c2lzCgoKYGBge3J9CkhBTExNQVJLIDwtIG1zaWdkYl9nc2V0cyhzcGVjaWVzID0gIk11cyBtdXNjdWx1cyIsICJIIikKYGBgCgpgYGB7cn0Kd2VpZ2h0ZWRfc2lnbmF0dXJlcyA8LSB2ZWN0b3IoImxpc3QiLCBsZW5ndGggPSA0KQp3ZWlnaHRlZF9zaWduYXR1cmVzW1sxXV0gPC0gZ2VuZXNfaGl0c19hZ2luZ19kb3duCndlaWdodGVkX3NpZ25hdHVyZXNbWzJdXSA8LSBnZW5lc19oaXRzX2FnaW5nX3VwCndlaWdodGVkX3NpZ25hdHVyZXNbWzNdXSA8LSBnZW5lc19oaXRzX2ZhcDJfdXAKd2VpZ2h0ZWRfc2lnbmF0dXJlc1tbNF1dIDwtIGdlbmVzX2hpdHNfZmFwMV91cApuYW1lcyh3ZWlnaHRlZF9zaWduYXR1cmVzKSA8LSBjKCJhZ2luZ19kb3duIiwgImFnaW5nX3VwICIsICJmYXAyX3VwIiwgImZhcDFfdXAiKQpgYGAKCmBgYHtyfQpoeXBfb2JqIDwtIGh5cGVSKHdlaWdodGVkX3NpZ25hdHVyZXMsIAogICAgICAgICAgICAgICAgIEhBTExNQVJLLCAKICAgICAgICAgICAgICAgICB0ZXN0ID0gImh5cGVyZ2VvbWV0cmljIiwKICAgICAgICAgICAgICAgICBmZHIgPSAuOSwKICAgICAgICAgICAgICAgICBwbG90dGluZyA9IFRSVUUpCmBgYApgYGB7cn0KaHlwX29iaiRkYXRhCmBgYAoKYGBge3J9Cmh5cF9kb3RzKGh5cF9vYmosIHZhbCA9ICJmZHIiKQpgYGAKCgoKYGBge3J9Cmh5cF90b19leGNlbChoeXBfb2JqLCAKICAgICAgICAgICAgIGZpbGVfcGF0aD1maWxlLnBhdGgoZGF0YV9kaXIsICJwcmVwcm9jZXNzZWQiLCAiaGFsbG1hcmtfZW5yaWNobWVudF9mYXAueGxzeCIpKQpgYGAKCgoKYGBge3J9CnNlc3Npb25JbmZvKCkKYGBgCg==