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(Seurat)
  library(tidyverse)
  library(BiocParallel)
  library(biomaRt)
  theme_set(theme_bw())
})

Helper functions

get_counts_stats <- function(sce10x_stem, cluster_to_remove) {
  gene_counts_by_cluster <-
    t(assay(sce10x_stem)) %>%
    as.matrix() %>%
    as_tibble() %>%
    group_by(cluster = colData(sce10x_stem)$cluster_condition) %>%
    summarise_all(list(~ mean(.)))

  umi_counts_max_1 <-
    gene_counts_by_cluster[c(2, 4, 5), -1] %>%
    summarize_all(list(~ max(.))) %>%
    mutate(dummy = "dummy") %>%
    pivot_longer(-dummy, names_to = "gene_name", values_to = "max_yng") %>%
    select(-dummy)

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

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

  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, data) {
  plotExpression(data,
    features = gene,
    x = "sample",
    exprs_values = "logcounts",
    colour_by = "condition",
    point_size = 1
  ) +
    facet_wrap(~ colData(data)$clusters, ncol = 1)
}

Define file paths

data_dir <- "./data"
figures_dir <- file.path("./figures")

Analysis and plots

Experiment Data

load muscle satellite cells

sce10x <-
  readRDS(file.path(
    data_dir,
    "preprocessed",
    "sce10x_filtered_final.rds"
  ))
sce10x_stem <- sce10x[, colData(sce10x)$cell_type == "stem"]
colData(sce10x_stem) <- colData(sce10x_stem)[, c("sum", "detected", "sample", "clusters", "cluster_condition", "condition")]
assay(sce10x_stem, 2) <- NULL
assay(sce10x_stem, 2) <- NULL
assay(sce10x_stem, 3) <- NULL
assay(sce10x_stem, 3) <- NULL
reducedDims(sce10x_stem) <- NULL
reducedDims(sce10x_stem) <- NULL
colData(sce10x_stem)$cluster <- "muscs"
colData(sce10x_stem) <- colData(sce10x_stem)[, c(1, 2, 3, 7, 5, 6, 4)]
rm(sce10x)
table(colData(sce10x_stem)$clusters, colData(sce10x_stem)$sample)
       
        yng1 yng2 yng3 aged1 aged2 aged3 aged4
  stem1  563 1043  383   155   300   154   340
  stem2  386  650  540   366   382   172   399
  stem3  250  220  126     0     0     0     0

Discard genes not expressed in at least 10 cells

n_exprs_genes <-
  nexprs(sce10x_stem,
    detection_limit = 0,
    byrow = TRUE
  )
keep <- n_exprs_genes >= 10
table(keep)
keep
FALSE  TRUE 
12928 20546 
sce10x_stem <- sce10x_stem[keep, ]

Compute the mean log normalized counts for each cluster

gene_counts_by_cluster <-
  t(assay(sce10x_stem, "logcounts")) %>%
  as.matrix() %>%
  as_tibble() %>%
  group_by(cluster = colData(sce10x_stem)$cluster_condition) %>%
  summarise_all(list(~ mean(.)))
gene_counts_long <-
  t(gene_counts_by_cluster[, -1]) %>%
  as_tibble(rownames = "gene") %>%
  set_names(c("gene", gene_counts_by_cluster[, 1]$cluster))
The `x` argument of `as_tibble.matrix()` must have unique column names if `.name_repair` is omitted as of tibble 2.0.0.
Using compatibility `.name_repair`.
gene_counts_long
ggplot(
  gene_counts_long,
  aes(x = stem1_yng, y = stem2_yng)
) +
  geom_point(
    size = .5,
    alpha = 0.5
  ) +
  geom_text(aes(
    label = gene
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  ) +
  geom_smooth(alpha = 0.2, colour = "grey") +
  coord_fixed(ratio = 1)

ggplot(
  gene_counts_long,
  aes(x = stem1_aged, y = stem2_aged)
) +
  geom_point(
    size = .5,
    alpha = 0.5
  ) +
  geom_text(aes(
    label = gene
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  ) +
  geom_smooth(alpha = 0.2, colour = "grey") +
  coord_fixed(ratio = 1)

ggplot(
  gene_counts_long,
  aes(x = stem1_yng, y = stem1_aged)
) +
  geom_point(
    size = .5,
    alpha = 0.5
  ) +
  geom_text(aes(
    label = gene
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  ) +
  geom_smooth(alpha = 0.2, colour = "grey") +
  coord_fixed(ratio = 1)

ggplot(
  gene_counts_long,
  aes(x = stem2_yng, y = stem2_aged)
) +
  geom_point(
    size = .5,
    alpha = 0.5
  ) +
  geom_text(aes(
    label = gene
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  ) +
  geom_smooth(alpha = 0.2, colour = "grey") +
  coord_fixed(ratio = 1)

ggplot(
  gene_counts_long,
  aes(x = stem1_yng, y = stem3_yng)
) +
  geom_point(
    size = .5,
    alpha = 0.5
  ) +
  geom_text(aes(
    label = gene
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  ) +
  geom_smooth(alpha = 0.2, colour = "grey") +
  coord_fixed(ratio = 1)

ggplot(
  gene_counts_long,
  aes(x = stem1_yng, y = stem3_yng)
) +
  geom_point(
    size = .5,
    alpha = 0.5
  ) +
  geom_text(aes(
    label = gene
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  ) +
  geom_smooth(alpha = 0.2, colour = "grey") +
  coord_fixed(ratio = 1)

ggplot(
  gene_counts_long,
  aes(x = stem2_yng, y = stem3_yng)
) +
  geom_point(
    size = .5,
    alpha = 0.5
  ) +
  geom_text(aes(
    label = gene
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  ) +
  geom_smooth(alpha = 0.2, colour = "grey") +
  coord_fixed(ratio = 1)

Tabula Muris Data

load Tabula Muris data

load(file.path(
  data_dir,
  "tabula_muris",
  "facs_Limb_Muscle_seurat_tiss.Robj"
))
facs_limb_muscle_tabula <- tiss
rm(tiss)
facs_limb_muscle_tabula <- UpdateSeuratObject(facs_limb_muscle_tabula)
Updating from v2.X to v3.X
Validating object structure
Updating object slots
Ensuring keys are in the proper strucutre
Ensuring feature names don't have underscores or pipes
Object representation is consistent with the most current Seurat version
facs_limb_muscle_tabula <- as.SingleCellExperiment(facs_limb_muscle_tabula)
facs_limb_muscle_tabula
class: SingleCellExperiment 
dim: 23341 1090 
metadata(0):
assays(3): counts logcounts scaledata
rownames(23341): 0610005C13Rik 0610007C21Rik ... l7Rn6 zsGreen-transgene
rowData names(0):
colnames(1090): A1.B002765.3_38_F.1.1 A1.D042103.3_11_M.1 ... P9.B002769.3_39_F.1.1 P9.D042186.3_8_M.1.1
colData names(18): nReads orig.ident ... nFeature_RNA ident
reducedDimNames(2): PCA TSNE
mainExpName: RNA
altExpNames(0):
load(file.path(
  data_dir,
  "tabula_muris",
  "droplet_Limb_Muscle_seurat_tiss.Robj"
))

droplet_limb_muscle_tabula <- tiss
rm(tiss)
droplet_limb_muscle_tabula <- UpdateSeuratObject(droplet_limb_muscle_tabula)
Updating from v2.X to v3.X
Validating object structure
Updating object slots
Ensuring keys are in the proper strucutre
Ensuring feature names don't have underscores or pipes
Object representation is consistent with the most current Seurat version
droplet_limb_muscle_tabula <- as.SingleCellExperiment(droplet_limb_muscle_tabula)
droplet_limb_muscle_tabula
class: SingleCellExperiment 
dim: 23341 4536 
metadata(0):
assays(3): counts logcounts scaledata
rownames(23341): Xkr4 Rp1 ... Tdtom-transgene zsGreen-transgene
rowData names(0):
colnames(4536): 10X_P7_14_AAACCTGCAGGTCCAC 10X_P7_14_AAACCTGCATCAGTAC ... 10X_P7_15_TTTGTCAGTCTCCACT 10X_P7_15_TTTGTCAGTTGTGGAG
colData names(16): orig.ident channel ... nFeature_RNA ident
reducedDimNames(2): PCA TSNE
mainExpName: RNA
altExpNames(0):

Keep muscle satellite and macrophage cells

# target_cell_types <- c("mesenchymal stem cell", "skeletal muscle satellite cell" ,"endothelial cell", "macrophage")
target_cell_types <- c("skeletal muscle satellite cell", "macrophage")
facs_limb_muscle_tabula <- facs_limb_muscle_tabula[, colData(facs_limb_muscle_tabula)$cell_ontology_class %in% target_cell_types]
droplet_limb_muscle_tabula <- droplet_limb_muscle_tabula[, colData(droplet_limb_muscle_tabula)$cell_ontology_class %in% target_cell_types]

Process and combine data from facs and droplet experiments

droplet_coldata <- colData(droplet_limb_muscle_tabula)[c("nCount_RNA", "nFeature_RNA", "mouse.id", "cell_ontology_class", "cluster.ids")]
droplet_coldata$condition <- "mid-aged"
colnames(droplet_coldata) <- c("sum", "detected", "sample", "cluster", "cluster_condition", "condition")
colData(droplet_limb_muscle_tabula) <- droplet_coldata
colData(droplet_limb_muscle_tabula)
DataFrame with 662 rows and 6 columns
                                 sum  detected   sample                cluster cluster_condition   condition
                           <numeric> <integer> <factor>            <character>       <character> <character>
10X_P7_14_AAACGGGAGTTTCCTT     19328      3305   3-F-56             macrophage                 7    mid-aged
10X_P7_14_AAATGCCCACTCAGGC      5321      1204   3-F-56             macrophage                 7    mid-aged
10X_P7_14_AAATGCCGTCAACATC      2069       892   3-F-56             macrophage                 7    mid-aged
10X_P7_14_AAATGCCTCGATCCCT      4580      1415   3-F-56 skeletal muscle sate..                 5    mid-aged
10X_P7_14_AACACGTAGTAGGTGC      3978       950   3-F-56             macrophage                 7    mid-aged
...                              ...       ...      ...                    ...               ...         ...
10X_P7_15_TTTGCGCTCGGAAACG      3186      1120   3-F-57             macrophage                 7    mid-aged
10X_P7_15_TTTGGTTAGAGCTGGT      3357      1094   3-F-57 skeletal muscle sate..                 5    mid-aged
10X_P7_15_TTTGGTTAGCGATGAC      5408      1809   3-F-57             macrophage                 7    mid-aged
10X_P7_15_TTTGGTTAGGTGATAT      8579      1929   3-F-57             macrophage                 7    mid-aged
10X_P7_15_TTTGTCAGTTGTGGAG      3463      1131   3-F-57 skeletal muscle sate..                 5    mid-aged
facs_coldata <- colData(facs_limb_muscle_tabula)[c("nCount_RNA", "nFeature_RNA", "mouse.id", "cell_ontology_class", "cluster.ids")]
facs_coldata$condition <- "mid-aged"
colnames(facs_coldata) <- c("sum", "detected", "sample", "cluster", "cluster_condition", "condition")
colData(facs_limb_muscle_tabula) <- facs_coldata
colData(facs_limb_muscle_tabula)
DataFrame with 585 rows and 6 columns
                             sum  detected   sample                cluster cluster_condition   condition
                       <numeric> <integer> <factor>            <character>       <character> <character>
A1.B002765.3_38_F.1.1     878318      2149   3_38_F skeletal muscle sate..                 0    mid-aged
A1.D042103.3_11_M.1       774558      1194   3_11_M skeletal muscle sate..                 0    mid-aged
A1.D042186.3_8_M.1.1      914257      2751   3_8_M  skeletal muscle sate..                 2    mid-aged
A10.B002765.3_38_F.1.1   1543007      2333   3_38_F skeletal muscle sate..                 0    mid-aged
A10.B002769.3_39_F.1.1   2521710      3556   3_39_F skeletal muscle sate..                 2    mid-aged
...                          ...       ...      ...                    ...               ...         ...
P7.B002765.3_38_F.1.1    1134974      3213   3_38_F             macrophage                 5    mid-aged
P7.D042473.3_10_M.1.1     963668      3584   3_10_M             macrophage                 5    mid-aged
P8.B002765.3_38_F.1.1     949789      2342   3_38_F             macrophage                 5    mid-aged
P8.B002769.3_39_F.1.1    2217452      3040   3_39_F             macrophage                 5    mid-aged
P9.B002765.3_38_F.1.1    1446574      2749   3_38_F             macrophage                 5    mid-aged
reducedDim(droplet_limb_muscle_tabula) <- NULL
reducedDim(facs_limb_muscle_tabula) <- NULL
reducedDim(droplet_limb_muscle_tabula) <- NULL
reducedDim(facs_limb_muscle_tabula) <- NULL
assay(droplet_limb_muscle_tabula, 3) <- NULL
assay(facs_limb_muscle_tabula, 3) <- NULL
colData(droplet_limb_muscle_tabula)$cluster <-
  case_when(
    colData(droplet_limb_muscle_tabula)$cluster == "macrophage" ~ "tabula_droplet_macrophage",
    colData(droplet_limb_muscle_tabula)$cluster == "skeletal muscle satellite cell" ~ "tabula_droplet_muscs"
  )

colData(facs_limb_muscle_tabula)$cluster <-
  case_when(
    colData(facs_limb_muscle_tabula)$cluster == "macrophage" ~ "tabula_facs_macrophage",
    colData(facs_limb_muscle_tabula)$cluster == "skeletal muscle satellite cell" ~ "tabula_facs_muscs"
  )

colData(droplet_limb_muscle_tabula)$cluster_condition <- 
  paste(colData(droplet_limb_muscle_tabula)$cluster, 
        colData(droplet_limb_muscle_tabula)$cluster_condition, sep = "_")
colData(facs_limb_muscle_tabula)$cluster_condition <- 
  paste(colData(facs_limb_muscle_tabula)$cluster, 
        colData(facs_limb_muscle_tabula)$cluster_condition, sep = "_")
colData(facs_limb_muscle_tabula)$clusters <- "facs_tabula"
colData(droplet_limb_muscle_tabula)$clusters <- "droplet_tabula"
droplet_limb_muscle_tabula <- droplet_limb_muscle_tabula[rownames(facs_limb_muscle_tabula), ]
tabula_muris <- cbind(droplet_limb_muscle_tabula, facs_limb_muscle_tabula)
# tabula_muris <- droplet_limb_muscle_tabula
tabula_muris
class: SingleCellExperiment 
dim: 23341 1247 
metadata(0):
assays(2): counts logcounts
rownames(23341): 0610005C13Rik 0610007C21Rik ... l7Rn6 zsGreen-transgene
rowData names(0):
colnames(1247): 10X_P7_14_AAACGGGAGTTTCCTT 10X_P7_14_AAATGCCCACTCAGGC ... P8.B002769.3_39_F.1.1 P9.B002765.3_38_F.1.1
colData names(7): sum detected ... condition clusters
reducedDimNames(0):
mainExpName: RNA
altExpNames(0):

Discard genes not expressed in at least 10 cells

n_exprs_genes <-
  nexprs(tabula_muris,
    detection_limit = 0,
    byrow = TRUE
  )
keep <- n_exprs_genes >= 10
table(keep)
keep
FALSE  TRUE 
10714 12627 
tabula_muris <- tabula_muris[keep, ]

Map gene names to ENSEMBL gene IDS

ensembl93 <- useEnsembl(
  biomart = "genes",
  dataset = "mmusculus_gene_ensembl",
  version = 93
)
mart <-
  useDataset(
    "mmusculus_gene_ensembl",
    ensembl93
  ) # from 2018

gene_metadata <-
  getBM(
    filters = "external_gene_name",
    attributes = c(
      "ensembl_gene_id_version",
      "external_gene_name",
      "gene_biotype",
      "chromosome_name",
      "description"
    ),
    values = rownames(tabula_muris),
    mart = mart
  )
chr_to_keep <- c(seq(1, 19), "MT", "X", "Y")
gene_metadata <-
  gene_metadata %>%
  filter(chromosome_name %in% chr_to_keep) %>%
  filter(!duplicated(external_gene_name))

gene_metadata <-
  gene_metadata %>%
  left_join(tibble(external_gene_name = rownames(tabula_muris)),
    .,
    by = "external_gene_name"
  ) %>%
  dplyr::rename(chr = "chromosome_name")
rowData(tabula_muris) <- gene_metadata

Discard genes not in standard chromosomes and those with duplicate ids

tabula_muris_filtered <- tabula_muris[!is.na(rowData(tabula_muris)$ensembl_gene_id_version), ]
tabula_muris_filtered
class: SingleCellExperiment 
dim: 11528 1247 
metadata(0):
assays(2): counts logcounts
rownames(11528): 0610009B22Rik 0610009L18Rik ... Zzef1 Zzz3
rowData names(5): external_gene_name ensembl_gene_id_version gene_biotype chr description
colnames(1247): 10X_P7_14_AAACGGGAGTTTCCTT 10X_P7_14_AAATGCCCACTCAGGC ... P8.B002769.3_39_F.1.1 P9.B002765.3_38_F.1.1
colData names(7): sum detected ... condition clusters
reducedDimNames(0):
mainExpName: RNA
altExpNames(0):
table(colData(tabula_muris_filtered)$cluster)

tabula_droplet_macrophage      tabula_droplet_muscs    tabula_facs_macrophage         tabula_facs_muscs 
                      308                       354                        45                       540 
# gene_counts_by_cluster_tabula_muris <-
#   t(assay(tabula_muris_filtered, "logcounts")) %>%
#   as.matrix() %>%
#   as_tibble() %>%
#   group_by(cluster = colData(tabula_muris_filtered)$cluster) %>%
#   summarise_all(list(~ mean(.)))
# gene_counts_long_tabula_muris <-
#   t(gene_counts_by_cluster_tabula_muris[, -1]) %>%
#   as_tibble(rownames = "gene") %>%
#   set_names(c("gene", gene_counts_by_cluster_tabula_muris[, 1]$cluster))
# gene_counts_long_tabula_muris

Combined Data

Join data using common genes only

commmon_genes <- 
  intersect(rowData(sce10x_stem)$ensembl_gene_id_version, 
            rowData(tabula_muris_filtered)$ensembl_gene_id_version)
sce10x_stem_filtered <- sce10x_stem
rowData(sce10x_stem_filtered) <- rowData(sce10x_stem_filtered)[, c(2, 1, 3, 4, 5)]
rownames(sce10x_stem_filtered) <- rowData(sce10x_stem)$ensembl_gene_id_version
rownames(tabula_muris_filtered) <- rowData(tabula_muris_filtered)$ensembl_gene_id_version
sce10x_stem_filtered <- sce10x_stem_filtered[commmon_genes, ]
tabula_muris_filtered_2 <- tabula_muris_filtered[commmon_genes, ]
rowData(sce10x_stem_filtered) <- rowData(tabula_muris_filtered_2)

rownames(sce10x_stem_filtered) <- rowData(sce10x_stem_filtered)$external_gene_name
rownames(tabula_muris_filtered_2) <- rowData(tabula_muris_filtered_2)$external_gene_name
combined <- cbind(sce10x_stem_filtered, tabula_muris_filtered_2)
combined
class: SingleCellExperiment 
dim: 9978 7676 
metadata(1134): tximetaInfo quantInfo ... txomeInfo txdbInfo
assays(2): counts logcounts
rownames(9978): Lypla1 Tcea1 ... Uty Ddx3y
rowData names(5): external_gene_name ensembl_gene_id_version gene_biotype chr description
colnames(7676): CTACAGAGTGGCCCAT_d1 CTAACCCCACACCTGG_d1 ... P8.B002769.3_39_F.1.1 P9.B002765.3_38_F.1.1
colData names(7): sum detected ... condition clusters
reducedDimNames(0):
mainExpName: RNA
altExpNames(0):

Compute the mean log normalized counts for each cluster

gene_counts_by_cluster_combined <-
  t(assay(combined, "logcounts")) %>%
  as.matrix() %>%
  as_tibble() %>%
  group_by(cluster = colData(combined)$cluster) %>%
  summarise_all(list(~ mean(.)))
gene_counts_long_combined <-
  t(gene_counts_by_cluster_combined[, -1]) %>%
  as_tibble(rownames = "gene") %>%
  set_names(c("gene", gene_counts_by_cluster_combined[, 1]$cluster))
gene_counts_long_combined

Compute correlations

cor_dt <- cor(gene_counts_long_combined[ , -1])
cor_dt
                          muscs tabula_droplet_macrophage tabula_droplet_muscs tabula_facs_macrophage tabula_facs_muscs
muscs                      1.00                      0.70                 0.85                   0.52              0.78
tabula_droplet_macrophage  0.70                      1.00                 0.84                   0.83              0.69
tabula_droplet_muscs       0.85                      0.84                 1.00                   0.62              0.83
tabula_facs_macrophage     0.52                      0.83                 0.62                   1.00              0.71
tabula_facs_muscs          0.78                      0.69                 0.83                   0.71              1.00
corrplot::corrplot(cor_dt, 
                   order = 'AOE', 
                   type = 'upper', 
                   tl.pos = 'd',
                   tl.cex=.7)
corrplot::corrplot(cor_dt, 
                   add = TRUE, 
                   type = 'lower',
                   method = 'number',
                   order = 'AOE',
                   diag = FALSE, 
                   tl.pos = 'n', 
                   cl.pos = 'n')

comparison across the three datasets

MuSC Tabula Muris droplet vs MuSC experiment droplet

ggplot(
  gene_counts_long_combined,
  aes( x= tabula_droplet_muscs, y = muscs)
) +
  geom_point(
    size = .5,
    alpha = 0.5
  ) +
  geom_text(aes(
    label = gene
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  ) +
  geom_smooth(alpha = 0.2, colour = "grey") +
  coord_fixed(ratio = 1)

MuSCs Tabula Muris droplet vs MuSCs Tabula Muris FACS

ggplot(
  gene_counts_long_combined,
  aes(x = tabula_facs_muscs , y=tabula_droplet_muscs)
) +
  geom_point(
    size = .5,
    alpha = 0.5
  ) +
  geom_text(aes(
    label = gene
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  ) +
  geom_smooth(alpha = 0.2, colour = "grey") +
  coord_fixed(ratio = 1)

Macrophage Tabula Muris droplet vs MuSCs experiment droplet

ggplot(
  gene_counts_long_combined,
  aes(x = tabula_droplet_macrophage , y=muscs)
) +
  geom_point(
    size = .5,
    alpha = 0.5
  ) +
  geom_text(aes(
    label = gene
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  ) +
  geom_smooth(alpha = 0.2, colour = "grey") +
  coord_fixed(ratio = 1)

Macrophage Tabula Muris droplet vs MuSC experiment droplet

ggplot(
  gene_counts_long_combined,
  aes(x = tabula_droplet_macrophage, y = tabula_droplet_muscs)
) +
  geom_point(
    size = .5,
    alpha = 0.5
  ) +
  geom_text(aes(
    label = gene
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  ) +
  geom_smooth(alpha = 0.2, colour = "grey") +
  coord_fixed(ratio = 1)

Macrophage Tabula Muris facs vs MuSC experiment droplet

ggplot(
  gene_counts_long_combined,
  aes(x = tabula_facs_macrophage, y = muscs)
) +
  geom_point(
    size = .5,
    alpha = 0.5
  ) +
  geom_text(aes(
    label = gene
  ),
  check_overlap = TRUE, nudge_y = -0.15, size = 3
  ) +
  geom_smooth(alpha = 0.2, colour = "grey") +
  coord_fixed(ratio = 1)

Plot gene expression

dec.combined <- modelGeneVar(combined[, !(colData(combined)$clusters =="facs_tabula")])

# Visualizing the fit:
fit.combined <- metadata(dec.combined)
plot(fit.combined$mean, fit.combined$var,
  xlab = "Mean of log-expression",
  ylab = "Variance of log-expression"
)
curve(fit.combined$trend(x), col = "dodgerblue", add = TRUE, lwd = 2)

hvg.combined.var <- getTopHVGs(dec.combined, n = 300)
plotHeatmap(combined[, !(colData(combined)$clusters =="facs_tabula")],
  color = colorRampPalette(RColorBrewer::brewer.pal(n = 11, name = "RdBu"))(11),
  features = hvg.combined.var,
  #  cluster_cols=FALSE,
  cluster_rows = TRUE,
  center = TRUE,
  # zlim= c(-3,3),
  order_columns_by = c("cluster", "sum"),
  #  gaps_row = seq(0,5*5,by=5)
)

# plotExpression(combined,
#   features = "Map4k4",
#   x = "cluster",
#   exprs_values = "logcounts",
#   colour_by = "clusters",
#   point_size = 1
# ) +
#   facet_wrap(~ colData(combined)$clusters, ncol = 1)
sessionInfo()
R version 4.1.2 (2021-11-01)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 20.04.3 LTS

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

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    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                  LC_ADDRESS=C               LC_TELEPHONE=C             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] biomaRt_2.48.3              BiocParallel_1.26.2         forcats_0.5.1               stringr_1.4.0               dplyr_1.0.7                 purrr_0.3.4                
 [7] readr_2.0.2                 tidyr_1.1.4                 tibble_3.1.6                tidyverse_1.3.1             SeuratObject_4.0.3          Seurat_4.0.5               
[13] scran_1.20.1                scater_1.20.1               ggplot2_3.3.5               scuttle_1.2.1               SingleCellExperiment_1.14.1 SummarizedExperiment_1.22.0
[19] Biobase_2.52.0              GenomicRanges_1.44.0        GenomeInfoDb_1.28.4         IRanges_2.26.0              S4Vectors_0.30.2            BiocGenerics_0.38.0        
[25] MatrixGenerics_1.4.3        matrixStats_0.61.0         

loaded via a namespace (and not attached):
  [1] utf8_1.2.2                reticulate_1.22           tidyselect_1.1.1          RSQLite_2.2.8             AnnotationDbi_1.54.1      htmlwidgets_1.5.4        
  [7] grid_4.1.2                Rtsne_0.15                munsell_0.5.0             ScaledMatrix_1.0.0        codetools_0.2-18          ica_1.0-2                
 [13] statmod_1.4.36            future_1.23.0             miniUI_0.1.1.1            withr_2.4.2               colorspace_2.0-2          filelock_1.0.2           
 [19] knitr_1.36                rstudioapi_0.13           ROCR_1.0-11               tensor_1.5                listenv_0.8.0             labeling_0.4.2           
 [25] GenomeInfoDbData_1.2.6    polyclip_1.10-0           pheatmap_1.0.12           farver_2.1.0              bit64_4.0.5               rprojroot_2.0.2          
 [31] parallelly_1.28.1         vctrs_0.3.8               generics_0.1.1            xfun_0.28                 BiocFileCache_2.0.0       R6_2.5.1                 
 [37] ggbeeswarm_0.6.0          rsvd_1.0.5                locfit_1.5-9.4            cachem_1.0.6              bitops_1.0-7              spatstat.utils_2.2-0     
 [43] DelayedArray_0.18.0       assertthat_0.2.1          promises_1.2.0.1          scales_1.1.1              beeswarm_0.4.0            gtable_0.3.0             
 [49] beachmat_2.8.1            globals_0.14.0            goftest_1.2-3             rlang_0.4.12              splines_4.1.2             lazyeval_0.2.2           
 [55] spatstat.geom_2.3-0       broom_0.7.10              yaml_2.2.1                reshape2_1.4.4            abind_1.4-5               modelr_0.1.8             
 [61] backports_1.3.0           httpuv_1.6.3              tools_4.1.2               ellipsis_0.3.2            spatstat.core_2.3-1       jquerylib_0.1.4          
 [67] RColorBrewer_1.1-2        ggridges_0.5.3            Rcpp_1.0.7                plyr_1.8.6                progress_1.2.2            sparseMatrixStats_1.4.2  
 [73] zlibbioc_1.38.0           RCurl_1.98-1.5            prettyunits_1.1.1         rpart_4.1-15              deldir_1.0-6              pbapply_1.5-0            
 [79] viridis_0.6.2             cowplot_1.1.1             zoo_1.8-9                 haven_2.4.3               ggrepel_0.9.1             cluster_2.1.2            
 [85] fs_1.5.0                  magrittr_2.0.1            data.table_1.14.2         scattermore_0.7           lmtest_0.9-39             reprex_2.0.1             
 [91] RANN_2.6.1                fitdistrplus_1.1-6        hms_1.1.1                 patchwork_1.1.1           mime_0.12                 evaluate_0.14            
 [97] xtable_1.8-4              XML_3.99-0.8              readxl_1.3.1              gridExtra_2.3             compiler_4.1.2            KernSmooth_2.23-20       
[103] crayon_1.4.2              htmltools_0.5.2           mgcv_1.8-38               later_1.3.0               tzdb_0.2.0                lubridate_1.8.0          
[109] DBI_1.1.1                 corrplot_0.92             dbplyr_2.1.1              rappdirs_0.3.3            MASS_7.3-54               Matrix_1.3-4             
[115] cli_3.1.0                 metapod_1.0.0             igraph_1.2.8              pkgconfig_2.0.3           plotly_4.10.0             spatstat.sparse_2.0-0    
[121] xml2_1.3.2                vipor_0.4.5               bslib_0.3.1               dqrng_0.3.0               XVector_0.32.0            rvest_1.0.2              
[127] digest_0.6.28             sctransform_0.3.2         RcppAnnoy_0.0.19          Biostrings_2.60.2         spatstat.data_2.1-0       rmarkdown_2.11           
[133] cellranger_1.1.0          leiden_0.3.9              uwot_0.1.10               edgeR_3.34.1              DelayedMatrixStats_1.14.3 curl_4.3.2               
[139] shiny_1.7.1               lifecycle_1.0.1           nlme_3.1-152              jsonlite_1.7.2            BiocNeighbors_1.10.0      viridisLite_0.4.0        
[145] limma_3.48.3              fansi_0.5.0               pillar_1.6.4              lattice_0.20-45           KEGGREST_1.32.0           fastmap_1.1.0            
[151] httr_1.4.2                survival_3.2-13           glue_1.5.0                png_0.1-7                 bit_4.0.4                 bluster_1.2.1            
[157] stringi_1.7.5             sass_0.4.0                blob_1.2.2                BiocSingular_1.8.1        memoise_2.0.0             irlba_2.3.3              
[163] future.apply_1.8.1       
LS0tCnRpdGxlOiAiTW91c2UgTXVzY2xlIFN0ZW0gQ2VsbCBQcm9qZWN0ICIKc3VidGl0bGU6ICJUYWJ1bGEgTXVyaXMgYW5hbHlzaXMgb24gc3RlbSBjZWxscyIKYXV0aG9yOiAKLSBuYW1lOiBSaWNrIEZhcm91bmkKICBhZmZpbGlhdGlvbjoKICAtICZjcnVrIEfDqW5vbWUgUXXDqWJlYyBJbm5vdmF0aW9uIENlbnRyZSwgTWNHaWxsIFVuaXZlcnNpdHksIE1vbnRyZWFsLCBDYW5hZGEKZGF0ZTogJ2ByIGZvcm1hdChTeXMuRGF0ZSgpLCAiJVktJUItJWQiKWAnCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIHRvYzogbm8KICAgIHRvY19mbG9hdDogCiAgICAgIGNvbGxhcHNlZDogZmFsc2UKICAgICAgc21vb3RoX3Njcm9sbDogZmFsc2UKLS0tCgoKIyBQcmVwYXJlIGFuYWx5c2lzIHdvcmtmbG93CgojIyBTZXQgZmlsZXBhdGhzIGFuZCBwYXJhbWV0ZXJzCgpgYGB7ciBzZXR1cH0Kc2V0LnNlZWQoNDIpCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gcnByb2pyb290OjpmaW5kX3JzdHVkaW9fcm9vdF9maWxlKCkpCm9wdGlvbnMoCiAgcmVhZHIuc2hvd19wcm9ncmVzcyA9IEZBTFNFLAogIGRpZ2l0cyA9IDIKKQpgYGAKCiMjIExvYWQgcGFja2FnZXMKYGBge3J9CnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyh7CiAgbGlicmFyeShzY2F0ZXIpCiAgbGlicmFyeShzY3JhbikKICBsaWJyYXJ5KFNldXJhdCkKICBsaWJyYXJ5KHRpZHl2ZXJzZSkKICBsaWJyYXJ5KEJpb2NQYXJhbGxlbCkKICBsaWJyYXJ5KGJpb21hUnQpCiAgdGhlbWVfc2V0KHRoZW1lX2J3KCkpCn0pCmBgYAoKCiMjIEhlbHBlciBmdW5jdGlvbnMKCmBgYHtyfQpnZXRfY291bnRzX3N0YXRzIDwtIGZ1bmN0aW9uKHNjZTEweF9zdGVtLCBjbHVzdGVyX3RvX3JlbW92ZSkgewogIGdlbmVfY291bnRzX2J5X2NsdXN0ZXIgPC0KICAgIHQoYXNzYXkoc2NlMTB4X3N0ZW0pKSAlPiUKICAgIGFzLm1hdHJpeCgpICU+JQogICAgYXNfdGliYmxlKCkgJT4lCiAgICBncm91cF9ieShjbHVzdGVyID0gY29sRGF0YShzY2UxMHhfc3RlbSkkY2x1c3Rlcl9jb25kaXRpb24pICU+JQogICAgc3VtbWFyaXNlX2FsbChsaXN0KH4gbWVhbiguKSkpCgogIHVtaV9jb3VudHNfbWF4XzEgPC0KICAgIGdlbmVfY291bnRzX2J5X2NsdXN0ZXJbYygyLCA0LCA1KSwgLTFdICU+JQogICAgc3VtbWFyaXplX2FsbChsaXN0KH4gbWF4KC4pKSkgJT4lCiAgICBtdXRhdGUoZHVtbXkgPSAiZHVtbXkiKSAlPiUKICAgIHBpdm90X2xvbmdlcigtZHVtbXksIG5hbWVzX3RvID0gImdlbmVfbmFtZSIsIHZhbHVlc190byA9ICJtYXhfeW5nIikgJT4lCiAgICBzZWxlY3QoLWR1bW15KQoKICB1bWlfY291bnRzX21heF8yIDwtCiAgICBnZW5lX2NvdW50c19ieV9jbHVzdGVyWy01LCAtMV0gJT4lCiAgICBzdW1tYXJpemVfYWxsKGxpc3QofiBtYXgoLikpKSAlPiUKICAgIG11dGF0ZShkdW1teSA9ICJkdW1teSIpICU+JQogICAgcGl2b3RfbG9uZ2VyKC1kdW1teSwgbmFtZXNfdG8gPSAiZ2VuZV9uYW1lIiwgdmFsdWVzX3RvID0gIm1heF9zdGVtMTIiKSAlPiUKICAgIHNlbGVjdCgtZHVtbXksIC1nZW5lX25hbWUpCgogIHN0YXRzIDwtCiAgICBwZXJGZWF0dXJlUUNNZXRyaWNzKHNjZTEweF9zdGVtLAogICAgICBleHByc192YWx1ZXMgPSBjKCJjb3VudHMiKSwKICAgICAgZmxhdHRlbiA9IFRSVUUKICAgICkgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIGJpbmRfY29scyguLCByb3dEYXRhKHNjZTEweF9zdGVtKSAlPiUKICAgICAgYXNfdGliYmxlKCkpICU+JQogICAgYmluZF9jb2xzKC4sIHVtaV9jb3VudHNfbWF4XzEsIHVtaV9jb3VudHNfbWF4XzIpCgogIHJldHVybihzdGF0cykKfQoKZ2V0X2xmYyA8LSBmdW5jdGlvbihjb250cmFzdCwgbmFtZSwgZGRzKSB7CiAgbGZjU2hyaW5rKGRkcywKICAgIGNvbnRyYXN0ID0gY29udHJhc3QsCiAgICB0eXBlID0gImFzaHIiLAogICAgc3ZhbHVlID0gVAogICkgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoLWJhc2VNZWFuKSAlPiUKICAgIG11dGF0ZShzdmFsdWUgPSBhYnMoc3ZhbHVlKSkgJT4lCiAgICBzZXRfbmFtZXMocGFzdGUoYygibGZjIiwgImxmY19zZSIsICJzdmFsdWUiKSwgbmFtZSwgc2VwID0gIl8iKSkKfQoKcGxvdF9leHByZXNzaW9uIDwtIGZ1bmN0aW9uKGdlbmUsIGRhdGEpIHsKICBwbG90RXhwcmVzc2lvbihkYXRhLAogICAgZmVhdHVyZXMgPSBnZW5lLAogICAgeCA9ICJzYW1wbGUiLAogICAgZXhwcnNfdmFsdWVzID0gImxvZ2NvdW50cyIsCiAgICBjb2xvdXJfYnkgPSAiY29uZGl0aW9uIiwKICAgIHBvaW50X3NpemUgPSAxCiAgKSArCiAgICBmYWNldF93cmFwKH4gY29sRGF0YShkYXRhKSRjbHVzdGVycywgbmNvbCA9IDEpCn0KYGBgCgoKIyMgRGVmaW5lIGZpbGUgcGF0aHMKCmBgYHtyfQpkYXRhX2RpciA8LSAiLi9kYXRhIgpmaWd1cmVzX2RpciA8LSBmaWxlLnBhdGgoIi4vZmlndXJlcyIpCmBgYAoKIyBBbmFseXNpcyBhbmQgcGxvdHMKCiMjIEV4cGVyaW1lbnQgRGF0YQoKCiMjIyBsb2FkIG11c2NsZSBzYXRlbGxpdGUgY2VsbHMKCgpgYGB7cn0Kc2NlMTB4IDwtCiAgcmVhZFJEUyhmaWxlLnBhdGgoCiAgICBkYXRhX2RpciwKICAgICJwcmVwcm9jZXNzZWQiLAogICAgInNjZTEweF9maWx0ZXJlZF9maW5hbC5yZHMiCiAgKSkKYGBgCgoKYGBge3J9CnNjZTEweF9zdGVtIDwtIHNjZTEweFssIGNvbERhdGEoc2NlMTB4KSRjZWxsX3R5cGUgPT0gInN0ZW0iXQpjb2xEYXRhKHNjZTEweF9zdGVtKSA8LSBjb2xEYXRhKHNjZTEweF9zdGVtKVssIGMoInN1bSIsICJkZXRlY3RlZCIsICJzYW1wbGUiLCAiY2x1c3RlcnMiLCAiY2x1c3Rlcl9jb25kaXRpb24iLCAiY29uZGl0aW9uIildCmFzc2F5KHNjZTEweF9zdGVtLCAyKSA8LSBOVUxMCmFzc2F5KHNjZTEweF9zdGVtLCAyKSA8LSBOVUxMCmFzc2F5KHNjZTEweF9zdGVtLCAzKSA8LSBOVUxMCmFzc2F5KHNjZTEweF9zdGVtLCAzKSA8LSBOVUxMCnJlZHVjZWREaW1zKHNjZTEweF9zdGVtKSA8LSBOVUxMCnJlZHVjZWREaW1zKHNjZTEweF9zdGVtKSA8LSBOVUxMCmNvbERhdGEoc2NlMTB4X3N0ZW0pJGNsdXN0ZXIgPC0gIm11c2NzIgpjb2xEYXRhKHNjZTEweF9zdGVtKSA8LSBjb2xEYXRhKHNjZTEweF9zdGVtKVssIGMoMSwgMiwgMywgNywgNSwgNiwgNCldCnJtKHNjZTEweCkKYGBgCgoKYGBge3J9CnRhYmxlKGNvbERhdGEoc2NlMTB4X3N0ZW0pJGNsdXN0ZXJzLCBjb2xEYXRhKHNjZTEweF9zdGVtKSRzYW1wbGUpCmBgYAoKIyMjIERpc2NhcmQgZ2VuZXMgbm90IGV4cHJlc3NlZCBpbiBhdCBsZWFzdCAxMCBjZWxscwoKYGBge3J9Cm5fZXhwcnNfZ2VuZXMgPC0KICBuZXhwcnMoc2NlMTB4X3N0ZW0sCiAgICBkZXRlY3Rpb25fbGltaXQgPSAwLAogICAgYnlyb3cgPSBUUlVFCiAgKQprZWVwIDwtIG5fZXhwcnNfZ2VuZXMgPj0gMTAKdGFibGUoa2VlcCkKYGBgCgpgYGB7cn0Kc2NlMTB4X3N0ZW0gPC0gc2NlMTB4X3N0ZW1ba2VlcCwgXQpgYGAKCgoKIyMjIENvbXB1dGUgdGhlIG1lYW4gbG9nIG5vcm1hbGl6ZWQgY291bnRzIGZvciBlYWNoIGNsdXN0ZXIKCgpgYGB7cn0KZ2VuZV9jb3VudHNfYnlfY2x1c3RlciA8LQogIHQoYXNzYXkoc2NlMTB4X3N0ZW0sICJsb2djb3VudHMiKSkgJT4lCiAgYXMubWF0cml4KCkgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgZ3JvdXBfYnkoY2x1c3RlciA9IGNvbERhdGEoc2NlMTB4X3N0ZW0pJGNsdXN0ZXJfY29uZGl0aW9uKSAlPiUKICBzdW1tYXJpc2VfYWxsKGxpc3QofiBtZWFuKC4pKSkKZ2VuZV9jb3VudHNfbG9uZyA8LQogIHQoZ2VuZV9jb3VudHNfYnlfY2x1c3RlclssIC0xXSkgJT4lCiAgYXNfdGliYmxlKHJvd25hbWVzID0gImdlbmUiKSAlPiUKICBzZXRfbmFtZXMoYygiZ2VuZSIsIGdlbmVfY291bnRzX2J5X2NsdXN0ZXJbLCAxXSRjbHVzdGVyKSkKZ2VuZV9jb3VudHNfbG9uZwpgYGAKCgpgYGB7ciBmaWcud2lkdGg9MTIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmdncGxvdCgKICBnZW5lX2NvdW50c19sb25nLAogIGFlcyh4ID0gc3RlbTFfeW5nLCB5ID0gc3RlbTJfeW5nKQopICsKICBnZW9tX3BvaW50KAogICAgc2l6ZSA9IC41LAogICAgYWxwaGEgPSAwLjUKICApICsKICBnZW9tX3RleHQoYWVzKAogICAgbGFiZWwgPSBnZW5lCiAgKSwKICBjaGVja19vdmVybGFwID0gVFJVRSwgbnVkZ2VfeSA9IC0wLjE1LCBzaXplID0gMwogICkgKwogIGdlb21fc21vb3RoKGFscGhhID0gMC4yLCBjb2xvdXIgPSAiZ3JleSIpICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpCmBgYAoKYGBge3IgZmlnLndpZHRoPTEyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZ3Bsb3QoCiAgZ2VuZV9jb3VudHNfbG9uZywKICBhZXMoeCA9IHN0ZW0xX2FnZWQsIHkgPSBzdGVtMl9hZ2VkKQopICsKICBnZW9tX3BvaW50KAogICAgc2l6ZSA9IC41LAogICAgYWxwaGEgPSAwLjUKICApICsKICBnZW9tX3RleHQoYWVzKAogICAgbGFiZWwgPSBnZW5lCiAgKSwKICBjaGVja19vdmVybGFwID0gVFJVRSwgbnVkZ2VfeSA9IC0wLjE1LCBzaXplID0gMwogICkgKwogIGdlb21fc21vb3RoKGFscGhhID0gMC4yLCBjb2xvdXIgPSAiZ3JleSIpICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpCmBgYAoKYGBge3IgZmlnLndpZHRoPTEyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZ3Bsb3QoCiAgZ2VuZV9jb3VudHNfbG9uZywKICBhZXMoeCA9IHN0ZW0xX3luZywgeSA9IHN0ZW0xX2FnZWQpCikgKwogIGdlb21fcG9pbnQoCiAgICBzaXplID0gLjUsCiAgICBhbHBoYSA9IDAuNQogICkgKwogIGdlb21fdGV4dChhZXMoCiAgICBsYWJlbCA9IGdlbmUKICApLAogIGNoZWNrX292ZXJsYXAgPSBUUlVFLCBudWRnZV95ID0gLTAuMTUsIHNpemUgPSAzCiAgKSArCiAgZ2VvbV9zbW9vdGgoYWxwaGEgPSAwLjIsIGNvbG91ciA9ICJncmV5IikgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkKYGBgCgoKYGBge3IgZmlnLndpZHRoPTEyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZ3Bsb3QoCiAgZ2VuZV9jb3VudHNfbG9uZywKICBhZXMoeCA9IHN0ZW0yX3luZywgeSA9IHN0ZW0yX2FnZWQpCikgKwogIGdlb21fcG9pbnQoCiAgICBzaXplID0gLjUsCiAgICBhbHBoYSA9IDAuNQogICkgKwogIGdlb21fdGV4dChhZXMoCiAgICBsYWJlbCA9IGdlbmUKICApLAogIGNoZWNrX292ZXJsYXAgPSBUUlVFLCBudWRnZV95ID0gLTAuMTUsIHNpemUgPSAzCiAgKSArCiAgZ2VvbV9zbW9vdGgoYWxwaGEgPSAwLjIsIGNvbG91ciA9ICJncmV5IikgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkKYGBgCgoKCmBgYHtyIGZpZy53aWR0aD0xMiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZ2dwbG90KAogIGdlbmVfY291bnRzX2xvbmcsCiAgYWVzKHggPSBzdGVtMV95bmcsIHkgPSBzdGVtM195bmcpCikgKwogIGdlb21fcG9pbnQoCiAgICBzaXplID0gLjUsCiAgICBhbHBoYSA9IDAuNQogICkgKwogIGdlb21fdGV4dChhZXMoCiAgICBsYWJlbCA9IGdlbmUKICApLAogIGNoZWNrX292ZXJsYXAgPSBUUlVFLCBudWRnZV95ID0gLTAuMTUsIHNpemUgPSAzCiAgKSArCiAgZ2VvbV9zbW9vdGgoYWxwaGEgPSAwLjIsIGNvbG91ciA9ICJncmV5IikgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkKYGBgCgoKYGBge3IgZmlnLndpZHRoPTEyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZ3Bsb3QoCiAgZ2VuZV9jb3VudHNfbG9uZywKICBhZXMoeCA9IHN0ZW0xX3luZywgeSA9IHN0ZW0zX3luZykKKSArCiAgZ2VvbV9wb2ludCgKICAgIHNpemUgPSAuNSwKICAgIGFscGhhID0gMC41CiAgKSArCiAgZ2VvbV90ZXh0KGFlcygKICAgIGxhYmVsID0gZ2VuZQogICksCiAgY2hlY2tfb3ZlcmxhcCA9IFRSVUUsIG51ZGdlX3kgPSAtMC4xNSwgc2l6ZSA9IDMKICApICsKICBnZW9tX3Ntb290aChhbHBoYSA9IDAuMiwgY29sb3VyID0gImdyZXkiKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKQpgYGAKCgpgYGB7ciBmaWcud2lkdGg9MTIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmdncGxvdCgKICBnZW5lX2NvdW50c19sb25nLAogIGFlcyh4ID0gc3RlbTJfeW5nLCB5ID0gc3RlbTNfeW5nKQopICsKICBnZW9tX3BvaW50KAogICAgc2l6ZSA9IC41LAogICAgYWxwaGEgPSAwLjUKICApICsKICBnZW9tX3RleHQoYWVzKAogICAgbGFiZWwgPSBnZW5lCiAgKSwKICBjaGVja19vdmVybGFwID0gVFJVRSwgbnVkZ2VfeSA9IC0wLjE1LCBzaXplID0gMwogICkgKwogIGdlb21fc21vb3RoKGFscGhhID0gMC4yLCBjb2xvdXIgPSAiZ3JleSIpICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpCmBgYAoKIyMgVGFidWxhIE11cmlzIERhdGEKCgojIyMgbG9hZCBUYWJ1bGEgTXVyaXMgZGF0YQoKYGBge3J9CmxvYWQoZmlsZS5wYXRoKAogIGRhdGFfZGlyLAogICJ0YWJ1bGFfbXVyaXMiLAogICJmYWNzX0xpbWJfTXVzY2xlX3NldXJhdF90aXNzLlJvYmoiCikpCmZhY3NfbGltYl9tdXNjbGVfdGFidWxhIDwtIHRpc3MKcm0odGlzcykKZmFjc19saW1iX211c2NsZV90YWJ1bGEgPC0gVXBkYXRlU2V1cmF0T2JqZWN0KGZhY3NfbGltYl9tdXNjbGVfdGFidWxhKQpmYWNzX2xpbWJfbXVzY2xlX3RhYnVsYSA8LSBhcy5TaW5nbGVDZWxsRXhwZXJpbWVudChmYWNzX2xpbWJfbXVzY2xlX3RhYnVsYSkKZmFjc19saW1iX211c2NsZV90YWJ1bGEKYGBgCgpgYGB7cn0KbG9hZChmaWxlLnBhdGgoCiAgZGF0YV9kaXIsCiAgInRhYnVsYV9tdXJpcyIsCiAgImRyb3BsZXRfTGltYl9NdXNjbGVfc2V1cmF0X3Rpc3MuUm9iaiIKKSkKCmRyb3BsZXRfbGltYl9tdXNjbGVfdGFidWxhIDwtIHRpc3MKcm0odGlzcykKZHJvcGxldF9saW1iX211c2NsZV90YWJ1bGEgPC0gVXBkYXRlU2V1cmF0T2JqZWN0KGRyb3BsZXRfbGltYl9tdXNjbGVfdGFidWxhKQpkcm9wbGV0X2xpbWJfbXVzY2xlX3RhYnVsYSA8LSBhcy5TaW5nbGVDZWxsRXhwZXJpbWVudChkcm9wbGV0X2xpbWJfbXVzY2xlX3RhYnVsYSkKZHJvcGxldF9saW1iX211c2NsZV90YWJ1bGEKYGBgCgojIyMgS2VlcCBtdXNjbGUgc2F0ZWxsaXRlIGFuZCBtYWNyb3BoYWdlIGNlbGxzCgpgYGB7cn0KIyB0YXJnZXRfY2VsbF90eXBlcyA8LSBjKCJtZXNlbmNoeW1hbCBzdGVtIGNlbGwiLCAic2tlbGV0YWwgbXVzY2xlIHNhdGVsbGl0ZSBjZWxsIiAsImVuZG90aGVsaWFsIGNlbGwiLCAibWFjcm9waGFnZSIpCnRhcmdldF9jZWxsX3R5cGVzIDwtIGMoInNrZWxldGFsIG11c2NsZSBzYXRlbGxpdGUgY2VsbCIsICJtYWNyb3BoYWdlIikKZmFjc19saW1iX211c2NsZV90YWJ1bGEgPC0gZmFjc19saW1iX211c2NsZV90YWJ1bGFbLCBjb2xEYXRhKGZhY3NfbGltYl9tdXNjbGVfdGFidWxhKSRjZWxsX29udG9sb2d5X2NsYXNzICVpbiUgdGFyZ2V0X2NlbGxfdHlwZXNdCmRyb3BsZXRfbGltYl9tdXNjbGVfdGFidWxhIDwtIGRyb3BsZXRfbGltYl9tdXNjbGVfdGFidWxhWywgY29sRGF0YShkcm9wbGV0X2xpbWJfbXVzY2xlX3RhYnVsYSkkY2VsbF9vbnRvbG9neV9jbGFzcyAlaW4lIHRhcmdldF9jZWxsX3R5cGVzXQpgYGAKCgojIyMgUHJvY2VzcyBhbmQgY29tYmluZSBkYXRhIGZyb20gZmFjcyBhbmQgZHJvcGxldCBleHBlcmltZW50cyAKCmBgYHtyfQpkcm9wbGV0X2NvbGRhdGEgPC0gY29sRGF0YShkcm9wbGV0X2xpbWJfbXVzY2xlX3RhYnVsYSlbYygibkNvdW50X1JOQSIsICJuRmVhdHVyZV9STkEiLCAibW91c2UuaWQiLCAiY2VsbF9vbnRvbG9neV9jbGFzcyIsICJjbHVzdGVyLmlkcyIpXQpkcm9wbGV0X2NvbGRhdGEkY29uZGl0aW9uIDwtICJtaWQtYWdlZCIKY29sbmFtZXMoZHJvcGxldF9jb2xkYXRhKSA8LSBjKCJzdW0iLCAiZGV0ZWN0ZWQiLCAic2FtcGxlIiwgImNsdXN0ZXIiLCAiY2x1c3Rlcl9jb25kaXRpb24iLCAiY29uZGl0aW9uIikKY29sRGF0YShkcm9wbGV0X2xpbWJfbXVzY2xlX3RhYnVsYSkgPC0gZHJvcGxldF9jb2xkYXRhCmNvbERhdGEoZHJvcGxldF9saW1iX211c2NsZV90YWJ1bGEpCmBgYAoKYGBge3J9CmZhY3NfY29sZGF0YSA8LSBjb2xEYXRhKGZhY3NfbGltYl9tdXNjbGVfdGFidWxhKVtjKCJuQ291bnRfUk5BIiwgIm5GZWF0dXJlX1JOQSIsICJtb3VzZS5pZCIsICJjZWxsX29udG9sb2d5X2NsYXNzIiwgImNsdXN0ZXIuaWRzIildCmZhY3NfY29sZGF0YSRjb25kaXRpb24gPC0gIm1pZC1hZ2VkIgpjb2xuYW1lcyhmYWNzX2NvbGRhdGEpIDwtIGMoInN1bSIsICJkZXRlY3RlZCIsICJzYW1wbGUiLCAiY2x1c3RlciIsICJjbHVzdGVyX2NvbmRpdGlvbiIsICJjb25kaXRpb24iKQpjb2xEYXRhKGZhY3NfbGltYl9tdXNjbGVfdGFidWxhKSA8LSBmYWNzX2NvbGRhdGEKY29sRGF0YShmYWNzX2xpbWJfbXVzY2xlX3RhYnVsYSkKYGBgCgpgYGB7cn0KcmVkdWNlZERpbShkcm9wbGV0X2xpbWJfbXVzY2xlX3RhYnVsYSkgPC0gTlVMTApyZWR1Y2VkRGltKGZhY3NfbGltYl9tdXNjbGVfdGFidWxhKSA8LSBOVUxMCnJlZHVjZWREaW0oZHJvcGxldF9saW1iX211c2NsZV90YWJ1bGEpIDwtIE5VTEwKcmVkdWNlZERpbShmYWNzX2xpbWJfbXVzY2xlX3RhYnVsYSkgPC0gTlVMTAphc3NheShkcm9wbGV0X2xpbWJfbXVzY2xlX3RhYnVsYSwgMykgPC0gTlVMTAphc3NheShmYWNzX2xpbWJfbXVzY2xlX3RhYnVsYSwgMykgPC0gTlVMTApgYGAKCmBgYHtyfQpjb2xEYXRhKGRyb3BsZXRfbGltYl9tdXNjbGVfdGFidWxhKSRjbHVzdGVyIDwtCiAgY2FzZV93aGVuKAogICAgY29sRGF0YShkcm9wbGV0X2xpbWJfbXVzY2xlX3RhYnVsYSkkY2x1c3RlciA9PSAibWFjcm9waGFnZSIgfiAidGFidWxhX2Ryb3BsZXRfbWFjcm9waGFnZSIsCiAgICBjb2xEYXRhKGRyb3BsZXRfbGltYl9tdXNjbGVfdGFidWxhKSRjbHVzdGVyID09ICJza2VsZXRhbCBtdXNjbGUgc2F0ZWxsaXRlIGNlbGwiIH4gInRhYnVsYV9kcm9wbGV0X211c2NzIgogICkKCmNvbERhdGEoZmFjc19saW1iX211c2NsZV90YWJ1bGEpJGNsdXN0ZXIgPC0KICBjYXNlX3doZW4oCiAgICBjb2xEYXRhKGZhY3NfbGltYl9tdXNjbGVfdGFidWxhKSRjbHVzdGVyID09ICJtYWNyb3BoYWdlIiB+ICJ0YWJ1bGFfZmFjc19tYWNyb3BoYWdlIiwKICAgIGNvbERhdGEoZmFjc19saW1iX211c2NsZV90YWJ1bGEpJGNsdXN0ZXIgPT0gInNrZWxldGFsIG11c2NsZSBzYXRlbGxpdGUgY2VsbCIgfiAidGFidWxhX2ZhY3NfbXVzY3MiCiAgKQoKY29sRGF0YShkcm9wbGV0X2xpbWJfbXVzY2xlX3RhYnVsYSkkY2x1c3Rlcl9jb25kaXRpb24gPC0gCiAgcGFzdGUoY29sRGF0YShkcm9wbGV0X2xpbWJfbXVzY2xlX3RhYnVsYSkkY2x1c3RlciwgCiAgICAgICAgY29sRGF0YShkcm9wbGV0X2xpbWJfbXVzY2xlX3RhYnVsYSkkY2x1c3Rlcl9jb25kaXRpb24sIHNlcCA9ICJfIikKY29sRGF0YShmYWNzX2xpbWJfbXVzY2xlX3RhYnVsYSkkY2x1c3Rlcl9jb25kaXRpb24gPC0gCiAgcGFzdGUoY29sRGF0YShmYWNzX2xpbWJfbXVzY2xlX3RhYnVsYSkkY2x1c3RlciwgCiAgICAgICAgY29sRGF0YShmYWNzX2xpbWJfbXVzY2xlX3RhYnVsYSkkY2x1c3Rlcl9jb25kaXRpb24sIHNlcCA9ICJfIikKY29sRGF0YShmYWNzX2xpbWJfbXVzY2xlX3RhYnVsYSkkY2x1c3RlcnMgPC0gImZhY3NfdGFidWxhIgpjb2xEYXRhKGRyb3BsZXRfbGltYl9tdXNjbGVfdGFidWxhKSRjbHVzdGVycyA8LSAiZHJvcGxldF90YWJ1bGEiCmBgYAoKYGBge3J9CmRyb3BsZXRfbGltYl9tdXNjbGVfdGFidWxhIDwtIGRyb3BsZXRfbGltYl9tdXNjbGVfdGFidWxhW3Jvd25hbWVzKGZhY3NfbGltYl9tdXNjbGVfdGFidWxhKSwgXQp0YWJ1bGFfbXVyaXMgPC0gY2JpbmQoZHJvcGxldF9saW1iX211c2NsZV90YWJ1bGEsIGZhY3NfbGltYl9tdXNjbGVfdGFidWxhKQojIHRhYnVsYV9tdXJpcyA8LSBkcm9wbGV0X2xpbWJfbXVzY2xlX3RhYnVsYQp0YWJ1bGFfbXVyaXMKYGBgCiMjIyBEaXNjYXJkIGdlbmVzIG5vdCBleHByZXNzZWQgaW4gYXQgbGVhc3QgMTAgY2VsbHMKCmBgYHtyfQpuX2V4cHJzX2dlbmVzIDwtCiAgbmV4cHJzKHRhYnVsYV9tdXJpcywKICAgIGRldGVjdGlvbl9saW1pdCA9IDAsCiAgICBieXJvdyA9IFRSVUUKICApCmtlZXAgPC0gbl9leHByc19nZW5lcyA+PSAxMAp0YWJsZShrZWVwKQpgYGAKCmBgYHtyfQp0YWJ1bGFfbXVyaXMgPC0gdGFidWxhX211cmlzW2tlZXAsIF0KYGBgCgojIyMgTWFwIGdlbmUgbmFtZXMgdG8gRU5TRU1CTCBnZW5lIElEUwoKYGBge3J9CmVuc2VtYmw5MyA8LSB1c2VFbnNlbWJsKAogIGJpb21hcnQgPSAiZ2VuZXMiLAogIGRhdGFzZXQgPSAibW11c2N1bHVzX2dlbmVfZW5zZW1ibCIsCiAgdmVyc2lvbiA9IDkzCikKbWFydCA8LQogIHVzZURhdGFzZXQoCiAgICAibW11c2N1bHVzX2dlbmVfZW5zZW1ibCIsCiAgICBlbnNlbWJsOTMKICApICMgZnJvbSAyMDE4CgpnZW5lX21ldGFkYXRhIDwtCiAgZ2V0Qk0oCiAgICBmaWx0ZXJzID0gImV4dGVybmFsX2dlbmVfbmFtZSIsCiAgICBhdHRyaWJ1dGVzID0gYygKICAgICAgImVuc2VtYmxfZ2VuZV9pZF92ZXJzaW9uIiwKICAgICAgImV4dGVybmFsX2dlbmVfbmFtZSIsCiAgICAgICJnZW5lX2Jpb3R5cGUiLAogICAgICAiY2hyb21vc29tZV9uYW1lIiwKICAgICAgImRlc2NyaXB0aW9uIgogICAgKSwKICAgIHZhbHVlcyA9IHJvd25hbWVzKHRhYnVsYV9tdXJpcyksCiAgICBtYXJ0ID0gbWFydAogICkKYGBgCgoKYGBge3J9CmNocl90b19rZWVwIDwtIGMoc2VxKDEsIDE5KSwgIk1UIiwgIlgiLCAiWSIpCmdlbmVfbWV0YWRhdGEgPC0KICBnZW5lX21ldGFkYXRhICU+JQogIGZpbHRlcihjaHJvbW9zb21lX25hbWUgJWluJSBjaHJfdG9fa2VlcCkgJT4lCiAgZmlsdGVyKCFkdXBsaWNhdGVkKGV4dGVybmFsX2dlbmVfbmFtZSkpCgpnZW5lX21ldGFkYXRhIDwtCiAgZ2VuZV9tZXRhZGF0YSAlPiUKICBsZWZ0X2pvaW4odGliYmxlKGV4dGVybmFsX2dlbmVfbmFtZSA9IHJvd25hbWVzKHRhYnVsYV9tdXJpcykpLAogICAgLiwKICAgIGJ5ID0gImV4dGVybmFsX2dlbmVfbmFtZSIKICApICU+JQogIGRwbHlyOjpyZW5hbWUoY2hyID0gImNocm9tb3NvbWVfbmFtZSIpCnJvd0RhdGEodGFidWxhX211cmlzKSA8LSBnZW5lX21ldGFkYXRhCmBgYAoKCiMjIyBEaXNjYXJkIGdlbmVzIG5vdCBpbiBzdGFuZGFyZCBjaHJvbW9zb21lcyBhbmQgdGhvc2Ugd2l0aCBkdXBsaWNhdGUgaWRzIAoKYGBge3J9CnRhYnVsYV9tdXJpc19maWx0ZXJlZCA8LSB0YWJ1bGFfbXVyaXNbIWlzLm5hKHJvd0RhdGEodGFidWxhX211cmlzKSRlbnNlbWJsX2dlbmVfaWRfdmVyc2lvbiksIF0KdGFidWxhX211cmlzX2ZpbHRlcmVkCmBgYAoKYGBge3J9CnRhYmxlKGNvbERhdGEodGFidWxhX211cmlzX2ZpbHRlcmVkKSRjbHVzdGVyKQpgYGAKCgpgYGB7cn0KIyBnZW5lX2NvdW50c19ieV9jbHVzdGVyX3RhYnVsYV9tdXJpcyA8LQojICAgdChhc3NheSh0YWJ1bGFfbXVyaXNfZmlsdGVyZWQsICJsb2djb3VudHMiKSkgJT4lCiMgICBhcy5tYXRyaXgoKSAlPiUKIyAgIGFzX3RpYmJsZSgpICU+JQojICAgZ3JvdXBfYnkoY2x1c3RlciA9IGNvbERhdGEodGFidWxhX211cmlzX2ZpbHRlcmVkKSRjbHVzdGVyKSAlPiUKIyAgIHN1bW1hcmlzZV9hbGwobGlzdCh+IG1lYW4oLikpKQojIGdlbmVfY291bnRzX2xvbmdfdGFidWxhX211cmlzIDwtCiMgICB0KGdlbmVfY291bnRzX2J5X2NsdXN0ZXJfdGFidWxhX211cmlzWywgLTFdKSAlPiUKIyAgIGFzX3RpYmJsZShyb3duYW1lcyA9ICJnZW5lIikgJT4lCiMgICBzZXRfbmFtZXMoYygiZ2VuZSIsIGdlbmVfY291bnRzX2J5X2NsdXN0ZXJfdGFidWxhX211cmlzWywgMV0kY2x1c3RlcikpCiMgZ2VuZV9jb3VudHNfbG9uZ190YWJ1bGFfbXVyaXMKYGBgCgoKCiMjIENvbWJpbmVkIERhdGEKCgojIyMgSm9pbiBkYXRhIHVzaW5nIGNvbW1vbiBnZW5lcyBvbmx5CgpgYGB7cn0KY29tbW1vbl9nZW5lcyA8LSAKICBpbnRlcnNlY3Qocm93RGF0YShzY2UxMHhfc3RlbSkkZW5zZW1ibF9nZW5lX2lkX3ZlcnNpb24sIAogICAgICAgICAgICByb3dEYXRhKHRhYnVsYV9tdXJpc19maWx0ZXJlZCkkZW5zZW1ibF9nZW5lX2lkX3ZlcnNpb24pCnNjZTEweF9zdGVtX2ZpbHRlcmVkIDwtIHNjZTEweF9zdGVtCnJvd0RhdGEoc2NlMTB4X3N0ZW1fZmlsdGVyZWQpIDwtIHJvd0RhdGEoc2NlMTB4X3N0ZW1fZmlsdGVyZWQpWywgYygyLCAxLCAzLCA0LCA1KV0Kcm93bmFtZXMoc2NlMTB4X3N0ZW1fZmlsdGVyZWQpIDwtIHJvd0RhdGEoc2NlMTB4X3N0ZW0pJGVuc2VtYmxfZ2VuZV9pZF92ZXJzaW9uCnJvd25hbWVzKHRhYnVsYV9tdXJpc19maWx0ZXJlZCkgPC0gcm93RGF0YSh0YWJ1bGFfbXVyaXNfZmlsdGVyZWQpJGVuc2VtYmxfZ2VuZV9pZF92ZXJzaW9uCnNjZTEweF9zdGVtX2ZpbHRlcmVkIDwtIHNjZTEweF9zdGVtX2ZpbHRlcmVkW2NvbW1tb25fZ2VuZXMsIF0KdGFidWxhX211cmlzX2ZpbHRlcmVkXzIgPC0gdGFidWxhX211cmlzX2ZpbHRlcmVkW2NvbW1tb25fZ2VuZXMsIF0Kcm93RGF0YShzY2UxMHhfc3RlbV9maWx0ZXJlZCkgPC0gcm93RGF0YSh0YWJ1bGFfbXVyaXNfZmlsdGVyZWRfMikKCnJvd25hbWVzKHNjZTEweF9zdGVtX2ZpbHRlcmVkKSA8LSByb3dEYXRhKHNjZTEweF9zdGVtX2ZpbHRlcmVkKSRleHRlcm5hbF9nZW5lX25hbWUKcm93bmFtZXModGFidWxhX211cmlzX2ZpbHRlcmVkXzIpIDwtIHJvd0RhdGEodGFidWxhX211cmlzX2ZpbHRlcmVkXzIpJGV4dGVybmFsX2dlbmVfbmFtZQpjb21iaW5lZCA8LSBjYmluZChzY2UxMHhfc3RlbV9maWx0ZXJlZCwgdGFidWxhX211cmlzX2ZpbHRlcmVkXzIpCmNvbWJpbmVkCmBgYAoKCiMjIyBDb21wdXRlIHRoZSBtZWFuIGxvZyBub3JtYWxpemVkIGNvdW50cyBmb3IgZWFjaCBjbHVzdGVyCgpgYGB7cn0KZ2VuZV9jb3VudHNfYnlfY2x1c3Rlcl9jb21iaW5lZCA8LQogIHQoYXNzYXkoY29tYmluZWQsICJsb2djb3VudHMiKSkgJT4lCiAgYXMubWF0cml4KCkgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgZ3JvdXBfYnkoY2x1c3RlciA9IGNvbERhdGEoY29tYmluZWQpJGNsdXN0ZXIpICU+JQogIHN1bW1hcmlzZV9hbGwobGlzdCh+IG1lYW4oLikpKQpnZW5lX2NvdW50c19sb25nX2NvbWJpbmVkIDwtCiAgdChnZW5lX2NvdW50c19ieV9jbHVzdGVyX2NvbWJpbmVkWywgLTFdKSAlPiUKICBhc190aWJibGUocm93bmFtZXMgPSAiZ2VuZSIpICU+JQogIHNldF9uYW1lcyhjKCJnZW5lIiwgZ2VuZV9jb3VudHNfYnlfY2x1c3Rlcl9jb21iaW5lZFssIDFdJGNsdXN0ZXIpKQpnZW5lX2NvdW50c19sb25nX2NvbWJpbmVkCmBgYAojIyMgQ29tcHV0ZSBjb3JyZWxhdGlvbnMgCgpgYGB7cn0KY29yX2R0IDwtIGNvcihnZW5lX2NvdW50c19sb25nX2NvbWJpbmVkWyAsIC0xXSkKY29yX2R0CmBgYApgYGB7ciBmaWcud2lkdGg9MTIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmNvcnJwbG90Ojpjb3JycGxvdChjb3JfZHQsIAogICAgICAgICAgICAgICAgICAgb3JkZXIgPSAnQU9FJywgCiAgICAgICAgICAgICAgICAgICB0eXBlID0gJ3VwcGVyJywgCiAgICAgICAgICAgICAgICAgICB0bC5wb3MgPSAnZCcsCiAgICAgICAgICAgICAgICAgICB0bC5jZXg9LjcpCmNvcnJwbG90Ojpjb3JycGxvdChjb3JfZHQsIAogICAgICAgICAgICAgICAgICAgYWRkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICB0eXBlID0gJ2xvd2VyJywKICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICdudW1iZXInLAogICAgICAgICAgICAgICAgICAgb3JkZXIgPSAnQU9FJywKICAgICAgICAgICAgICAgICAgIGRpYWcgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICB0bC5wb3MgPSAnbicsIAogICAgICAgICAgICAgICAgICAgY2wucG9zID0gJ24nKQpgYGAKCiMjIyBjb21wYXJpc29uIGFjcm9zcyB0aGUgdGhyZWUgZGF0YXNldHMgCgoKIyMjIyBNdVNDIFRhYnVsYSBNdXJpcyBkcm9wbGV0IHZzIE11U0MgZXhwZXJpbWVudCBkcm9wbGV0IAoKYGBge3IgZmlnLndpZHRoPTEyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZ3Bsb3QoCiAgZ2VuZV9jb3VudHNfbG9uZ19jb21iaW5lZCwKICBhZXMoIHg9IHRhYnVsYV9kcm9wbGV0X211c2NzLCB5ID0gbXVzY3MpCikgKwogIGdlb21fcG9pbnQoCiAgICBzaXplID0gLjUsCiAgICBhbHBoYSA9IDAuNQogICkgKwogIGdlb21fdGV4dChhZXMoCiAgICBsYWJlbCA9IGdlbmUKICApLAogIGNoZWNrX292ZXJsYXAgPSBUUlVFLCBudWRnZV95ID0gLTAuMTUsIHNpemUgPSAzCiAgKSArCiAgZ2VvbV9zbW9vdGgoYWxwaGEgPSAwLjIsIGNvbG91ciA9ICJncmV5IikgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkKYGBgCgojIyMjIE11U0NzIFRhYnVsYSBNdXJpcyBkcm9wbGV0IHZzIE11U0NzIFRhYnVsYSBNdXJpcyBGQUNTCgpgYGB7ciBmaWcud2lkdGg9MTIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmdncGxvdCgKICBnZW5lX2NvdW50c19sb25nX2NvbWJpbmVkLAogIGFlcyh4ID0gdGFidWxhX2ZhY3NfbXVzY3MgLCB5PXRhYnVsYV9kcm9wbGV0X211c2NzKQopICsKICBnZW9tX3BvaW50KAogICAgc2l6ZSA9IC41LAogICAgYWxwaGEgPSAwLjUKICApICsKICBnZW9tX3RleHQoYWVzKAogICAgbGFiZWwgPSBnZW5lCiAgKSwKICBjaGVja19vdmVybGFwID0gVFJVRSwgbnVkZ2VfeSA9IC0wLjE1LCBzaXplID0gMwogICkgKwogIGdlb21fc21vb3RoKGFscGhhID0gMC4yLCBjb2xvdXIgPSAiZ3JleSIpICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpCmBgYAoKCiMjIyMgTWFjcm9waGFnZSBUYWJ1bGEgTXVyaXMgZHJvcGxldCB2cyBNdVNDcyBleHBlcmltZW50IGRyb3BsZXQgCgpgYGB7ciBmaWcud2lkdGg9MTIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmdncGxvdCgKICBnZW5lX2NvdW50c19sb25nX2NvbWJpbmVkLAogIGFlcyh4ID0gdGFidWxhX2Ryb3BsZXRfbWFjcm9waGFnZSAsIHk9bXVzY3MpCikgKwogIGdlb21fcG9pbnQoCiAgICBzaXplID0gLjUsCiAgICBhbHBoYSA9IDAuNQogICkgKwogIGdlb21fdGV4dChhZXMoCiAgICBsYWJlbCA9IGdlbmUKICApLAogIGNoZWNrX292ZXJsYXAgPSBUUlVFLCBudWRnZV95ID0gLTAuMTUsIHNpemUgPSAzCiAgKSArCiAgZ2VvbV9zbW9vdGgoYWxwaGEgPSAwLjIsIGNvbG91ciA9ICJncmV5IikgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkKYGBgCgoKCgoKIyMjIyBNYWNyb3BoYWdlIFRhYnVsYSBNdXJpcyBkcm9wbGV0IHZzIE11U0MgZXhwZXJpbWVudCBkcm9wbGV0IAoKCmBgYHtyIGZpZy53aWR0aD0xMiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZ2dwbG90KAogIGdlbmVfY291bnRzX2xvbmdfY29tYmluZWQsCiAgYWVzKHggPSB0YWJ1bGFfZHJvcGxldF9tYWNyb3BoYWdlLCB5ID0gdGFidWxhX2Ryb3BsZXRfbXVzY3MpCikgKwogIGdlb21fcG9pbnQoCiAgICBzaXplID0gLjUsCiAgICBhbHBoYSA9IDAuNQogICkgKwogIGdlb21fdGV4dChhZXMoCiAgICBsYWJlbCA9IGdlbmUKICApLAogIGNoZWNrX292ZXJsYXAgPSBUUlVFLCBudWRnZV95ID0gLTAuMTUsIHNpemUgPSAzCiAgKSArCiAgZ2VvbV9zbW9vdGgoYWxwaGEgPSAwLjIsIGNvbG91ciA9ICJncmV5IikgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkKYGBgCgojIyMjIE1hY3JvcGhhZ2UgVGFidWxhIE11cmlzIGZhY3MgdnMgTXVTQyBleHBlcmltZW50IGRyb3BsZXQgCgoKYGBge3IgZmlnLndpZHRoPTEyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZ3Bsb3QoCiAgZ2VuZV9jb3VudHNfbG9uZ19jb21iaW5lZCwKICBhZXMoeCA9IHRhYnVsYV9mYWNzX21hY3JvcGhhZ2UsIHkgPSBtdXNjcykKKSArCiAgZ2VvbV9wb2ludCgKICAgIHNpemUgPSAuNSwKICAgIGFscGhhID0gMC41CiAgKSArCiAgZ2VvbV90ZXh0KGFlcygKICAgIGxhYmVsID0gZ2VuZQogICksCiAgY2hlY2tfb3ZlcmxhcCA9IFRSVUUsIG51ZGdlX3kgPSAtMC4xNSwgc2l6ZSA9IDMKICApICsKICBnZW9tX3Ntb290aChhbHBoYSA9IDAuMiwgY29sb3VyID0gImdyZXkiKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKQpgYGAKCgoKIyMjIFBsb3QgZ2VuZSBleHByZXNzaW9uCgoKCmBgYHtyfQpkZWMuY29tYmluZWQgPC0gbW9kZWxHZW5lVmFyKGNvbWJpbmVkWywgIShjb2xEYXRhKGNvbWJpbmVkKSRjbHVzdGVycyA9PSJmYWNzX3RhYnVsYSIpXSkKCiMgVmlzdWFsaXppbmcgdGhlIGZpdDoKZml0LmNvbWJpbmVkIDwtIG1ldGFkYXRhKGRlYy5jb21iaW5lZCkKcGxvdChmaXQuY29tYmluZWQkbWVhbiwgZml0LmNvbWJpbmVkJHZhciwKICB4bGFiID0gIk1lYW4gb2YgbG9nLWV4cHJlc3Npb24iLAogIHlsYWIgPSAiVmFyaWFuY2Ugb2YgbG9nLWV4cHJlc3Npb24iCikKY3VydmUoZml0LmNvbWJpbmVkJHRyZW5kKHgpLCBjb2wgPSAiZG9kZ2VyYmx1ZSIsIGFkZCA9IFRSVUUsIGx3ZCA9IDIpCmBgYAoKYGBge3J9Cmh2Zy5jb21iaW5lZC52YXIgPC0gZ2V0VG9wSFZHcyhkZWMuY29tYmluZWQsIG4gPSAzMDApCmBgYAoKCmBgYHtyIGZpZy5oZWlnaHQ9NDAsIGZpZy53aWR0aD0xMn0KcGxvdEhlYXRtYXAoY29tYmluZWRbLCAhKGNvbERhdGEoY29tYmluZWQpJGNsdXN0ZXJzID09ImZhY3NfdGFidWxhIildLAogIGNvbG9yID0gY29sb3JSYW1wUGFsZXR0ZShSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwobiA9IDExLCBuYW1lID0gIlJkQnUiKSkoMTEpLAogIGZlYXR1cmVzID0gaHZnLmNvbWJpbmVkLnZhciwKICAjICBjbHVzdGVyX2NvbHM9RkFMU0UsCiAgY2x1c3Rlcl9yb3dzID0gVFJVRSwKICBjZW50ZXIgPSBUUlVFLAogICMgemxpbT0gYygtMywzKSwKICBvcmRlcl9jb2x1bW5zX2J5ID0gYygiY2x1c3RlciIsICJzdW0iKSwKICAjICBnYXBzX3JvdyA9IHNlcSgwLDUqNSxieT01KQopCmBgYAoKCmBgYHtyIGZpZy53aWR0aD0xMn0KIyBwbG90RXhwcmVzc2lvbihjb21iaW5lZCwKIyAgIGZlYXR1cmVzID0gIk1hcDRrNCIsCiMgICB4ID0gImNsdXN0ZXIiLAojICAgZXhwcnNfdmFsdWVzID0gImxvZ2NvdW50cyIsCiMgICBjb2xvdXJfYnkgPSAiY2x1c3RlcnMiLAojICAgcG9pbnRfc2l6ZSA9IDEKIyApICsKIyAgIGZhY2V0X3dyYXAofiBjb2xEYXRhKGNvbWJpbmVkKSRjbHVzdGVycywgbmNvbCA9IDEpCmBgYAoKCgpgYGB7cn0Kc2Vzc2lvbkluZm8oKQpgYGAK