Analysis of the pallial progenitor domains along corticogenesis from the Mouse Brain Atlas - Development released by the Linnarsson’s lab on July 2020 (BioRxiv preprint).

load libraries

library(loomR)
library(Seurat)
library(scrattch.hicat)
library(reticulate)

library(dplyr)
library(ggExtra)

library(ggplot2)
library(patchwork)
library(RColorBrewer)

#Set ggplot theme classic
theme_set(theme_classic())

#Set python env for UMAP 
use_python("/home/matthieu/.local/share/r-miniconda/envs/r-reticulate/bin/python")

Extraction of annotated radial glial cell from E11 to E15.5

Reading loom file containing cluster metadata

lfile <- connect(filename = "./DevelopingMouseBrainAtlas/dev_all.agg.loom",
                 skip.validate =T,
                 mode="r+")

We extract all cluster annotated as “radial glia”

ClustersAnno <- lfile$col.attrs$Clusters[][lfile$col.attrs$Class[] %in% c("Radial glia")]
lfile$close_all()

Reading loom file containing all metadata and count table for the 292,495 high-quality cells

lfile <- connect(filename = "./DevelopingMouseBrainAtlas/dev_all.loom",
                 skip.validate =T,
                 mode="r+")

Plot extracted cells on the global tsne

tSNE <- t(lfile$col.attrs$BTSNE[,])

tSNE.df <- lfile$get.attribute.df(MARGIN = 2, attributes = c("Clusters", "Age"), col.names = "CellID")
tSNE.df$GlialCell <- ifelse(tSNE.df$Clusters %in% ClustersAnno & tSNE.df$Age %in% c("e11.0","e12.0","e12.5","e13.0","e13.5","e14.0", "e14.5", "e15.0", "e15.5"), "Radial glia", "OtherCells")

tSNE.df$tSNE.1 <- tSNE[,1]
tSNE.df$tSNE.2 <- tSNE[,2]
plot <-ggplot(tSNE.df, aes(x=tSNE.1, y=tSNE.2, colour = GlialCell)) +
          geom_point( size=0.3, shape=16) +
          scale_color_manual(values= c("grey90","#e7823a")) +
          theme_classic()+
          theme(axis.text.x=element_blank(), axis.text.y=element_blank(),
                axis.ticks.x=element_blank(), axis.ticks.y=element_blank(),
                axis.title.x=element_blank(),axis.title.y=element_blank()) +
          ggtitle(label = paste(names(table(tSNE.df$GlialCell)[2]), table(tSNE.df$GlialCell)[2]))

plot$data <- plot$data[order(plot$data$GlialCell,decreasing = F),]

plot

rm(tSNE.df,tSNE)

Extract Radial glia cells count matrix and metadata

Retrieve the count matrix

cells <- lfile$col.attrs$Clusters[] %in% ClustersAnno & lfile$col.attrs$Age[] %in% c("e11.0","e12.0","e12.5","e13.0","e13.5","e14.0", "e14.5", "e15.0", "e15.5")
data.subset <- lfile[["matrix"]][ cells, ]
data.subset <- t(data.subset)

dim(data.subset)
## [1] 31053 22650

Retrieve gene names

gene.names <- lfile[["row_attrs/Gene"]][]
rownames(data.subset) <- gene.names

Extract meta.data information

attrs <- c("CellID","Age", "Batch", "Chemistry", "ChipID","Clusters", "Region", "Tissue", "PseudoTissue")
attr.df <- lfile$get.attribute.df(MARGIN = 2, attributes = attrs, col.names = "CellID")
attr.df <- attr.df[cells,]
rownames(attr.df) <- attr.df$CellID

colnames(data.subset) <- attr.df$CellID

Closing loom object

lfile$close_all()

Perfom analysis with seurat v2.3.4

Initiate a Seurat object

Raw.data <- CreateSeuratObject(raw.data = data.subset,
                               min.cells = 5,
                               min.genes = 0,
                               project = "RadialGlia_DevelopingMouseBrainAtlas")

rm(list=ls()[!ls() %in% c("Raw.data","attr.df")])
gc()
##             used   (Mb) gc trigger    (Mb)   max used    (Mb)
## Ncells   3263133  174.3    6057934   323.6    6057934   323.6
## Vcells 879352160 6709.0 2453505816 18718.8 2991256468 22821.5

We exclude genes with duplicated row names

rownames(Raw.data@raw.data)[duplicated(rownames(Raw.data@raw.data))]
## [1] "Atp5o"   "Gm2464"  "Gcat"    "Nudt8"   "Aldoa"   "Ints5"   "Zc3h11a"
## [8] "Pick1"
Raw.data@raw.data <- Raw.data@raw.data[!duplicated(rownames(Raw.data@raw.data)),]

Low quality cells filtering and data normalization

Compute ribosomal and mitochondrial transcript fractions per cell

mito.genes <- grep(pattern = "^mt-", x = rownames(x = Raw.data@data), value = TRUE)
percent.mito <- Matrix::colSums(Raw.data@raw.data[mito.genes, ])/Matrix::colSums(Raw.data@raw.data)
Raw.data <- AddMetaData(object = Raw.data, metadata = percent.mito, col.name = "percent.mito")

ribo.genes <- grep(pattern = "(^Rpl|^Rps|^Mrp)", x = rownames(x = Raw.data@data), value = TRUE)
percent.ribo <- Matrix::colSums(Raw.data@raw.data[ribo.genes, ])/Matrix::colSums(Raw.data@raw.data)
Raw.data <- AddMetaData(object = Raw.data, metadata = percent.ribo, col.name = "percent.ribo")

Raw.data@meta.data <- cbind(Raw.data@meta.data, attr.df)
rm(mito.genes, percent.mito,ribo.genes,percent.ribo)
Cell.QC.Stat <- Raw.data@meta.data

Filtering cells based on number of genes and transcripts detected

Remove cells with to few genes detected or with to many UMI counts

# Set low and hight thresholds on the number of detected genes
min.Genes.thr <- median(log10(Cell.QC.Stat$nGene)) - 3*mad(log10(Cell.QC.Stat$nGene))
max.Genes.thr <- median(log10(Cell.QC.Stat$nGene)) + 3*mad(log10(Cell.QC.Stat$nGene))

# Set hight threshold on the number of transcripts
max.nUMI.thr <- median(log10(Cell.QC.Stat$nUMI)) + 3*mad(log10(Cell.QC.Stat$nUMI))

# Gene/UMI scatter plot before filtering
p <- ggplot(Cell.QC.Stat, aes(x=log10(nUMI), y=log10(nGene))) +
      geom_point() +
      geom_smooth(method="lm") +
      geom_hline(aes(yintercept = min.Genes.thr), colour = "green", linetype = 2) +
      geom_hline(aes(yintercept = max.Genes.thr), colour = "green", linetype = 2) +
      geom_vline(aes(xintercept = max.nUMI.thr), colour = "red", linetype = 2)

ggMarginal(p, type = "histogram", fill="lightgrey")

# Filter cells base on both metrics
Cell.QC.Stat <- Cell.QC.Stat %>% filter(log10(nGene) > min.Genes.thr) %>% filter(log10(nUMI) < max.nUMI.thr)
p <- ggplot(Cell.QC.Stat, aes(x=log10(nUMI), y=log10(nGene))) +
  geom_point() +
  geom_smooth(method="lm") +
  geom_hline(aes(yintercept = min.Genes.thr), colour = "green", linetype = 2) +
  geom_hline(aes(yintercept = max.Genes.thr), colour = "green", linetype = 2) +
  geom_vline(aes(xintercept = max.nUMI.thr), colour = "red", linetype = 2) +
  annotate(geom = "text", label = paste0(dim(Cell.QC.Stat)[1], " QC passed cells"), x = 4, y = 3.8)

ggMarginal(p, type = "histogram", fill="lightgrey")

Keep only valid cells

Radial.Glia.data <- SubsetData(Raw.data, cells.use = Cell.QC.Stat$CellID , subset.raw = T,  do.clean = F)
rm(list=ls()[!ls() %in% c("Radial.Glia.data")])
# Plot final QC metrics
VlnPlot(object = Radial.Glia.data,
        features.plot = c("nGene","nUMI", "percent.mito", "percent.ribo"),
        cols.use = c("#ebcb2e", "#9ec22f", "#a9961b", "#cc3a1b", "#cc8778" , "#d14c8d","#4cabdc", "#5ab793", "#e7823a"),
        nCol = 2, point.size.use = 0, group.by = "Age")

Normalization and scaling

Gene filtering

Radial.Glia.data@raw.data <- Radial.Glia.data@raw.data[!duplicated(rownames(Radial.Glia.data@raw.data)),]

num.cells <- Matrix::rowSums(Radial.Glia.data@raw.data > 0)
genes.use <- names(x = num.cells[which(x = num.cells >= 10)])
Radial.Glia.data@raw.data <- Radial.Glia.data@raw.data[genes.use, ]
Radial.Glia.data@data <- Radial.Glia.data@data[genes.use, ]

Normalization

Radial.Glia.data <- NormalizeData(object = Radial.Glia.data,
                                  normalization.method = "LogNormalize", 
                                  scale.factor = round(median(Radial.Glia.data@meta.data$nUMI)),
                                  display.progress = F)
Radial.Glia.data <- FindVariableGenes(object = Radial.Glia.data,
                                       mean.function = ExpMean,
                                       dispersion.function = LogVMR,
                                       x.low.cutoff = 0.0125,
                                       x.high.cutoff = 3,
                                       y.cutoff = 1,
                                       do.plot = F, display.progress = T)

Assign Cell-Cycle Score

s.genes <- c("Mcm5", "Pcna", "Tym5", "Fen1", "Mcm2", "Mcm4", "Rrm1", "Ung",
             "Gins2", "Mcm6", "Cdca7", "Dtl", "Prim1", "Uhrf1", "Mlf1ip",
             "Hells", "Rfc2", "Rap2", "Nasp", "Rad51ap1", "Gmnn", "Wdr76", "Slbp",
             "Ccne2", "Ubr7", "Pold3", "Msh2", "Atad2", "Rad51", "Rrm2", "Cdc45",
             "Cdc6", "Exo1", "Tipin", "Dscc1", "Blm", " Casp8ap2", "Usp1", "Clspn",
             "Pola1", "Chaf1b", "Brip1", "E2f8")

g2m.genes <- c("Hmgb2", "Ddk1","Nusap1", "Ube2c", "Birc5", "Tpx2", "Top2a", "Ndc80",
               "Cks2", "Nuf2", "Cks1b", "Mki67", "Tmpo", " Cenpk", "Tacc3", "Fam64a",
               "Smc4", "Ccnb2", "Ckap2l", "Ckap2", "Aurkb", "Bub1", "Kif11", "Anp32e",
               "Tubb4b", "Gtse1", "kif20b", "Hjurp", "Cdca3", "Hn1", "Cdc20", "Ttk", "Cdc25c",
               "kif2c", "Rangap1", "Ncapd2", "Dlgap5", "Cdca2", "Cdca8", "Ect2", "Kif23", "Hmmr",
               "Aurka", "Psrc1", "Anln", "Lbr", "Ckap5", "Cenpe", "Ctcf", "Nek2", "G2e3", "Gas2l3", "Cbx5", "Cenpa")

Radial.Glia.data<- CellCycleScoring(object = Radial.Glia.data,
                                    s.genes = s.genes,
                                    g2m.genes = g2m.genes,
                                    set.ident = F)

Radial.Glia.data@meta.data$CC.Difference <- Radial.Glia.data@meta.data$S.Score - Radial.Glia.data@meta.data$G2M.Score
VlnPlot(object = Radial.Glia.data,
        features.plot = c("S.Score", "G2M.Score","CC.Difference" ,"percent.ribo"),
        cols.use = c("#ebcb2e", "#9ec22f", "#a9961b", "#cc3a1b", "#cc8778" , "#d14c8d","#4cabdc", "#5ab793", "#e7823a"),
        nCol = 2, point.size.use = 0, group.by = "Age")

Data scaling and cell cycle regression

Radial.Glia.data <- ScaleData(object = Radial.Glia.data,
                     vars.to.regress = c("CC.Difference","percent.mito","nGene", "nUMI"),
                     display.progress = T)
## 
## Time Elapsed:  1.55461797714233 mins

Dimensionality reduction

PCA and UMAP

Radial.Glia.data <- RunPCA(object = Radial.Glia.data,
                          pcs.compute = 30,
                          do.print = TRUE,
                          pcs.print = F)
rm(list=ls()[!ls() %in% c("Radial.Glia.data")])
gc()
##             used   (Mb) gc trigger    (Mb)   max used    (Mb)
## Ncells   3109520  166.1    6057934   323.6    6057934   323.6
## Vcells 888117436 6775.8 2683674431 20474.9 2991256468 22821.5
Radial.Glia.data <- RunUMAP(Radial.Glia.data, dims.use = 1:30, n_neighbors = 8, max.dim = 2)

Features plot

Age, Region, Tissue, Pseudo-tissue

Age

DimPlot(Radial.Glia.data,
        reduction.use = "umap",
        group.by = c("Age"),
        cols.use = c("#ebcb2e", "#9ec22f", "#a9961b", "#cc3a1b", "#cc8778" , "#d14c8d","#4cabdc", "#5ab793", "#e7823a"),
        dim.1 = 1,
        dim.2 = 2,
        do.label=T,
        label.size = 4,
        no.axes = T,
        no.legend = F)

Region

DimPlot(Radial.Glia.data,
        reduction.use = "umap",
        group.by = c("Region"),
        cols.use = c("#ebcb2e", "#9ec22f", "#a9961b", "#cc3a1b", "#cc8778" , "#d14c8d","#4cabdc", "#5ab793", "#e7823a"),
        dim.1 = 1,
        dim.2 = 2,
        do.label=T,
        label.size = 4,
        no.axes = T,
        no.legend = F)

Tissue

DimPlot(Radial.Glia.data,
        reduction.use = "umap",
        group.by = c("Tissue"),
        cols.use = c("#ebcb2e", "#9ec22f", "#a9961b", "#cc3a1b", "#cc8778" , "#d14c8d","#4cabdc", "#5ab793", "#e7823a"),
        dim.1 = 1,
        dim.2 = 2,
        do.label=T,
        label.size = 4,
        no.axes = T,
        no.legend = F)

PseudoTissue

DimPlot(Radial.Glia.data,
        reduction.use = "umap",
        group.by = c("PseudoTissue"),
        cols.use = c("#ebcb2e", "#9ec22f", "#a9961b", "#cc3a1b", "#cc8778" , "#d14c8d","#4cabdc", "#5ab793", "#e7823a"),
        dim.1 = 1,
        dim.2 = 2,
        do.label=T,
        label.size = 4,
        no.axes = T,
        no.legend = F)

Major radial glia population makers

plot <- FeaturePlot(object = Radial.Glia.data,
                    features.plot =  c("Foxg1","Gsx2","Otx2", "Olig2", "Dlx2",
                                      "Tfap2c", "Dmrta2", "Fezf2", "Pax6","Emx1",
                                      "Shh", "Rspo2","Sfrp2", "Fgf8", "Qrfpr"),
                    cols.use = c("grey90", brewer.pal(9,"YlGnBu")),
                    reduction.use = "umap",
                    no.legend = T,
                    overlay = F,
                    dark.theme = F,
                    do.return =T,
                    no.axes = T)
for (i in 1:length(plot)){
  plot[[i]]$data <- plot[[i]]$data[order(plot[[i]]$data$gene),]
}
cowplot::plot_grid(plotlist = plot[1:15], ncol = 5)

Extract Forbrain cells

Forbrain.cells <- Radial.Glia.data@meta.data %>% filter(Region == "Forebrain") %>% pull(CellID)

Radial.Glia.data <- SubsetData(Radial.Glia.data, cells.use = Forbrain.cells , subset.raw = T,  do.clean = F)
rm(list=ls()[!ls() %in% c("Radial.Glia.data")])

Normalization and scaling

Gene filtering

num.cells <- Matrix::rowSums(Radial.Glia.data@raw.data > 0)
genes.use <- names(x = num.cells[which(x = num.cells >= 10)])
Radial.Glia.data@raw.data <- Radial.Glia.data@raw.data[genes.use, ]
Radial.Glia.data@data <- Radial.Glia.data@data[genes.use, ]

Normalization

Radial.Glia.data <- NormalizeData(object = Radial.Glia.data,
                         normalization.method = "LogNormalize", 
                         scale.factor = round(median(Radial.Glia.data@meta.data$nUMI)),
                         display.progress = F)
Radial.Glia.data <- FindVariableGenes(object = Radial.Glia.data,
                                       mean.function = ExpMean,
                                       dispersion.function = LogVMR,
                                       x.low.cutoff = 0.0125,
                                       x.high.cutoff = 3,
                                       y.cutoff = 1,
                                       do.plot = F, display.progress = T)

Data scaling and cell cycle regression

Radial.Glia.data <- ScaleData(object = Radial.Glia.data,
                     vars.to.regress = c("CC.Difference","percent.mito","nGene", "nUMI"),
                     display.progress = T)
## 
## Time Elapsed:  1.63568867842356 mins

Dimensionality reduction

Radial.Glia.data <- RunPCA(object = Radial.Glia.data,
                          pcs.compute = 30,
                          do.print = TRUE,
                          pcs.print = F)
Radial.Glia.data <- RunUMAP(Radial.Glia.data, dims.use = 1:30, n_neighbors = 8, max.dim = 2)
colors <- c("#b7d174", "#83c3b8", "#3e69ac",
            "#e46b6b",  "#009fda", "#c773a7",
            "#ec756d", "#7293c8", "#b79f0b",
            "#ebcb2e", "#cc3a1b", "#cc8778")

DimPlot(Radial.Glia.data,
        group.by = "Age",
        reduction.use = "umap",
        dim.1 = 1,
        dim.2 = 2,
        do.label=T,
        label.size = 4,
        no.legend = F,
        no.axes = T,
        cols.use = rep(c("#bdd8ef", "#6db8e2", "#357ebc", "#1c4896"),each=2))

DimPlot(Radial.Glia.data,
        reduction.use = "umap",
        group.by = c("Tissue"),
        cols.use = c("#ebcb2e", "#9ec22f", "#a9961b", "#cc3a1b", "#cc8778" , "#d14c8d","#4cabdc", "#5ab793", "#e7823a"),
        dim.1 = 1,
        dim.2 = 2,
        do.label=T,
        label.size = 4,
        no.axes = T,
        no.legend = F)

rm(list=ls()[!ls() %in% c("Radial.Glia.data")])
gc()
##             used   (Mb) gc trigger    (Mb)   max used    (Mb)
## Ncells   3159501  168.8    6057934   323.6    6057934   323.6
## Vcells 587530028 4482.5 2146939545 16379.9 2991256468 22821.5

Perform iterative clustering

Prepare the dataset for clustering with scrattch.hicat

Gene filtering

We decided to exclude cell cycle, ribosomal and mitochondrial associated genes, as well as Xist for the clustering step.

# Exclude cell cycle associated genes
ccgenes <- as.character(read.table("./Progenitors/CellCycleGenes.csv", sep = ";")[,1])

# Exclude genes detected in less than 10 cells
num.cells <- Matrix::rowSums(Radial.Glia.data@data > 0)
genes.use <- names(x = num.cells[which(x = num.cells >= 10)])

GenesToRemove <- c(grep(pattern = "(^Rpl|^Rps|^Mrp)", x = genes.use, value = TRUE),
                   grep(pattern = "^mt-", x = genes.use, value = TRUE),
                   "Xist", ccgenes)

genes.use <- genes.use[!genes.use %in% GenesToRemove]

Normalization

dgeMatrix_count <- as.matrix(Radial.Glia.data@raw.data)[rownames(Radial.Glia.data@raw.data) %in% genes.use,]
dgeMatrix_cpm <- cpm(dgeMatrix_count)
norm.dat <- log2(dgeMatrix_cpm + 1)
norm.dat <- Matrix(norm.dat, sparse = TRUE)
Data.matrix <- list(raw.dat= dgeMatrix_count, norm.dat= norm.dat)
attach(Data.matrix)
rm(list = ls()[!ls() %in% c("Radial.Glia.data", "Data.matrix")])
gc()
##             used   (Mb) gc trigger    (Mb)   max used    (Mb)
## Ncells   3166012  169.1    6057934   323.6    6057934   323.6
## Vcells 899707492 6864.3 2146939545 16379.9 2991256468 22821.5

Filter unwanted sources of variation

gene.counts <- log2(colSums(as.matrix(Data.matrix$norm.dat) > 0))
nUMI <- log2(colSums(Data.matrix$raw.dat))
perctMito <- Radial.Glia.data@meta.data$percent.mito
perctRibo <- Radial.Glia.data@meta.data$percent.ribo
ccphasediff <- Radial.Glia.data@meta.data$CC.Difference

rm.eigen <- as.matrix(cbind(gene.counts,
                            nUMI,
                            perctMito,
                            perctRibo,
                            ccphasediff))

row.names(rm.eigen) <- names(gene.counts)

colnames(rm.eigen) <- c("log2nGenes",
                        "log2nUMI",
                        "perctMito",
                        "perctRibo",
                        "ccphasediff")

Set Iterative clustering parameters

# Parameters for iterative clustering
de.param <- de_param(padj.th     = 0.01, 
                     lfc.th      = 1,
                     low.th      = 1, 
                     q1.th       = 0.25, 
                     q2.th       = NULL,
                     q.diff.th   = 0.7,
                     de.score.th = 300,
                     min.cells = 50)

Run iterative clustering

iter.result <- iter_clust(norm.dat, 
                          counts = raw.dat,
                          dim.method = "pca",
                          max.dim = 30,
                          de.param = de.param,
                          type = "undirectional",
                          rm.eigen = rm.eigen,
                          k.param = 15,
                          rm.th = 0.7,
                          vg.padj.th = 0.5,
                          method = "louvain",
                          prefix = "test-iter_clust",
                          verbose = F)
## [1] "test-iter_clust"
##   Finding nearest neighbors...DONE ~ 2.976 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.774 s
##   Build undirected graph from the weighted links...DONE ~ 0.765 s
##   Run louvain clustering on the graph ...DONE ~ 0.587 s
##   Return a community class
##   -Modularity value: 0.8365338 
##   -Number of clusters: 22[1] "test-iter_clust.1"
##   Finding nearest neighbors...DONE ~ 0.006 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.022 s
##   Build undirected graph from the weighted links...DONE ~ 0.026 s
##   Run louvain clustering on the graph ...DONE ~ 0.01 s
##   Return a community class
##   -Modularity value: 0.6294141 
##   -Number of clusters: 7[1] "test-iter_clust.2"
##   Finding nearest neighbors...DONE ~ 0.009 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.035 s
##   Build undirected graph from the weighted links...DONE ~ 0.033 s
##   Run louvain clustering on the graph ...DONE ~ 0.02 s
##   Return a community class
##   -Modularity value: 0.7529057 
##   -Number of clusters: 11[1] "test-iter_clust.3"
##   Finding nearest neighbors...DONE ~ 0.017 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.042 s
##   Build undirected graph from the weighted links...DONE ~ 0.04 s
##   Run louvain clustering on the graph ...DONE ~ 0.021 s
##   Return a community class
##   -Modularity value: 0.7050087 
##   -Number of clusters: 13[1] "test-iter_clust.4"
##   Finding nearest neighbors...DONE ~ 0.384 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.232 s
##   Build undirected graph from the weighted links...DONE ~ 0.229 s
##   Run louvain clustering on the graph ...DONE ~ 0.156 s
##   Return a community class
##   -Modularity value: 0.8127554 
##   -Number of clusters: 19[1] "test-iter_clust.4.1"
##   Finding nearest neighbors...DONE ~ 0.005 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.021 s
##   Build undirected graph from the weighted links...DONE ~ 0.019 s
##   Run louvain clustering on the graph ...DONE ~ 0.01 s
##   Return a community class
##   -Modularity value: 0.671172 
##   -Number of clusters: 7[1] "test-iter_clust.4.2"
##   Finding nearest neighbors...DONE ~ 0.257 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.195 s
##   Build undirected graph from the weighted links...DONE ~ 0.18 s
##   Run louvain clustering on the graph ...DONE ~ 0.124 s
##   Return a community class
##   -Modularity value: 0.8213536 
##   -Number of clusters: 17[1] "test-iter_clust.4.2.1"
##   Finding nearest neighbors...DONE ~ 0.242 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.185 s
##   Build undirected graph from the weighted links...DONE ~ 0.173 s
##   Run louvain clustering on the graph ...DONE ~ 0.113 s
##   Return a community class
##   -Modularity value: 0.8166865 
##   -Number of clusters: 18[1] "test-iter_clust.4.2.2"
##   Finding nearest neighbors...DONE ~ 0.003 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.017 s
##   Build undirected graph from the weighted links...DONE ~ 0.028 s
##   Run louvain clustering on the graph ...DONE ~ 0.01 s
##   Return a community class
##   -Modularity value: 0.6669176 
##   -Number of clusters: 6[1] "test-iter_clust.4.3"
##   Finding nearest neighbors...DONE ~ 0.005 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.019 s
##   Build undirected graph from the weighted links...DONE ~ 0.018 s
##   Run louvain clustering on the graph ...DONE ~ 0.008 s
##   Return a community class
##   -Modularity value: 0.6211829 
##   -Number of clusters: 6[1] "test-iter_clust.5"
##   Finding nearest neighbors...DONE ~ 0.503 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.261 s
##   Build undirected graph from the weighted links...DONE ~ 0.249 s
##   Run louvain clustering on the graph ...DONE ~ 0.196 s
##   Return a community class
##   -Modularity value: 0.8039505 
##   -Number of clusters: 16[1] "test-iter_clust.5.1"
##   Finding nearest neighbors...DONE ~ 0.297 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.164 s
##   Build undirected graph from the weighted links...DONE ~ 0.163 s
##   Run louvain clustering on the graph ...DONE ~ 0.098 s
##   Return a community class
##   -Modularity value: 0.7740656 
##   -Number of clusters: 17[1] "test-iter_clust.5.1.1"
##   Finding nearest neighbors...DONE ~ 0.318 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.157 s
##   Build undirected graph from the weighted links...DONE ~ 0.151 s
##   Run louvain clustering on the graph ...DONE ~ 0.099 s
##   Return a community class
##   -Modularity value: 0.7643717 
##   -Number of clusters: 13[1] "test-iter_clust.5.1.2"
##   Finding nearest neighbors...DONE ~ 0.001 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.01 s
##   Build undirected graph from the weighted links...DONE ~ 0.01 s
##   Run louvain clustering on the graph ...DONE ~ 0.006 s
##   Return a community class
##   -Modularity value: 0.643927 
##   -Number of clusters: 6[1] "test-iter_clust.5.2"
##   Finding nearest neighbors...DONE ~ 0.13 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.076 s
##   Build undirected graph from the weighted links...DONE ~ 0.074 s
##   Run louvain clustering on the graph ...DONE ~ 0.047 s
##   Return a community class
##   -Modularity value: 0.6347574 
##   -Number of clusters: 9[1] "test-iter_clust.5.3"
##   Finding nearest neighbors...DONE ~ 0.017 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.039 s
##   Build undirected graph from the weighted links...DONE ~ 0.037 s
##   Run louvain clustering on the graph ...DONE ~ 0.017 s
##   Return a community class
##   -Modularity value: 0.7105503 
##   -Number of clusters: 12[1] "test-iter_clust.6"
##   Finding nearest neighbors...DONE ~ 0.028 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.054 s
##   Build undirected graph from the weighted links...DONE ~ 0.051 s
##   Run louvain clustering on the graph ...DONE ~ 0.027 s
##   Return a community class
##   -Modularity value: 0.7669241 
##   -Number of clusters: 12[1] "test-iter_clust.6.1"
##   Finding nearest neighbors...DONE ~ 0.004 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.025 s
##   Build undirected graph from the weighted links...DONE ~ 0.023 s
##   Run louvain clustering on the graph ...DONE ~ 0.01 s
##   Return a community class
##   -Modularity value: 0.7934622 
##   -Number of clusters: 9[1] "test-iter_clust.6.2"
##   Finding nearest neighbors...DONE ~ 0.015 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.035 s
##   Build undirected graph from the weighted links...DONE ~ 0.034 s
##   Run louvain clustering on the graph ...DONE ~ 0.015 s
##   Return a community class
##   -Modularity value: 0.7163692 
##   -Number of clusters: 11[1] "test-iter_clust.7"
##   Finding nearest neighbors...DONE ~ 0.016 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.036 s
##   Build undirected graph from the weighted links...DONE ~ 0.033 s
##   Run louvain clustering on the graph ...DONE ~ 0.017 s
##   Return a community class
##   -Modularity value: 0.696045 
##   -Number of clusters: 10[1] "test-iter_clust.8"
##   Finding nearest neighbors...DONE ~ 0.03 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.045 s
##   Build undirected graph from the weighted links...DONE ~ 0.043 s
##   Run louvain clustering on the graph ...DONE ~ 0.025 s
##   Return a community class
##   -Modularity value: 0.7293799 
##   -Number of clusters: 12[1] "test-iter_clust.9"
##   Finding nearest neighbors...DONE ~ 0.092 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.081 s
##   Build undirected graph from the weighted links...DONE ~ 0.075 s
##   Run louvain clustering on the graph ...DONE ~ 0.044 s
##   Return a community class
##   -Modularity value: 0.7855973 
##   -Number of clusters: 13[1] "test-iter_clust.9.1"
##   Finding nearest neighbors...DONE ~ 0.001 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.011 s
##   Build undirected graph from the weighted links...DONE ~ 0.011 s
##   Run louvain clustering on the graph ...DONE ~ 0.004 s
##   Return a community class
##   -Modularity value: 0.5786325 
##   -Number of clusters: 8[1] "test-iter_clust.9.2"
##   Finding nearest neighbors...DONE ~ 0.008 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.026 s
##   Build undirected graph from the weighted links...DONE ~ 0.023 s
##   Run louvain clustering on the graph ...DONE ~ 0.01 s
##   Return a community class
##   -Modularity value: 0.7372565 
##   -Number of clusters: 11[1] "test-iter_clust.9.3"
##   Finding nearest neighbors...DONE ~ 0.037 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.054 s
##   Build undirected graph from the weighted links...DONE ~ 0.052 s
##   Run louvain clustering on the graph ...DONE ~ 0.026 s
##   Return a community class
##   -Modularity value: 0.7374588 
##   -Number of clusters: 10[1] "test-iter_clust.10"
##   Finding nearest neighbors...DONE ~ 0.085 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.077 s
##   Build undirected graph from the weighted links...DONE ~ 0.072 s
##   Run louvain clustering on the graph ...DONE ~ 0.046 s
##   Return a community class
##   -Modularity value: 0.7068849 
##   -Number of clusters: 11

Merge clusters not discriminated by DEGs

# Merge clusters which are not separable by DEGs
rd.dat <- t(norm.dat[iter.result$markers,])
merge.result <- merge_cl(norm.dat, 
                         cl = iter.result$cl, 
                         rd.dat = rd.dat,
                         de.param = de.param)

cat(length(unique(merge.result$cl))," Clusters\n")
## 18  Clusters

Plot clusters on UMAP embedding

Radial.Glia.data@ident <- as.factor(merge.result$cl)
Radial.Glia.data@meta.data$Scrattchicat.ident <- as.character(Radial.Glia.data@ident)

colors <- c("#68b041", "#e3c148", "#b7d174", "#83c3b8",  "#3e69ac", "#e46b6b","#009fda",
            "#c773a7","#ec756d", "#7293c8", "#b79f0b", "#3ca73f","#31b6bd",
            "#ebcb2e", "#9ec22f", "#a9961b", "#cc3a1b", "#cc8778" , "#d14c8d",
            "#4cabdc", "#5ab793", "#e7823a","#e6bb9b", "#046c9a", "#4784a2" , "#4990c9")

DimPlot(Radial.Glia.data,
        reduction.use = "umap",
        dim.1 = 1,
        dim.2 = 2,
        do.label=T,
        label.size = 4,
        no.legend = F,
        no.axes = T,
        cols.use = colors)

plot <- FeaturePlot(object = Radial.Glia.data,
            features.plot =  c("Barhl2", "Otx2", "Dlk1", "Sfrp2",
                               "Foxg1", "Emx1", "Gsx2", "Olig2",
                               "Wnt3a", "Rspo3", "Fgf8", "Shh"
                               ),
            cols.use = c("grey90", brewer.pal(9,"YlGnBu")),
            reduction.use = "umap",
            no.legend = T,
            overlay = F,
            dark.theme = F,
            do.return =T,
            no.axes = T)
for (i in 1:length(plot)){
  plot[[i]]$data <- plot[[i]]$data[order(plot[[i]]$data$gene),]
}
cowplot::plot_grid(plotlist = plot[1:12], ncol = 4)

rm(list = ls()[!ls() %in% c("Radial.Glia.data")])
gc()
##             used   (Mb) gc trigger    (Mb)   max used    (Mb)
## Ncells   3247236  173.5    6057934   323.6    6057934   323.6
## Vcells 900987039 6874.0 2146939545 16379.9 2991256468 22821.5

Compute maturation and spatial scores

We use the gene signatures from Fig6 E and G to compute the maturation or spatial scores

Dorso-Ventral scores

Sgenes <- read.table("./Progenitors/Spatial.gene.clusters.csv", sep = ";", header = T, row.names = 1)
# VP enriched genes at E12
genes.list <- Sgenes %>%
              filter(Gene.Clusters %in% c("Clust.1", "Clust.2")) %>%
              pull(Gene) %>%
              as.character()

genes.list <- list(genes.list[genes.list %in% rownames(Radial.Glia.data@data)])

genes.list
## [[1]]
##   [1] "Slc39a10"      "Dner"          "Plekha6"       "Pdk1"         
##   [5] "Tmx4"          "Zcchc12"       "Arx"           "Xist"         
##   [9] "Riiad1"        "Hs3st1"        "Mthfd2l"       "Cald1"        
##  [13] "Nap1l5"        "Peg3"          "St5"           "Bnip3"        
##  [17] "Ostm1"         "Ascl1"         "Gm2694"        "Dleu7"        
##  [21] "Anxa2"         "Spsb4"         "Cyfip2"        "Gpx3"         
##  [25] "Sez6"          "Ptch1"         "Mctp1"         "Atad2b"       
##  [29] "Sybu"          "Pmm1"          "Wnt7b"         "Six3"         
##  [33] "Esco1"         "Tpgs2"         "Celf4"         "Vldlr"        
##  [37] "Spats2l"       "Klf7"          "Acadl"         "Ackr3"        
##  [41] "D1Ertd622e"    "Pam"           "Nckap5"        "Btg2"         
##  [45] "B3galt2"       "Xpr1"          "Gm5532"        "Rasal2"       
##  [49] "Atp1b1"        "Dusp10"        "Kcnk2"         "Nenf"         
##  [53] "Nacc2"         "Notch1"        "Pbx3"          "Gsn"          
##  [57] "Lypd6"         "Tnfaip6"       "Ermn"          "Gca"          
##  [61] "Fign"          "Dlx2"          "Itga6"         "Fam171b"      
##  [65] "Lrp4"          "Tspan18"       "Sema6d"        "Slc24a5"      
##  [69] "Myef2"         "Acss1"         "Stmn3"         "Fgf13"        
##  [73] "Pou3f4"        "Usp51"         "Tnik"          "Qrfpr"        
##  [77] "Anxa5"         "Fat4"          "Hspa4l"        "Slc7a11"      
##  [81] "Lhfp"          "Arhgef26"      "Ptx3"          "Fstl5"        
##  [85] "Ctso"          "Sfrp2"         "Nes"           "Igsf3"        
##  [89] "Rhoc"          "Ank2"          "Cxxc4"         "Ddit4l"       
##  [93] "Lmo4"          "Car8"          "Rgs3"          "Cntln"        
##  [97] "Jun"           "Mycl"          "Kif1b"         "Akap9"        
## [101] "Cacna2d1"      "Napepld"       "Fam126a"       "Actr3b"       
## [105] "3110082J24Rik" "Fam193a"       "Klf3"          "Chic2"        
## [109] "Gsx2"          "Epha5"         "Shroom3"       "Mn1"          
## [113] "Gatsl2"        "St7"           "Zfp800"        "Cpa4"         
## [117] "Mest"          "Ptn"           "Ndnf"          "Tcf7l1"       
## [121] "Lrrtm1"        "Prokr1"        "Wnt7a"         "Frmd4b"       
## [125] "Gpr19"         "Bbc3"          "Ttc9b"         "Zfp60"        
## [129] "Gm26604"       "Dbx1"          "Nr2f2"         "Gm2115"       
## [133] "Prss23"        "Lmo1"          "Dkk3"          "Fgfr2"        
## [137] "Fam53b"        "Adgra1"        "Dusp8"         "Cited2"       
## [141] "Map7"          "Ahi1"          "Marcks"        "Hsf2"         
## [145] "Smpdl3a"       "Jmjd1c"        "Prmt2"         "Nuak1"        
## [149] "Timp3"         "Cep290"        "Phlda1"        "Sox1"         
## [153] "Csmd1"         "Sfrp1"         "Zfp703"        "Nrg1"         
## [157] "Rwdd4a"        "Palld"         "Pgpep1"        "Neto2"        
## [161] "Tppp3"         "Abhd4"         "Ajuba"         "Dpysl2"       
## [165] "Pcdh9"         "Mycbp2"        "Sox21"         "4931406C07Rik"
## [169] "Bmper"         "Ntm"           "Ubash3b"       "Il18"         
## [173] "Herc1"         "Filip1"        "Rbp1"          "Cspg5"        
## [177] "Stac"          "Meis1"         "Sqstm1"        "Sparc"        
## [181] "Hist3h2ba"     "Myo18a"        "Spag9"         "Rdm1"         
## [185] "Tubb2a"        "Cxcl14"        "Ntrk2"         "Fam172a"      
## [189] "Nr2f1"         "Fam84a"        "Id2"           "Meg3"         
## [193] "Itgb8"         "Rai14"         "Sema5a"        "Nell2"        
## [197] "Tmem106c"      "Itgb5"         "Epha3"         "Robo2"        
## [201] "Jam2"          "Eva1c"         "Sox8"          "Ptchd4"       
## [205] "Dlgap1"        "Tmem178"       "Zeb1"          "Cxxc5"        
## [209] "Cdo1"          "Sema6a"        "Megf10"        "Setbp1"       
## [213] "Cnih2"         "Efemp2"        "Gng3"          "Gnaq"         
## [217] "Rorb"          "Fgfbp3"        "Nkx2-3"
Radial.Glia.data <- AddModuleScore(Radial.Glia.data,
                                  genes.list = genes.list,
                                  genes.pool = NULL,
                                  n.bin = 5,
                                  seed.use = 1,
                                  ctrl.size = length(genes.list),
                                  use.k = FALSE,
                                  enrich.name = "E12VP_signature",
                                  random.seed = 1)
# DP enriched genes at E12
genes.list <- Sgenes %>%
              filter(Gene.Clusters %in% c("Clust.4")) %>%
              pull(Gene) %>%
              as.character()

genes.list <- list(genes.list[genes.list %in% rownames(Radial.Glia.data@data)])

genes.list
## [[1]]
##  [1] "Igfbp2"   "Lrrfip1"  "Tgfb2"    "Fjx1"     "Lmo2"     "Mpped2"  
##  [7] "Gpc4"     "Gria2"    "Igfbpl1"  "Gm11266"  "Ubc"      "Aacs"    
## [13] "Cav1"     "Serpinh1" "Ifitm2"   "Dhcr7"    "Rspo3"    "Cd24a"   
## [19] "Hsp90b1"  "Rmst"     "Cd63"     "Calr"     "Mt1"      "Fezf2"   
## [25] "Gnl3"     "Dct"      "Cdon"     "Gsta4"    "Mat2b"    "Slc16a3" 
## [31] "Hist1h3g" "Hist1h1d" "Ctsl"     "Mycn"     "Sp8"      "Alcam"   
## [37] "Gm26917"  "Gm42418"  "Eif1a"    "Wnt8b"
Radial.Glia.data <- AddModuleScore(Radial.Glia.data,
                                  genes.list = genes.list,
                                  genes.pool = NULL,
                                  n.bin = 5,
                                  seed.use = 1,
                                  ctrl.size = length(genes.list),
                                  use.k = FALSE,
                                  enrich.name = "E12DP_signature",
                                  random.seed = 1)

Maturation scores

Tgenes <- read.table("./Progenitors/Temporal.gene.clusters.csv", sep = ";", header = T, row.names = 1)
# VP enriched genes at E12
genes.list <- Tgenes %>%
              filter(Gene.Clusters %in% c("Clust.2")) %>%
              pull(Gene) %>%
              as.character()

genes.list <- list(genes.list[genes.list %in% rownames(Radial.Glia.data@data)])

genes.list
## [[1]]
##  [1] "Nop58"    "Set"      "Hspa5"    "Lhx2"     "Flrt3"    "Wfdc2"   
##  [7] "Bex1"     "Wls"      "Bach2"    "Slc2a1"   "Mcm7"     "Kdelr2"  
## [13] "Tmem176b" "Emx1"     "Lrrn1"    "Socs2"    "Isyna1"   "Syce2"   
## [19] "Mt2"      "Chst2"    "Shmt1"    "Aldoc"    "Gas1"     "H2-K1"   
## [25] "Tgif1"    "Msh6"     "Dmrt3"    "Emx2"
Radial.Glia.data <- AddModuleScore(Radial.Glia.data,
                                  genes.list = genes.list,
                                  genes.pool = NULL,
                                  n.bin = 5,
                                  seed.use = 1,
                                  ctrl.size = length(genes.list),
                                  use.k = FALSE,
                                  enrich.name = "Young_signature",
                                  random.seed = 1)
# DP enriched genes at E12
genes.list <- Tgenes %>%
              filter(Gene.Clusters %in% c("Clust.1")) %>%
              pull(Gene) %>%
              as.character()

genes.list <- list(genes.list[genes.list %in% rownames(Radial.Glia.data@data)])

genes.list
## [[1]]
##  [1] "Gm29260"   "Pantr1"    "Zdbf2"     "Pea15a"    "Zeb2"      "Pax6"     
##  [7] "Insm1"     "Tfap2c"    "Cdh4"      "Nkain4"    "Gpm6b"     "Veph1"    
## [13] "Lxn"       "Trim2"     "Cyr61"     "Ddah1"     "Tox"       "Pou3f2"   
## [19] "Pdpn"      "Limch1"    "Ptprz1"    "Gng12"     "Prkcb"     "Ypel3"    
## [25] "Gpm6a"     "Ncan"      "Tox3"      "Mt3"       "Necab2"    "Rgcc"     
## [31] "Pcdh8"     "Ednrb"     "Elavl3"    "Scg3"      "Myo6"      "Hmgn3"    
## [37] "Eomes"     "Eif1b"     "Gm11627"   "Sox9"      "Hist1h2ap" "Atxn1"    
## [43] "Gadd45g"   "Cplx2"     "Gm17750"   "Nrcam"     "Rtn1"      "Acot1"    
## [49] "Slc1a3"    "Myo10"     "Ctnnd2"    "Snhg18"    "Ncald"     "Kif21a"   
## [55] "Lima1"     "Gap43"     "Zbtb20"    "Ccdc80"    "Cadm2"     "Lix1"     
## [61] "Vit"       "Sncaip"    "Sall3"     "Asrgl1"    "Plce1"
Radial.Glia.data <- AddModuleScore(Radial.Glia.data,
                                  genes.list = genes.list,
                                  genes.pool = NULL,
                                  n.bin = 5,
                                  seed.use = 1,
                                  ctrl.size = length(genes.list),
                                  use.k = FALSE,
                                  enrich.name = "Mature_signature",
                                  random.seed = 1)

Plots

color.pal <- c("#440154FF", "#443A83FF", "#31688EFF", "#21908CFF", "#35B779FF", "#8FD744FF", "#FDE725FF", "#F98C0AFF", "#BB3754FF", "#56106EFF", "#000004FF")

FeaturePlot(object = Radial.Glia.data,
            features.plot = c("E12VP_signature1", "E12DP_signature1", "Young_signature1", "Mature_signature1"),
            cols.use =   color.pal,
            reduction.use = "umap",
            no.axes = T,
            no.legend = T,
            overlay = F,
            dark.theme = F
            )

Plot spatial and temporal marker genes

plot <- FeaturePlot(object = Radial.Glia.data,
                    features.plot =  c("Zcchc12", "Qrfpr", "Sfrp2",
                                       "Mpped2", "Zbtb20", "Gm29260",
                                       "Tfap2c", "Lrrn1", "Nrg1"),
                    cols.use = c("grey90", brewer.pal(9,"YlGnBu")),
                    reduction.use = "umap",
                    no.legend = T,
                    overlay = F,
                    dark.theme = F,
                    do.return =T,
                    no.axes = T)
for (i in 1:length(plot)){
  plot[[i]]$data <- plot[[i]]$data[order(plot[[i]]$data$gene),]
}
cowplot::plot_grid(plotlist = plot[1:9], ncol = 3)

Session Info

#date
format(Sys.time(), "%d %B, %Y, %H,%M")
## [1] "03 mai, 2021, 11,23"
#Packages used
sessionInfo()
## R version 3.6.3 (2020-02-29)
## 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/atlas/libblas.so.3.10.3
## LAPACK: /usr/lib/x86_64-linux-gnu/atlas/liblapack.so.3.10.3
## 
## locale:
##  [1] LC_CTYPE=fr_FR.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=fr_FR.UTF-8        LC_COLLATE=fr_FR.UTF-8    
##  [5] LC_MONETARY=fr_FR.UTF-8    LC_MESSAGES=fr_FR.UTF-8   
##  [7] LC_PAPER=fr_FR.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] limma_3.42.0          Rphenograph_0.99.1    igraph_1.2.5         
##  [4] matrixStats_0.55.0    RColorBrewer_1.1-2    patchwork_0.0.1      
##  [7] ggExtra_0.9           dplyr_0.8.3           reticulate_1.18      
## [10] scrattch.hicat_0.0.16 Seurat_2.3.4          Matrix_1.2-17        
## [13] cowplot_1.0.0         ggplot2_3.2.1         loomR_0.2.1.9000     
## [16] hdf5r_1.3.2.9000      R6_2.4.1             
## 
## loaded via a namespace (and not attached):
##   [1] Rtsne_0.15          colorspace_1.4-1    class_7.3-17       
##   [4] modeltools_0.2-22   ggridges_0.5.1      mclust_5.4.5       
##   [7] htmlTable_1.13.2    base64enc_0.1-3     rstudioapi_0.11    
##  [10] proxy_0.4-23        farver_2.0.1        npsurv_0.4-0       
##  [13] flexmix_2.3-15      bit64_4.0.2         codetools_0.2-16   
##  [16] splines_3.6.3       R.methodsS3_1.7.1   lsei_1.2-0         
##  [19] robustbase_0.93-5   knitr_1.26          zeallot_0.1.0      
##  [22] jsonlite_1.7.0      Formula_1.2-3       ica_1.0-2          
##  [25] cluster_2.1.0       kernlab_0.9-29      png_0.1-7          
##  [28] R.oo_1.23.0         shiny_1.4.0         compiler_3.6.3     
##  [31] httr_1.4.1          backports_1.1.5     fastmap_1.0.1      
##  [34] assertthat_0.2.1    lazyeval_0.2.2      later_1.0.0        
##  [37] lars_1.2            acepack_1.4.1       htmltools_0.5.0    
##  [40] tools_3.6.3         gtable_0.3.0        glue_1.4.1         
##  [43] reshape2_1.4.3      RANN_2.6.1          rappdirs_0.3.1     
##  [46] Rcpp_1.0.5          vctrs_0.2.0         gdata_2.18.0       
##  [49] ape_5.3             nlme_3.1-141        iterators_1.0.12   
##  [52] fpc_2.2-3           gbRd_0.4-11         lmtest_0.9-37      
##  [55] xfun_0.18           stringr_1.4.0       mime_0.7           
##  [58] miniUI_0.1.1.1      lifecycle_0.1.0     irlba_2.3.3        
##  [61] gtools_3.8.1        DEoptimR_1.0-8      MASS_7.3-53        
##  [64] zoo_1.8-6           scales_1.1.0        promises_1.1.0     
##  [67] doSNOW_1.0.18       parallel_3.6.3      yaml_2.2.1         
##  [70] pbapply_1.4-2       gridExtra_2.3       rpart_4.1-15       
##  [73] segmented_1.0-0     latticeExtra_0.6-28 stringi_1.4.6      
##  [76] foreach_1.4.7       checkmate_1.9.4     caTools_1.17.1.2   
##  [79] bibtex_0.4.2        Rdpack_0.11-0       SDMTools_1.1-221.1 
##  [82] rlang_0.4.7         pkgconfig_2.0.3     dtw_1.21-3         
##  [85] prabclus_2.3-1      bitops_1.0-6        evaluate_0.14      
##  [88] lattice_0.20-41     ROCR_1.0-7          purrr_0.3.3        
##  [91] labeling_0.3        htmlwidgets_1.5.1   bit_4.0.4          
##  [94] tidyselect_0.2.5    plyr_1.8.4          magrittr_1.5       
##  [97] snow_0.4-3          gplots_3.0.1.1      Hmisc_4.3-0        
## [100] pillar_1.4.2        foreign_0.8-72      withr_2.1.2        
## [103] fitdistrplus_1.0-14 mixtools_1.1.0      survival_2.44-1.1  
## [106] nnet_7.3-14         tsne_0.1-3          tibble_2.1.3       
## [109] crayon_1.4.0        KernSmooth_2.23-15  rmarkdown_2.5      
## [112] grid_3.6.3          data.table_1.12.6   metap_1.1          
## [115] digest_0.6.25       diptest_0.75-7      xtable_1.8-4       
## [118] httpuv_1.5.2        tidyr_1.0.0         R.utils_2.9.0      
## [121] stats4_3.6.3        munsell_0.5.0

  1. Institute of Psychiatry and Neuroscience of Paris, INSERM U1266, 75014, Paris, France, ↩︎

LS0tCnRpdGxlOiAiU3BhdGlhbCBhbmQgbWF0dXJhdGlvbiBzaWduYXR1cmVzIGFsb25nIGNvcnRpY29nZW5lc2lzIgphdXRob3I6CiAgIC0gTWF0dGhpZXUgTW9yZWF1XltJbnN0aXR1dGUgb2YgUHN5Y2hpYXRyeSBhbmQgTmV1cm9zY2llbmNlIG9mIFBhcmlzLCBJTlNFUk0gVTEyNjYsIDc1MDE0LCBQYXJpcywgRnJhbmNlLCBtYXR0aGlldS5tb3JlYXVAaW5zZXJtLmZyXSBbIVtdKGh0dHBzOi8vb3JjaWQub3JnL3NpdGVzL2RlZmF1bHQvZmlsZXMvaW1hZ2VzL29yY2lkXzE2eDE2LnBuZyldKGh0dHBzOi8vb3JjaWQub3JnLzAwMDAtMDAwMi0yNTkyLTIzNzMpCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkICVCLCAlWScpYCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OiAKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgZGZfcHJpbnQ6IHRpYmJsZQogICAgaGlnaGxpZ2h0OiBoYWRkb2NrCiAgICBpbmNsdWRlczoKICAgICAgaW5faGVhZGVyOiBoZWFkZXIuaHRtbAogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA1CiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogeWVzCi0tLQoKYGBge2NzcywgZWNobz1GQUxTRX0KaDEgewogIGZvbnQtc2l6ZTogMzRweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICNlNjRkMDA7CiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwp9CmgxLnRpdGxlIHsKICBmb250LXNpemU6IDQwcHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIHRleHQtYWxpZ246IGNlbnRlcjsKICB0ZXh0LWRlY29yYXRpb246IG5vbmU7CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDIgewogIGZvbnQtc2l6ZTogMzBweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDMgewogIGZvbnQtc2l6ZTogMjRweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDQgewogIGZvbnQtc2l6ZTogMjBweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDUgewogIGZvbnQtc2l6ZTogMThweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KCi5zY3JvbGwtMTAwIHsKICBtYXgtaGVpZ2h0OiAyMDBweDsKICBvdmVyZmxvdy15OiBhdXRvOwogIGJhY2tncm91bmQtY29sb3I6IGluaGVyaXQ7Cn0KCnAgewogIGZvbnQtc2l6ZTogMTZweDsKfQpgYGAKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGZpZy5hbGlnbiA9ICdjZW50ZXInLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFKQoKc2V0LnNlZWQoMTIzNCkKYGBgCgpBbmFseXNpcyBvZiB0aGUgcGFsbGlhbCBwcm9nZW5pdG9yIGRvbWFpbnMgYWxvbmcgY29ydGljb2dlbmVzaXMgZnJvbSB0aGUgW01vdXNlIEJyYWluIEF0bGFzIC0gRGV2ZWxvcG1lbnRdKGh0dHA6Ly9tb3VzZWJyYWluLm9yZykgcmVsZWFzZWQgYnkgdGhlIExpbm5hcnNzb24ncyBsYWIgb24gSnVseSAyMDIwIFsoQmlvUnhpdiBwcmVwcmludCldKGh0dHBzOi8vd3d3LmJpb3J4aXYub3JnL2NvbnRlbnQvMTAuMTEwMS8yMDIwLjA3LjAyLjE4NDA1MXYxLmZ1bGwucGRmKS4KCgojIGxvYWQgbGlicmFyaWVzCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkobG9vbVIpCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KHNjcmF0dGNoLmhpY2F0KQpsaWJyYXJ5KHJldGljdWxhdGUpCgpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdnRXh0cmEpCgpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKCiNTZXQgZ2dwbG90IHRoZW1lIGNsYXNzaWMKdGhlbWVfc2V0KHRoZW1lX2NsYXNzaWMoKSkKCiNTZXQgcHl0aG9uIGVudiBmb3IgVU1BUCAKdXNlX3B5dGhvbigiL2hvbWUvbWF0dGhpZXUvLmxvY2FsL3NoYXJlL3ItbWluaWNvbmRhL2VudnMvci1yZXRpY3VsYXRlL2Jpbi9weXRob24iKQpgYGAKCiMgRXh0cmFjdGlvbiBvZiBhbm5vdGF0ZWQgcmFkaWFsIGdsaWFsIGNlbGwgZnJvbSBFMTEgdG8gRTE1LjUKCiMjIFJlYWRpbmcgbG9vbSBmaWxlIGNvbnRhaW5pbmcgY2x1c3RlciBtZXRhZGF0YQoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGZpbGUgPC0gY29ubmVjdChmaWxlbmFtZSA9ICIuL0RldmVsb3BpbmdNb3VzZUJyYWluQXRsYXMvZGV2X2FsbC5hZ2cubG9vbSIsCiAgICAgICAgICAgICAgICAgc2tpcC52YWxpZGF0ZSA9VCwKICAgICAgICAgICAgICAgICBtb2RlPSJyKyIpCmBgYAoKV2UgZXh0cmFjdCBhbGwgY2x1c3RlciBhbm5vdGF0ZWQgYXMgInJhZGlhbCBnbGlhIgoKYGBge3J9CkNsdXN0ZXJzQW5ubyA8LSBsZmlsZSRjb2wuYXR0cnMkQ2x1c3RlcnNbXVtsZmlsZSRjb2wuYXR0cnMkQ2xhc3NbXSAlaW4lIGMoIlJhZGlhbCBnbGlhIildCmBgYAoKYGBge3J9CmxmaWxlJGNsb3NlX2FsbCgpCmBgYAoKIyMgUmVhZGluZyBsb29tIGZpbGUgY29udGFpbmluZyBhbGwgbWV0YWRhdGEgYW5kIGNvdW50IHRhYmxlIGZvciB0aGUgMjkyLDQ5NSBoaWdoLXF1YWxpdHkgY2VsbHMKCmBgYHtyfQpsZmlsZSA8LSBjb25uZWN0KGZpbGVuYW1lID0gIi4vRGV2ZWxvcGluZ01vdXNlQnJhaW5BdGxhcy9kZXZfYWxsLmxvb20iLAogICAgICAgICAgICAgICAgIHNraXAudmFsaWRhdGUgPVQsCiAgICAgICAgICAgICAgICAgbW9kZT0icisiKQpgYGAKCiMjIyBQbG90IGV4dHJhY3RlZCBjZWxscyBvbiB0aGUgZ2xvYmFsIHRzbmUKCmBgYHtyfQp0U05FIDwtIHQobGZpbGUkY29sLmF0dHJzJEJUU05FWyxdKQoKdFNORS5kZiA8LSBsZmlsZSRnZXQuYXR0cmlidXRlLmRmKE1BUkdJTiA9IDIsIGF0dHJpYnV0ZXMgPSBjKCJDbHVzdGVycyIsICJBZ2UiKSwgY29sLm5hbWVzID0gIkNlbGxJRCIpCnRTTkUuZGYkR2xpYWxDZWxsIDwtIGlmZWxzZSh0U05FLmRmJENsdXN0ZXJzICVpbiUgQ2x1c3RlcnNBbm5vICYgdFNORS5kZiRBZ2UgJWluJSBjKCJlMTEuMCIsImUxMi4wIiwiZTEyLjUiLCJlMTMuMCIsImUxMy41IiwiZTE0LjAiLCAiZTE0LjUiLCAiZTE1LjAiLCAiZTE1LjUiKSwgIlJhZGlhbCBnbGlhIiwgIk90aGVyQ2VsbHMiKQoKdFNORS5kZiR0U05FLjEgPC0gdFNORVssMV0KdFNORS5kZiR0U05FLjIgPC0gdFNORVssMl0KCmBgYAoKCmBgYHtyIGZpZy5kaW09Yyg3LCA2KX0KcGxvdCA8LWdncGxvdCh0U05FLmRmLCBhZXMoeD10U05FLjEsIHk9dFNORS4yLCBjb2xvdXIgPSBHbGlhbENlbGwpKSArCiAgICAgICAgICBnZW9tX3BvaW50KCBzaXplPTAuMywgc2hhcGU9MTYpICsKICAgICAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9IGMoImdyZXk5MCIsIiNlNzgyM2EiKSkgKwogICAgICAgICAgdGhlbWVfY2xhc3NpYygpKwogICAgICAgICAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSxheGlzLnRpdGxlLnk9ZWxlbWVudF9ibGFuaygpKSArCiAgICAgICAgICBnZ3RpdGxlKGxhYmVsID0gcGFzdGUobmFtZXModGFibGUodFNORS5kZiRHbGlhbENlbGwpWzJdKSwgdGFibGUodFNORS5kZiRHbGlhbENlbGwpWzJdKSkKCnBsb3QkZGF0YSA8LSBwbG90JGRhdGFbb3JkZXIocGxvdCRkYXRhJEdsaWFsQ2VsbCxkZWNyZWFzaW5nID0gRiksXQoKcGxvdApybSh0U05FLmRmLHRTTkUpCmBgYAoKIyMjIEV4dHJhY3QgUmFkaWFsIGdsaWEgY2VsbHMgY291bnQgbWF0cml4IGFuZCBtZXRhZGF0YQoKUmV0cmlldmUgdGhlIGNvdW50IG1hdHJpeAoKYGBge3J9CmNlbGxzIDwtIGxmaWxlJGNvbC5hdHRycyRDbHVzdGVyc1tdICVpbiUgQ2x1c3RlcnNBbm5vICYgbGZpbGUkY29sLmF0dHJzJEFnZVtdICVpbiUgYygiZTExLjAiLCJlMTIuMCIsImUxMi41IiwiZTEzLjAiLCJlMTMuNSIsImUxNC4wIiwgImUxNC41IiwgImUxNS4wIiwgImUxNS41IikKZGF0YS5zdWJzZXQgPC0gbGZpbGVbWyJtYXRyaXgiXV1bIGNlbGxzLCBdCmRhdGEuc3Vic2V0IDwtIHQoZGF0YS5zdWJzZXQpCgpkaW0oZGF0YS5zdWJzZXQpCmBgYAoKUmV0cmlldmUgZ2VuZSBuYW1lcwoKYGBge3J9CmdlbmUubmFtZXMgPC0gbGZpbGVbWyJyb3dfYXR0cnMvR2VuZSJdXVtdCnJvd25hbWVzKGRhdGEuc3Vic2V0KSA8LSBnZW5lLm5hbWVzCmBgYAoKRXh0cmFjdCBtZXRhLmRhdGEgaW5mb3JtYXRpb24KCmBgYHtyfQphdHRycyA8LSBjKCJDZWxsSUQiLCJBZ2UiLCAiQmF0Y2giLCAiQ2hlbWlzdHJ5IiwgIkNoaXBJRCIsIkNsdXN0ZXJzIiwgIlJlZ2lvbiIsICJUaXNzdWUiLCAiUHNldWRvVGlzc3VlIikKYXR0ci5kZiA8LSBsZmlsZSRnZXQuYXR0cmlidXRlLmRmKE1BUkdJTiA9IDIsIGF0dHJpYnV0ZXMgPSBhdHRycywgY29sLm5hbWVzID0gIkNlbGxJRCIpCmF0dHIuZGYgPC0gYXR0ci5kZltjZWxscyxdCnJvd25hbWVzKGF0dHIuZGYpIDwtIGF0dHIuZGYkQ2VsbElECgpjb2xuYW1lcyhkYXRhLnN1YnNldCkgPC0gYXR0ci5kZiRDZWxsSUQKYGBgCgpDbG9zaW5nIGxvb20gb2JqZWN0CgpgYGB7cn0KbGZpbGUkY2xvc2VfYWxsKCkKYGBgCgojIFBlcmZvbSBhbmFseXNpcyB3aXRoIHNldXJhdCB2Mi4zLjQKCiMjIEluaXRpYXRlIGEgU2V1cmF0IG9iamVjdAoKYGBge3J9ClJhdy5kYXRhIDwtIENyZWF0ZVNldXJhdE9iamVjdChyYXcuZGF0YSA9IGRhdGEuc3Vic2V0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmNlbGxzID0gNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5nZW5lcyA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9qZWN0ID0gIlJhZGlhbEdsaWFfRGV2ZWxvcGluZ01vdXNlQnJhaW5BdGxhcyIpCgpybShsaXN0PWxzKClbIWxzKCkgJWluJSBjKCJSYXcuZGF0YSIsImF0dHIuZGYiKV0pCmdjKCkKYGBgCgpXZSBleGNsdWRlIGdlbmVzIHdpdGggZHVwbGljYXRlZCByb3cgbmFtZXMKCmBgYHtyfQpyb3duYW1lcyhSYXcuZGF0YUByYXcuZGF0YSlbZHVwbGljYXRlZChyb3duYW1lcyhSYXcuZGF0YUByYXcuZGF0YSkpXQpgYGAKCmBgYHtyfQpSYXcuZGF0YUByYXcuZGF0YSA8LSBSYXcuZGF0YUByYXcuZGF0YVshZHVwbGljYXRlZChyb3duYW1lcyhSYXcuZGF0YUByYXcuZGF0YSkpLF0KYGBgCgojIyBMb3cgcXVhbGl0eSBjZWxscyBmaWx0ZXJpbmcgYW5kIGRhdGEgbm9ybWFsaXphdGlvbgoKQ29tcHV0ZSByaWJvc29tYWwgYW5kIG1pdG9jaG9uZHJpYWwgdHJhbnNjcmlwdCBmcmFjdGlvbnMgcGVyIGNlbGwKCmBgYHtyfQptaXRvLmdlbmVzIDwtIGdyZXAocGF0dGVybiA9ICJebXQtIiwgeCA9IHJvd25hbWVzKHggPSBSYXcuZGF0YUBkYXRhKSwgdmFsdWUgPSBUUlVFKQpwZXJjZW50Lm1pdG8gPC0gTWF0cml4Ojpjb2xTdW1zKFJhdy5kYXRhQHJhdy5kYXRhW21pdG8uZ2VuZXMsIF0pL01hdHJpeDo6Y29sU3VtcyhSYXcuZGF0YUByYXcuZGF0YSkKUmF3LmRhdGEgPC0gQWRkTWV0YURhdGEob2JqZWN0ID0gUmF3LmRhdGEsIG1ldGFkYXRhID0gcGVyY2VudC5taXRvLCBjb2wubmFtZSA9ICJwZXJjZW50Lm1pdG8iKQoKcmliby5nZW5lcyA8LSBncmVwKHBhdHRlcm4gPSAiKF5ScGx8XlJwc3xeTXJwKSIsIHggPSByb3duYW1lcyh4ID0gUmF3LmRhdGFAZGF0YSksIHZhbHVlID0gVFJVRSkKcGVyY2VudC5yaWJvIDwtIE1hdHJpeDo6Y29sU3VtcyhSYXcuZGF0YUByYXcuZGF0YVtyaWJvLmdlbmVzLCBdKS9NYXRyaXg6OmNvbFN1bXMoUmF3LmRhdGFAcmF3LmRhdGEpClJhdy5kYXRhIDwtIEFkZE1ldGFEYXRhKG9iamVjdCA9IFJhdy5kYXRhLCBtZXRhZGF0YSA9IHBlcmNlbnQucmlibywgY29sLm5hbWUgPSAicGVyY2VudC5yaWJvIikKClJhdy5kYXRhQG1ldGEuZGF0YSA8LSBjYmluZChSYXcuZGF0YUBtZXRhLmRhdGEsIGF0dHIuZGYpCnJtKG1pdG8uZ2VuZXMsIHBlcmNlbnQubWl0byxyaWJvLmdlbmVzLHBlcmNlbnQucmlibykKYGBgCgpgYGB7cn0KQ2VsbC5RQy5TdGF0IDwtIFJhdy5kYXRhQG1ldGEuZGF0YQpgYGAKCiMjIyBGaWx0ZXJpbmcgY2VsbHMgYmFzZWQgb24gbnVtYmVyIG9mIGdlbmVzIGFuZCB0cmFuc2NyaXB0cyBkZXRlY3RlZAoKUmVtb3ZlIGNlbGxzIHdpdGggdG8gZmV3IGdlbmVzIGRldGVjdGVkIG9yIHdpdGggdG8gbWFueSBVTUkgY291bnRzCgpgYGB7cn0KIyBTZXQgbG93IGFuZCBoaWdodCB0aHJlc2hvbGRzIG9uIHRoZSBudW1iZXIgb2YgZGV0ZWN0ZWQgZ2VuZXMKbWluLkdlbmVzLnRociA8LSBtZWRpYW4obG9nMTAoQ2VsbC5RQy5TdGF0JG5HZW5lKSkgLSAzKm1hZChsb2cxMChDZWxsLlFDLlN0YXQkbkdlbmUpKQptYXguR2VuZXMudGhyIDwtIG1lZGlhbihsb2cxMChDZWxsLlFDLlN0YXQkbkdlbmUpKSArIDMqbWFkKGxvZzEwKENlbGwuUUMuU3RhdCRuR2VuZSkpCgojIFNldCBoaWdodCB0aHJlc2hvbGQgb24gdGhlIG51bWJlciBvZiB0cmFuc2NyaXB0cwptYXgublVNSS50aHIgPC0gbWVkaWFuKGxvZzEwKENlbGwuUUMuU3RhdCRuVU1JKSkgKyAzKm1hZChsb2cxMChDZWxsLlFDLlN0YXQkblVNSSkpCgojIEdlbmUvVU1JIHNjYXR0ZXIgcGxvdCBiZWZvcmUgZmlsdGVyaW5nCnAgPC0gZ2dwbG90KENlbGwuUUMuU3RhdCwgYWVzKHg9bG9nMTAoblVNSSksIHk9bG9nMTAobkdlbmUpKSkgKwogICAgICBnZW9tX3BvaW50KCkgKwogICAgICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIikgKwogICAgICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWluLkdlbmVzLnRociksIGNvbG91ciA9ICJncmVlbiIsIGxpbmV0eXBlID0gMikgKwogICAgICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWF4LkdlbmVzLnRociksIGNvbG91ciA9ICJncmVlbiIsIGxpbmV0eXBlID0gMikgKwogICAgICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWF4Lm5VTUkudGhyKSwgY29sb3VyID0gInJlZCIsIGxpbmV0eXBlID0gMikKCmdnTWFyZ2luYWwocCwgdHlwZSA9ICJoaXN0b2dyYW0iLCBmaWxsPSJsaWdodGdyZXkiKQpgYGAKCmBgYHtyfQojIEZpbHRlciBjZWxscyBiYXNlIG9uIGJvdGggbWV0cmljcwpDZWxsLlFDLlN0YXQgPC0gQ2VsbC5RQy5TdGF0ICU+JSBmaWx0ZXIobG9nMTAobkdlbmUpID4gbWluLkdlbmVzLnRocikgJT4lIGZpbHRlcihsb2cxMChuVU1JKSA8IG1heC5uVU1JLnRocikKYGBgCgoKYGBge3J9CnAgPC0gZ2dwbG90KENlbGwuUUMuU3RhdCwgYWVzKHg9bG9nMTAoblVNSSksIHk9bG9nMTAobkdlbmUpKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWluLkdlbmVzLnRociksIGNvbG91ciA9ICJncmVlbiIsIGxpbmV0eXBlID0gMikgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBtYXguR2VuZXMudGhyKSwgY29sb3VyID0gImdyZWVuIiwgbGluZXR5cGUgPSAyKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1heC5uVU1JLnRociksIGNvbG91ciA9ICJyZWQiLCBsaW5ldHlwZSA9IDIpICsKICBhbm5vdGF0ZShnZW9tID0gInRleHQiLCBsYWJlbCA9IHBhc3RlMChkaW0oQ2VsbC5RQy5TdGF0KVsxXSwgIiBRQyBwYXNzZWQgY2VsbHMiKSwgeCA9IDQsIHkgPSAzLjgpCgpnZ01hcmdpbmFsKHAsIHR5cGUgPSAiaGlzdG9ncmFtIiwgZmlsbD0ibGlnaHRncmV5IikKYGBgCgpLZWVwIG9ubHkgdmFsaWQgY2VsbHMKCmBgYHtyfQpSYWRpYWwuR2xpYS5kYXRhIDwtIFN1YnNldERhdGEoUmF3LmRhdGEsIGNlbGxzLnVzZSA9IENlbGwuUUMuU3RhdCRDZWxsSUQgLCBzdWJzZXQucmF3ID0gVCwgIGRvLmNsZWFuID0gRikKcm0obGlzdD1scygpWyFscygpICVpbiUgYygiUmFkaWFsLkdsaWEuZGF0YSIpXSkKYGBgCgoKYGBge3J9CiMgUGxvdCBmaW5hbCBRQyBtZXRyaWNzClZsblBsb3Qob2JqZWN0ID0gUmFkaWFsLkdsaWEuZGF0YSwKICAgICAgICBmZWF0dXJlcy5wbG90ID0gYygibkdlbmUiLCJuVU1JIiwgInBlcmNlbnQubWl0byIsICJwZXJjZW50LnJpYm8iKSwKICAgICAgICBjb2xzLnVzZSA9IGMoIiNlYmNiMmUiLCAiIzllYzIyZiIsICIjYTk5NjFiIiwgIiNjYzNhMWIiLCAiI2NjODc3OCIgLCAiI2QxNGM4ZCIsIiM0Y2FiZGMiLCAiIzVhYjc5MyIsICIjZTc4MjNhIiksCiAgICAgICAgbkNvbCA9IDIsIHBvaW50LnNpemUudXNlID0gMCwgZ3JvdXAuYnkgPSAiQWdlIikKYGBgCgojIyMgTm9ybWFsaXphdGlvbiBhbmQgc2NhbGluZwoKR2VuZSBmaWx0ZXJpbmcKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9ClJhZGlhbC5HbGlhLmRhdGFAcmF3LmRhdGEgPC0gUmFkaWFsLkdsaWEuZGF0YUByYXcuZGF0YVshZHVwbGljYXRlZChyb3duYW1lcyhSYWRpYWwuR2xpYS5kYXRhQHJhdy5kYXRhKSksXQoKbnVtLmNlbGxzIDwtIE1hdHJpeDo6cm93U3VtcyhSYWRpYWwuR2xpYS5kYXRhQHJhdy5kYXRhID4gMCkKZ2VuZXMudXNlIDwtIG5hbWVzKHggPSBudW0uY2VsbHNbd2hpY2goeCA9IG51bS5jZWxscyA+PSAxMCldKQpSYWRpYWwuR2xpYS5kYXRhQHJhdy5kYXRhIDwtIFJhZGlhbC5HbGlhLmRhdGFAcmF3LmRhdGFbZ2VuZXMudXNlLCBdClJhZGlhbC5HbGlhLmRhdGFAZGF0YSA8LSBSYWRpYWwuR2xpYS5kYXRhQGRhdGFbZ2VuZXMudXNlLCBdCmBgYApOb3JtYWxpemF0aW9uCgpgYGB7cn0KUmFkaWFsLkdsaWEuZGF0YSA8LSBOb3JtYWxpemVEYXRhKG9iamVjdCA9IFJhZGlhbC5HbGlhLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtYWxpemF0aW9uLm1ldGhvZCA9ICJMb2dOb3JtYWxpemUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlLmZhY3RvciA9IHJvdW5kKG1lZGlhbihSYWRpYWwuR2xpYS5kYXRhQG1ldGEuZGF0YSRuVU1JKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNwbGF5LnByb2dyZXNzID0gRikKYGBgCgpgYGB7ciBjbGFzcy5vdXRwdXQ9InNjcm9sbC0xMDAifQpSYWRpYWwuR2xpYS5kYXRhIDwtIEZpbmRWYXJpYWJsZUdlbmVzKG9iamVjdCA9IFJhZGlhbC5HbGlhLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4uZnVuY3Rpb24gPSBFeHBNZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNwZXJzaW9uLmZ1bmN0aW9uID0gTG9nVk1SLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4Lmxvdy5jdXRvZmYgPSAwLjAxMjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHguaGlnaC5jdXRvZmYgPSAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5LmN1dG9mZiA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvLnBsb3QgPSBGLCBkaXNwbGF5LnByb2dyZXNzID0gVCkKYGBgCgojIyBBc3NpZ24gQ2VsbC1DeWNsZSBTY29yZQoKYGBge3J9CnMuZ2VuZXMgPC0gYygiTWNtNSIsICJQY25hIiwgIlR5bTUiLCAiRmVuMSIsICJNY20yIiwgIk1jbTQiLCAiUnJtMSIsICJVbmciLAogICAgICAgICAgICAgIkdpbnMyIiwgIk1jbTYiLCAiQ2RjYTciLCAiRHRsIiwgIlByaW0xIiwgIlVocmYxIiwgIk1sZjFpcCIsCiAgICAgICAgICAgICAiSGVsbHMiLCAiUmZjMiIsICJSYXAyIiwgIk5hc3AiLCAiUmFkNTFhcDEiLCAiR21ubiIsICJXZHI3NiIsICJTbGJwIiwKICAgICAgICAgICAgICJDY25lMiIsICJVYnI3IiwgIlBvbGQzIiwgIk1zaDIiLCAiQXRhZDIiLCAiUmFkNTEiLCAiUnJtMiIsICJDZGM0NSIsCiAgICAgICAgICAgICAiQ2RjNiIsICJFeG8xIiwgIlRpcGluIiwgIkRzY2MxIiwgIkJsbSIsICIgQ2FzcDhhcDIiLCAiVXNwMSIsICJDbHNwbiIsCiAgICAgICAgICAgICAiUG9sYTEiLCAiQ2hhZjFiIiwgIkJyaXAxIiwgIkUyZjgiKQoKZzJtLmdlbmVzIDwtIGMoIkhtZ2IyIiwgIkRkazEiLCJOdXNhcDEiLCAiVWJlMmMiLCAiQmlyYzUiLCAiVHB4MiIsICJUb3AyYSIsICJOZGM4MCIsCiAgICAgICAgICAgICAgICJDa3MyIiwgIk51ZjIiLCAiQ2tzMWIiLCAiTWtpNjciLCAiVG1wbyIsICIgQ2VucGsiLCAiVGFjYzMiLCAiRmFtNjRhIiwKICAgICAgICAgICAgICAgIlNtYzQiLCAiQ2NuYjIiLCAiQ2thcDJsIiwgIkNrYXAyIiwgIkF1cmtiIiwgIkJ1YjEiLCAiS2lmMTEiLCAiQW5wMzJlIiwKICAgICAgICAgICAgICAgIlR1YmI0YiIsICJHdHNlMSIsICJraWYyMGIiLCAiSGp1cnAiLCAiQ2RjYTMiLCAiSG4xIiwgIkNkYzIwIiwgIlR0ayIsICJDZGMyNWMiLAogICAgICAgICAgICAgICAia2lmMmMiLCAiUmFuZ2FwMSIsICJOY2FwZDIiLCAiRGxnYXA1IiwgIkNkY2EyIiwgIkNkY2E4IiwgIkVjdDIiLCAiS2lmMjMiLCAiSG1tciIsCiAgICAgICAgICAgICAgICJBdXJrYSIsICJQc3JjMSIsICJBbmxuIiwgIkxiciIsICJDa2FwNSIsICJDZW5wZSIsICJDdGNmIiwgIk5lazIiLCAiRzJlMyIsICJHYXMybDMiLCAiQ2J4NSIsICJDZW5wYSIpCgpSYWRpYWwuR2xpYS5kYXRhPC0gQ2VsbEN5Y2xlU2NvcmluZyhvYmplY3QgPSBSYWRpYWwuR2xpYS5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzLmdlbmVzID0gcy5nZW5lcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZzJtLmdlbmVzID0gZzJtLmdlbmVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXQuaWRlbnQgPSBGKQoKUmFkaWFsLkdsaWEuZGF0YUBtZXRhLmRhdGEkQ0MuRGlmZmVyZW5jZSA8LSBSYWRpYWwuR2xpYS5kYXRhQG1ldGEuZGF0YSRTLlNjb3JlIC0gUmFkaWFsLkdsaWEuZGF0YUBtZXRhLmRhdGEkRzJNLlNjb3JlCmBgYAoKYGBge3J9ClZsblBsb3Qob2JqZWN0ID0gUmFkaWFsLkdsaWEuZGF0YSwKICAgICAgICBmZWF0dXJlcy5wbG90ID0gYygiUy5TY29yZSIsICJHMk0uU2NvcmUiLCJDQy5EaWZmZXJlbmNlIiAsInBlcmNlbnQucmlibyIpLAogICAgICAgIGNvbHMudXNlID0gYygiI2ViY2IyZSIsICIjOWVjMjJmIiwgIiNhOTk2MWIiLCAiI2NjM2ExYiIsICIjY2M4Nzc4IiAsICIjZDE0YzhkIiwiIzRjYWJkYyIsICIjNWFiNzkzIiwgIiNlNzgyM2EiKSwKICAgICAgICBuQ29sID0gMiwgcG9pbnQuc2l6ZS51c2UgPSAwLCBncm91cC5ieSA9ICJBZ2UiKQpgYGAKCiMjIERhdGEgc2NhbGluZyBhbmQgY2VsbCBjeWNsZSByZWdyZXNzaW9uCgpgYGB7ciBjbGFzcy5vdXRwdXQ9InNjcm9sbC0xMDAifQpSYWRpYWwuR2xpYS5kYXRhIDwtIFNjYWxlRGF0YShvYmplY3QgPSBSYWRpYWwuR2xpYS5kYXRhLAogICAgICAgICAgICAgICAgICAgICB2YXJzLnRvLnJlZ3Jlc3MgPSBjKCJDQy5EaWZmZXJlbmNlIiwicGVyY2VudC5taXRvIiwibkdlbmUiLCAiblVNSSIpLAogICAgICAgICAgICAgICAgICAgICBkaXNwbGF5LnByb2dyZXNzID0gVCkKYGBgCgojIERpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbgoKIyMgUENBIGFuZCBVTUFQCgpgYGB7cn0KUmFkaWFsLkdsaWEuZGF0YSA8LSBSdW5QQ0Eob2JqZWN0ID0gUmFkaWFsLkdsaWEuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICBwY3MuY29tcHV0ZSA9IDMwLAogICAgICAgICAgICAgICAgICAgICAgICAgIGRvLnByaW50ID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICBwY3MucHJpbnQgPSBGKQpgYGAKCgpgYGB7cn0Kcm0obGlzdD1scygpWyFscygpICVpbiUgYygiUmFkaWFsLkdsaWEuZGF0YSIpXSkKZ2MoKQpgYGAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9ClJhZGlhbC5HbGlhLmRhdGEgPC0gUnVuVU1BUChSYWRpYWwuR2xpYS5kYXRhLCBkaW1zLnVzZSA9IDE6MzAsIG5fbmVpZ2hib3JzID0gOCwgbWF4LmRpbSA9IDIpCmBgYAoKIyMgRmVhdHVyZXMgcGxvdAoKIyMjIEFnZSwgUmVnaW9uLCBUaXNzdWUsIFBzZXVkby10aXNzdWUKCiMjIyMgQWdlCgpgYGB7cn0KRGltUGxvdChSYWRpYWwuR2xpYS5kYXRhLAogICAgICAgIHJlZHVjdGlvbi51c2UgPSAidW1hcCIsCiAgICAgICAgZ3JvdXAuYnkgPSBjKCJBZ2UiKSwKICAgICAgICBjb2xzLnVzZSA9IGMoIiNlYmNiMmUiLCAiIzllYzIyZiIsICIjYTk5NjFiIiwgIiNjYzNhMWIiLCAiI2NjODc3OCIgLCAiI2QxNGM4ZCIsIiM0Y2FiZGMiLCAiIzVhYjc5MyIsICIjZTc4MjNhIiksCiAgICAgICAgZGltLjEgPSAxLAogICAgICAgIGRpbS4yID0gMiwKICAgICAgICBkby5sYWJlbD1ULAogICAgICAgIGxhYmVsLnNpemUgPSA0LAogICAgICAgIG5vLmF4ZXMgPSBULAogICAgICAgIG5vLmxlZ2VuZCA9IEYpCmBgYAoKIyMjIyBSZWdpb24KCmBgYHtyfQpEaW1QbG90KFJhZGlhbC5HbGlhLmRhdGEsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJ1bWFwIiwKICAgICAgICBncm91cC5ieSA9IGMoIlJlZ2lvbiIpLAogICAgICAgIGNvbHMudXNlID0gYygiI2ViY2IyZSIsICIjOWVjMjJmIiwgIiNhOTk2MWIiLCAiI2NjM2ExYiIsICIjY2M4Nzc4IiAsICIjZDE0YzhkIiwiIzRjYWJkYyIsICIjNWFiNzkzIiwgIiNlNzgyM2EiKSwKICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgZGltLjIgPSAyLAogICAgICAgIGRvLmxhYmVsPVQsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDQsCiAgICAgICAgbm8uYXhlcyA9IFQsCiAgICAgICAgbm8ubGVnZW5kID0gRikKYGBgCgojIyMjIFRpc3N1ZQoKYGBge3J9CkRpbVBsb3QoUmFkaWFsLkdsaWEuZGF0YSwKICAgICAgICByZWR1Y3Rpb24udXNlID0gInVtYXAiLAogICAgICAgIGdyb3VwLmJ5ID0gYygiVGlzc3VlIiksCiAgICAgICAgY29scy51c2UgPSBjKCIjZWJjYjJlIiwgIiM5ZWMyMmYiLCAiI2E5OTYxYiIsICIjY2MzYTFiIiwgIiNjYzg3NzgiICwgIiNkMTRjOGQiLCIjNGNhYmRjIiwgIiM1YWI3OTMiLCAiI2U3ODIzYSIpLAogICAgICAgIGRpbS4xID0gMSwKICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICBsYWJlbC5zaXplID0gNCwKICAgICAgICBuby5heGVzID0gVCwKICAgICAgICBuby5sZWdlbmQgPSBGKQpgYGAKCiMjIyMgUHNldWRvVGlzc3VlCgpgYGB7cn0KRGltUGxvdChSYWRpYWwuR2xpYS5kYXRhLAogICAgICAgIHJlZHVjdGlvbi51c2UgPSAidW1hcCIsCiAgICAgICAgZ3JvdXAuYnkgPSBjKCJQc2V1ZG9UaXNzdWUiKSwKICAgICAgICBjb2xzLnVzZSA9IGMoIiNlYmNiMmUiLCAiIzllYzIyZiIsICIjYTk5NjFiIiwgIiNjYzNhMWIiLCAiI2NjODc3OCIgLCAiI2QxNGM4ZCIsIiM0Y2FiZGMiLCAiIzVhYjc5MyIsICIjZTc4MjNhIiksCiAgICAgICAgZGltLjEgPSAxLAogICAgICAgIGRpbS4yID0gMiwKICAgICAgICBkby5sYWJlbD1ULAogICAgICAgIGxhYmVsLnNpemUgPSA0LAogICAgICAgIG5vLmF4ZXMgPSBULAogICAgICAgIG5vLmxlZ2VuZCA9IEYpCmBgYAoKIyMjIE1ham9yIHJhZGlhbCBnbGlhIHBvcHVsYXRpb24gbWFrZXJzCgpgYGB7ciBmaWcuc2hvdz0naGlkZSd9CnBsb3QgPC0gRmVhdHVyZVBsb3Qob2JqZWN0ID0gUmFkaWFsLkdsaWEuZGF0YSwKICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcy5wbG90ID0gIGMoIkZveGcxIiwiR3N4MiIsIk90eDIiLCAiT2xpZzIiLCAiRGx4MiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRmYXAyYyIsICJEbXJ0YTIiLCAiRmV6ZjIiLCAiUGF4NiIsIkVteDEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTaGgiLCAiUnNwbzIiLCJTZnJwMiIsICJGZ2Y4IiwgIlFyZnByIiksCiAgICAgICAgICAgICAgICAgICAgY29scy51c2UgPSBjKCJncmV5OTAiLCBicmV3ZXIucGFsKDksIllsR25CdSIpKSwKICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24udXNlID0gInVtYXAiLAogICAgICAgICAgICAgICAgICAgIG5vLmxlZ2VuZCA9IFQsCiAgICAgICAgICAgICAgICAgICAgb3ZlcmxheSA9IEYsCiAgICAgICAgICAgICAgICAgICAgZGFyay50aGVtZSA9IEYsCiAgICAgICAgICAgICAgICAgICAgZG8ucmV0dXJuID1ULAogICAgICAgICAgICAgICAgICAgIG5vLmF4ZXMgPSBUKQoKCmZvciAoaSBpbiAxOmxlbmd0aChwbG90KSl7CiAgcGxvdFtbaV1dJGRhdGEgPC0gcGxvdFtbaV1dJGRhdGFbb3JkZXIocGxvdFtbaV1dJGRhdGEkZ2VuZSksXQp9CmBgYAoKYGBge3J9CmNvd3Bsb3Q6OnBsb3RfZ3JpZChwbG90bGlzdCA9IHBsb3RbMToxNV0sIG5jb2wgPSA1KQpgYGAKCiMgRXh0cmFjdCBGb3JicmFpbiBjZWxscwoKYGBge3J9CkZvcmJyYWluLmNlbGxzIDwtIFJhZGlhbC5HbGlhLmRhdGFAbWV0YS5kYXRhICU+JSBmaWx0ZXIoUmVnaW9uID09ICJGb3JlYnJhaW4iKSAlPiUgcHVsbChDZWxsSUQpCgpSYWRpYWwuR2xpYS5kYXRhIDwtIFN1YnNldERhdGEoUmFkaWFsLkdsaWEuZGF0YSwgY2VsbHMudXNlID0gRm9yYnJhaW4uY2VsbHMgLCBzdWJzZXQucmF3ID0gVCwgIGRvLmNsZWFuID0gRikKcm0obGlzdD1scygpWyFscygpICVpbiUgYygiUmFkaWFsLkdsaWEuZGF0YSIpXSkKYGBgCgojIyBOb3JtYWxpemF0aW9uIGFuZCBzY2FsaW5nCgpHZW5lIGZpbHRlcmluZwoKYGBge3J9Cm51bS5jZWxscyA8LSBNYXRyaXg6OnJvd1N1bXMoUmFkaWFsLkdsaWEuZGF0YUByYXcuZGF0YSA+IDApCmdlbmVzLnVzZSA8LSBuYW1lcyh4ID0gbnVtLmNlbGxzW3doaWNoKHggPSBudW0uY2VsbHMgPj0gMTApXSkKUmFkaWFsLkdsaWEuZGF0YUByYXcuZGF0YSA8LSBSYWRpYWwuR2xpYS5kYXRhQHJhdy5kYXRhW2dlbmVzLnVzZSwgXQpSYWRpYWwuR2xpYS5kYXRhQGRhdGEgPC0gUmFkaWFsLkdsaWEuZGF0YUBkYXRhW2dlbmVzLnVzZSwgXQpgYGAKCk5vcm1hbGl6YXRpb24KCmBgYHtyfQpSYWRpYWwuR2xpYS5kYXRhIDwtIE5vcm1hbGl6ZURhdGEob2JqZWN0ID0gUmFkaWFsLkdsaWEuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIkxvZ05vcm1hbGl6ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGUuZmFjdG9yID0gcm91bmQobWVkaWFuKFJhZGlhbC5HbGlhLmRhdGFAbWV0YS5kYXRhJG5VTUkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BsYXkucHJvZ3Jlc3MgPSBGKQpgYGAKCmBgYHtyIGNsYXNzLm91dHB1dD0ic2Nyb2xsLTEwMCJ9ClJhZGlhbC5HbGlhLmRhdGEgPC0gRmluZFZhcmlhYmxlR2VuZXMob2JqZWN0ID0gUmFkaWFsLkdsaWEuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhbi5mdW5jdGlvbiA9IEV4cE1lYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BlcnNpb24uZnVuY3Rpb24gPSBMb2dWTVIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHgubG93LmN1dG9mZiA9IDAuMDEyNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeC5oaWdoLmN1dG9mZiA9IDMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkuY3V0b2ZmID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG8ucGxvdCA9IEYsIGRpc3BsYXkucHJvZ3Jlc3MgPSBUKQpgYGAKCiMjIERhdGEgc2NhbGluZyBhbmQgY2VsbCBjeWNsZSByZWdyZXNzaW9uCgpgYGB7ciBjbGFzcy5vdXRwdXQ9InNjcm9sbC0xMDAifQpSYWRpYWwuR2xpYS5kYXRhIDwtIFNjYWxlRGF0YShvYmplY3QgPSBSYWRpYWwuR2xpYS5kYXRhLAogICAgICAgICAgICAgICAgICAgICB2YXJzLnRvLnJlZ3Jlc3MgPSBjKCJDQy5EaWZmZXJlbmNlIiwicGVyY2VudC5taXRvIiwibkdlbmUiLCAiblVNSSIpLAogICAgICAgICAgICAgICAgICAgICBkaXNwbGF5LnByb2dyZXNzID0gVCkKYGBgCgojIyBEaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24KCmBgYHtyfQpSYWRpYWwuR2xpYS5kYXRhIDwtIFJ1blBDQShvYmplY3QgPSBSYWRpYWwuR2xpYS5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgIHBjcy5jb21wdXRlID0gMzAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZG8ucHJpbnQgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgIHBjcy5wcmludCA9IEYpCmBgYAoKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9ClJhZGlhbC5HbGlhLmRhdGEgPC0gUnVuVU1BUChSYWRpYWwuR2xpYS5kYXRhLCBkaW1zLnVzZSA9IDE6MzAsIG5fbmVpZ2hib3JzID0gOCwgbWF4LmRpbSA9IDIpCmBgYAoKYGBge3J9CmNvbG9ycyA8LSBjKCIjYjdkMTc0IiwgIiM4M2MzYjgiLCAiIzNlNjlhYyIsCiAgICAgICAgICAgICIjZTQ2YjZiIiwgICIjMDA5ZmRhIiwgIiNjNzczYTciLAogICAgICAgICAgICAiI2VjNzU2ZCIsICIjNzI5M2M4IiwgIiNiNzlmMGIiLAogICAgICAgICAgICAiI2ViY2IyZSIsICIjY2MzYTFiIiwgIiNjYzg3NzgiKQoKRGltUGxvdChSYWRpYWwuR2xpYS5kYXRhLAogICAgICAgIGdyb3VwLmJ5ID0gIkFnZSIsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJ1bWFwIiwKICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgZGltLjIgPSAyLAogICAgICAgIGRvLmxhYmVsPVQsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDQsCiAgICAgICAgbm8ubGVnZW5kID0gRiwKICAgICAgICBuby5heGVzID0gVCwKICAgICAgICBjb2xzLnVzZSA9IHJlcChjKCIjYmRkOGVmIiwgIiM2ZGI4ZTIiLCAiIzM1N2ViYyIsICIjMWM0ODk2IiksZWFjaD0yKSkKYGBgCgpgYGB7cn0KRGltUGxvdChSYWRpYWwuR2xpYS5kYXRhLAogICAgICAgIHJlZHVjdGlvbi51c2UgPSAidW1hcCIsCiAgICAgICAgZ3JvdXAuYnkgPSBjKCJUaXNzdWUiKSwKICAgICAgICBjb2xzLnVzZSA9IGMoIiNlYmNiMmUiLCAiIzllYzIyZiIsICIjYTk5NjFiIiwgIiNjYzNhMWIiLCAiI2NjODc3OCIgLCAiI2QxNGM4ZCIsIiM0Y2FiZGMiLCAiIzVhYjc5MyIsICIjZTc4MjNhIiksCiAgICAgICAgZGltLjEgPSAxLAogICAgICAgIGRpbS4yID0gMiwKICAgICAgICBkby5sYWJlbD1ULAogICAgICAgIGxhYmVsLnNpemUgPSA0LAogICAgICAgIG5vLmF4ZXMgPSBULAogICAgICAgIG5vLmxlZ2VuZCA9IEYpCmBgYApgYGB7cn0Kcm0obGlzdD1scygpWyFscygpICVpbiUgYygiUmFkaWFsLkdsaWEuZGF0YSIpXSkKZ2MoKQpgYGAKCgojIFBlcmZvcm0gaXRlcmF0aXZlIGNsdXN0ZXJpbmcKCiMjIFByZXBhcmUgdGhlIGRhdGFzZXQgZm9yIGNsdXN0ZXJpbmcgd2l0aCBzY3JhdHRjaC5oaWNhdAoKIyMjIEdlbmUgZmlsdGVyaW5nCgpXZSBkZWNpZGVkIHRvIGV4Y2x1ZGUgY2VsbCBjeWNsZSwgcmlib3NvbWFsIGFuZCBtaXRvY2hvbmRyaWFsIGFzc29jaWF0ZWQgZ2VuZXMsIGFzIHdlbGwgYXMgWGlzdCBmb3IgdGhlIGNsdXN0ZXJpbmcgc3RlcC4KCmBgYHtyfQojIEV4Y2x1ZGUgY2VsbCBjeWNsZSBhc3NvY2lhdGVkIGdlbmVzCmNjZ2VuZXMgPC0gYXMuY2hhcmFjdGVyKHJlYWQudGFibGUoIi4vUHJvZ2VuaXRvcnMvQ2VsbEN5Y2xlR2VuZXMuY3N2Iiwgc2VwID0gIjsiKVssMV0pCgojIEV4Y2x1ZGUgZ2VuZXMgZGV0ZWN0ZWQgaW4gbGVzcyB0aGFuIDEwIGNlbGxzCm51bS5jZWxscyA8LSBNYXRyaXg6OnJvd1N1bXMoUmFkaWFsLkdsaWEuZGF0YUBkYXRhID4gMCkKZ2VuZXMudXNlIDwtIG5hbWVzKHggPSBudW0uY2VsbHNbd2hpY2goeCA9IG51bS5jZWxscyA+PSAxMCldKQoKR2VuZXNUb1JlbW92ZSA8LSBjKGdyZXAocGF0dGVybiA9ICIoXlJwbHxeUnBzfF5NcnApIiwgeCA9IGdlbmVzLnVzZSwgdmFsdWUgPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgIGdyZXAocGF0dGVybiA9ICJebXQtIiwgeCA9IGdlbmVzLnVzZSwgdmFsdWUgPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgICJYaXN0IiwgY2NnZW5lcykKCmdlbmVzLnVzZSA8LSBnZW5lcy51c2VbIWdlbmVzLnVzZSAlaW4lIEdlbmVzVG9SZW1vdmVdCmBgYAoKIyMjIE5vcm1hbGl6YXRpb24KCmBgYHtyfQpkZ2VNYXRyaXhfY291bnQgPC0gYXMubWF0cml4KFJhZGlhbC5HbGlhLmRhdGFAcmF3LmRhdGEpW3Jvd25hbWVzKFJhZGlhbC5HbGlhLmRhdGFAcmF3LmRhdGEpICVpbiUgZ2VuZXMudXNlLF0KZGdlTWF0cml4X2NwbSA8LSBjcG0oZGdlTWF0cml4X2NvdW50KQpub3JtLmRhdCA8LSBsb2cyKGRnZU1hdHJpeF9jcG0gKyAxKQpgYGAKCmBgYHtyfQpub3JtLmRhdCA8LSBNYXRyaXgobm9ybS5kYXQsIHNwYXJzZSA9IFRSVUUpCkRhdGEubWF0cml4IDwtIGxpc3QocmF3LmRhdD0gZGdlTWF0cml4X2NvdW50LCBub3JtLmRhdD0gbm9ybS5kYXQpCmF0dGFjaChEYXRhLm1hdHJpeCkKYGBgCgoKYGBge3J9CnJtKGxpc3QgPSBscygpWyFscygpICVpbiUgYygiUmFkaWFsLkdsaWEuZGF0YSIsICJEYXRhLm1hdHJpeCIpXSkKZ2MoKQpgYGAKCiMjIyBGaWx0ZXIgdW53YW50ZWQgc291cmNlcyBvZiB2YXJpYXRpb24KCmBgYHtyfQpnZW5lLmNvdW50cyA8LSBsb2cyKGNvbFN1bXMoYXMubWF0cml4KERhdGEubWF0cml4JG5vcm0uZGF0KSA+IDApKQpuVU1JIDwtIGxvZzIoY29sU3VtcyhEYXRhLm1hdHJpeCRyYXcuZGF0KSkKcGVyY3RNaXRvIDwtIFJhZGlhbC5HbGlhLmRhdGFAbWV0YS5kYXRhJHBlcmNlbnQubWl0bwpwZXJjdFJpYm8gPC0gUmFkaWFsLkdsaWEuZGF0YUBtZXRhLmRhdGEkcGVyY2VudC5yaWJvCmNjcGhhc2VkaWZmIDwtIFJhZGlhbC5HbGlhLmRhdGFAbWV0YS5kYXRhJENDLkRpZmZlcmVuY2UKCnJtLmVpZ2VuIDwtIGFzLm1hdHJpeChjYmluZChnZW5lLmNvdW50cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5VTUksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJjdE1pdG8sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJjdFJpYm8sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjY3BoYXNlZGlmZikpCgpyb3cubmFtZXMocm0uZWlnZW4pIDwtIG5hbWVzKGdlbmUuY291bnRzKQoKY29sbmFtZXMocm0uZWlnZW4pIDwtIGMoImxvZzJuR2VuZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAibG9nMm5VTUkiLAogICAgICAgICAgICAgICAgICAgICAgICAicGVyY3RNaXRvIiwKICAgICAgICAgICAgICAgICAgICAgICAgInBlcmN0UmlibyIsCiAgICAgICAgICAgICAgICAgICAgICAgICJjY3BoYXNlZGlmZiIpCmBgYAoKIyMgU2V0IEl0ZXJhdGl2ZSBjbHVzdGVyaW5nIHBhcmFtZXRlcnMKCmBgYHtyfQojIFBhcmFtZXRlcnMgZm9yIGl0ZXJhdGl2ZSBjbHVzdGVyaW5nCmRlLnBhcmFtIDwtIGRlX3BhcmFtKHBhZGoudGggICAgID0gMC4wMSwgCiAgICAgICAgICAgICAgICAgICAgIGxmYy50aCAgICAgID0gMSwKICAgICAgICAgICAgICAgICAgICAgbG93LnRoICAgICAgPSAxLCAKICAgICAgICAgICAgICAgICAgICAgcTEudGggICAgICAgPSAwLjI1LCAKICAgICAgICAgICAgICAgICAgICAgcTIudGggICAgICAgPSBOVUxMLAogICAgICAgICAgICAgICAgICAgICBxLmRpZmYudGggICA9IDAuNywKICAgICAgICAgICAgICAgICAgICAgZGUuc2NvcmUudGggPSAzMDAsCiAgICAgICAgICAgICAgICAgICAgIG1pbi5jZWxscyA9IDUwKQpgYGAKCiMjIFJ1biBpdGVyYXRpdmUgY2x1c3RlcmluZwoKYGBge3IgY2xhc3Mub3V0cHV0PSJzY3JvbGwtMTAwIn0KCml0ZXIucmVzdWx0IDwtIGl0ZXJfY2x1c3Qobm9ybS5kYXQsIAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50cyA9IHJhdy5kYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGltLm1ldGhvZCA9ICJwY2EiLAogICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5kaW0gPSAzMCwKICAgICAgICAgICAgICAgICAgICAgICAgICBkZS5wYXJhbSA9IGRlLnBhcmFtLAogICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSAidW5kaXJlY3Rpb25hbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgcm0uZWlnZW4gPSBybS5laWdlbiwKICAgICAgICAgICAgICAgICAgICAgICAgICBrLnBhcmFtID0gMTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgcm0udGggPSAwLjcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgdmcucGFkai50aCA9IDAuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAibG91dmFpbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZml4ID0gInRlc3QtaXRlcl9jbHVzdCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZSA9IEYpCgpgYGAKCiMjIE1lcmdlIGNsdXN0ZXJzIG5vdCBkaXNjcmltaW5hdGVkIGJ5IERFR3MKCmBgYHtyfQojIE1lcmdlIGNsdXN0ZXJzIHdoaWNoIGFyZSBub3Qgc2VwYXJhYmxlIGJ5IERFR3MKcmQuZGF0IDwtIHQobm9ybS5kYXRbaXRlci5yZXN1bHQkbWFya2VycyxdKQptZXJnZS5yZXN1bHQgPC0gbWVyZ2VfY2wobm9ybS5kYXQsIAogICAgICAgICAgICAgICAgICAgICAgICAgY2wgPSBpdGVyLnJlc3VsdCRjbCwgCiAgICAgICAgICAgICAgICAgICAgICAgICByZC5kYXQgPSByZC5kYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICBkZS5wYXJhbSA9IGRlLnBhcmFtKQoKY2F0KGxlbmd0aCh1bmlxdWUobWVyZ2UucmVzdWx0JGNsKSksIiBDbHVzdGVyc1xuIikKYGBgCgojIyBQbG90IGNsdXN0ZXJzIG9uIFVNQVAgZW1iZWRkaW5nCgpgYGB7cn0KUmFkaWFsLkdsaWEuZGF0YUBpZGVudCA8LSBhcy5mYWN0b3IobWVyZ2UucmVzdWx0JGNsKQpSYWRpYWwuR2xpYS5kYXRhQG1ldGEuZGF0YSRTY3JhdHRjaGljYXQuaWRlbnQgPC0gYXMuY2hhcmFjdGVyKFJhZGlhbC5HbGlhLmRhdGFAaWRlbnQpCgpjb2xvcnMgPC0gYygiIzY4YjA0MSIsICIjZTNjMTQ4IiwgIiNiN2QxNzQiLCAiIzgzYzNiOCIsICAiIzNlNjlhYyIsICIjZTQ2YjZiIiwiIzAwOWZkYSIsCiAgICAgICAgICAgICIjYzc3M2E3IiwiI2VjNzU2ZCIsICIjNzI5M2M4IiwgIiNiNzlmMGIiLCAiIzNjYTczZiIsIiMzMWI2YmQiLAogICAgICAgICAgICAiI2ViY2IyZSIsICIjOWVjMjJmIiwgIiNhOTk2MWIiLCAiI2NjM2ExYiIsICIjY2M4Nzc4IiAsICIjZDE0YzhkIiwKICAgICAgICAgICAgIiM0Y2FiZGMiLCAiIzVhYjc5MyIsICIjZTc4MjNhIiwiI2U2YmI5YiIsICIjMDQ2YzlhIiwgIiM0Nzg0YTIiICwgIiM0OTkwYzkiKQoKRGltUGxvdChSYWRpYWwuR2xpYS5kYXRhLAogICAgICAgIHJlZHVjdGlvbi51c2UgPSAidW1hcCIsCiAgICAgICAgZGltLjEgPSAxLAogICAgICAgIGRpbS4yID0gMiwKICAgICAgICBkby5sYWJlbD1ULAogICAgICAgIGxhYmVsLnNpemUgPSA0LAogICAgICAgIG5vLmxlZ2VuZCA9IEYsCiAgICAgICAgbm8uYXhlcyA9IFQsCiAgICAgICAgY29scy51c2UgPSBjb2xvcnMpCmBgYAoKYGBge3IgZmlnLnNob3c9J2hpZGUnfQpwbG90IDwtIEZlYXR1cmVQbG90KG9iamVjdCA9IFJhZGlhbC5HbGlhLmRhdGEsCiAgICAgICAgICAgIGZlYXR1cmVzLnBsb3QgPSAgYygiQmFyaGwyIiwgIk90eDIiLCAiRGxrMSIsICJTZnJwMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRm94ZzEiLCAiRW14MSIsICJHc3gyIiwgIk9saWcyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXbnQzYSIsICJSc3BvMyIsICJGZ2Y4IiwgIlNoaCIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgIGNvbHMudXNlID0gYygiZ3JleTkwIiwgYnJld2VyLnBhbCg5LCJZbEduQnUiKSksCiAgICAgICAgICAgIHJlZHVjdGlvbi51c2UgPSAidW1hcCIsCiAgICAgICAgICAgIG5vLmxlZ2VuZCA9IFQsCiAgICAgICAgICAgIG92ZXJsYXkgPSBGLAogICAgICAgICAgICBkYXJrLnRoZW1lID0gRiwKICAgICAgICAgICAgZG8ucmV0dXJuID1ULAogICAgICAgICAgICBuby5heGVzID0gVCkKCmZvciAoaSBpbiAxOmxlbmd0aChwbG90KSl7CiAgcGxvdFtbaV1dJGRhdGEgPC0gcGxvdFtbaV1dJGRhdGFbb3JkZXIocGxvdFtbaV1dJGRhdGEkZ2VuZSksXQp9CmBgYAoKYGBge3IgZmlnLmRpbSA9IGMoOSw2KX0KY293cGxvdDo6cGxvdF9ncmlkKHBsb3RsaXN0ID0gcGxvdFsxOjEyXSwgbmNvbCA9IDQpCmBgYAoKYGBge3J9CnJtKGxpc3QgPSBscygpWyFscygpICVpbiUgYygiUmFkaWFsLkdsaWEuZGF0YSIpXSkKZ2MoKQpgYGAKIyBDb21wdXRlIG1hdHVyYXRpb24gYW5kIHNwYXRpYWwgc2NvcmVzCgpXZSB1c2UgdGhlIGdlbmUgc2lnbmF0dXJlcyBmcm9tIEZpZzYgRSBhbmQgRyB0byBjb21wdXRlIHRoZSBtYXR1cmF0aW9uIG9yIHNwYXRpYWwgc2NvcmVzCgojIyBEb3Jzby1WZW50cmFsIHNjb3JlcwpgYGB7cn0KU2dlbmVzIDwtIHJlYWQudGFibGUoIi4vUHJvZ2VuaXRvcnMvU3BhdGlhbC5nZW5lLmNsdXN0ZXJzLmNzdiIsIHNlcCA9ICI7IiwgaGVhZGVyID0gVCwgcm93Lm5hbWVzID0gMSkKYGBgCgpgYGB7cn0KIyBWUCBlbnJpY2hlZCBnZW5lcyBhdCBFMTIKZ2VuZXMubGlzdCA8LSBTZ2VuZXMgJT4lCiAgICAgICAgICAgICAgZmlsdGVyKEdlbmUuQ2x1c3RlcnMgJWluJSBjKCJDbHVzdC4xIiwgIkNsdXN0LjIiKSkgJT4lCiAgICAgICAgICAgICAgcHVsbChHZW5lKSAlPiUKICAgICAgICAgICAgICBhcy5jaGFyYWN0ZXIoKQoKZ2VuZXMubGlzdCA8LSBsaXN0KGdlbmVzLmxpc3RbZ2VuZXMubGlzdCAlaW4lIHJvd25hbWVzKFJhZGlhbC5HbGlhLmRhdGFAZGF0YSldKQoKZ2VuZXMubGlzdAoKUmFkaWFsLkdsaWEuZGF0YSA8LSBBZGRNb2R1bGVTY29yZShSYWRpYWwuR2xpYS5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZXMubGlzdCA9IGdlbmVzLmxpc3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lcy5wb29sID0gTlVMTCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG4uYmluID0gNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZWQudXNlID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0cmwuc2l6ZSA9IGxlbmd0aChnZW5lcy5saXN0KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZS5rID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbnJpY2gubmFtZSA9ICJFMTJWUF9zaWduYXR1cmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tLnNlZWQgPSAxKQpgYGAKCgpgYGB7cn0KIyBEUCBlbnJpY2hlZCBnZW5lcyBhdCBFMTIKZ2VuZXMubGlzdCA8LSBTZ2VuZXMgJT4lCiAgICAgICAgICAgICAgZmlsdGVyKEdlbmUuQ2x1c3RlcnMgJWluJSBjKCJDbHVzdC40IikpICU+JQogICAgICAgICAgICAgIHB1bGwoR2VuZSkgJT4lCiAgICAgICAgICAgICAgYXMuY2hhcmFjdGVyKCkKCmdlbmVzLmxpc3QgPC0gbGlzdChnZW5lcy5saXN0W2dlbmVzLmxpc3QgJWluJSByb3duYW1lcyhSYWRpYWwuR2xpYS5kYXRhQGRhdGEpXSkKCmdlbmVzLmxpc3QKClJhZGlhbC5HbGlhLmRhdGEgPC0gQWRkTW9kdWxlU2NvcmUoUmFkaWFsLkdsaWEuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVzLmxpc3QgPSBnZW5lcy5saXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZXMucG9vbCA9IE5VTEwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuLmJpbiA9IDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkLnVzZSA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHJsLnNpemUgPSBsZW5ndGgoZ2VuZXMubGlzdCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2UuayA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5yaWNoLm5hbWUgPSAiRTEyRFBfc2lnbmF0dXJlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbS5zZWVkID0gMSkKYGBgCgojIyBNYXR1cmF0aW9uIHNjb3JlcwpgYGB7cn0KVGdlbmVzIDwtIHJlYWQudGFibGUoIi4vUHJvZ2VuaXRvcnMvVGVtcG9yYWwuZ2VuZS5jbHVzdGVycy5jc3YiLCBzZXAgPSAiOyIsIGhlYWRlciA9IFQsIHJvdy5uYW1lcyA9IDEpCmBgYAoKYGBge3J9CiMgVlAgZW5yaWNoZWQgZ2VuZXMgYXQgRTEyCmdlbmVzLmxpc3QgPC0gVGdlbmVzICU+JQogICAgICAgICAgICAgIGZpbHRlcihHZW5lLkNsdXN0ZXJzICVpbiUgYygiQ2x1c3QuMiIpKSAlPiUKICAgICAgICAgICAgICBwdWxsKEdlbmUpICU+JQogICAgICAgICAgICAgIGFzLmNoYXJhY3RlcigpCgpnZW5lcy5saXN0IDwtIGxpc3QoZ2VuZXMubGlzdFtnZW5lcy5saXN0ICVpbiUgcm93bmFtZXMoUmFkaWFsLkdsaWEuZGF0YUBkYXRhKV0pCgpnZW5lcy5saXN0CgpSYWRpYWwuR2xpYS5kYXRhIDwtIEFkZE1vZHVsZVNjb3JlKFJhZGlhbC5HbGlhLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lcy5saXN0ID0gZ2VuZXMubGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVzLnBvb2wgPSBOVUxMLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbi5iaW4gPSA1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZC51c2UgPSAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3RybC5zaXplID0gbGVuZ3RoKGdlbmVzLmxpc3QpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlLmsgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVucmljaC5uYW1lID0gIllvdW5nX3NpZ25hdHVyZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5kb20uc2VlZCA9IDEpCmBgYAoKCmBgYHtyfQojIERQIGVucmljaGVkIGdlbmVzIGF0IEUxMgpnZW5lcy5saXN0IDwtIFRnZW5lcyAlPiUKICAgICAgICAgICAgICBmaWx0ZXIoR2VuZS5DbHVzdGVycyAlaW4lIGMoIkNsdXN0LjEiKSkgJT4lCiAgICAgICAgICAgICAgcHVsbChHZW5lKSAlPiUKICAgICAgICAgICAgICBhcy5jaGFyYWN0ZXIoKQoKZ2VuZXMubGlzdCA8LSBsaXN0KGdlbmVzLmxpc3RbZ2VuZXMubGlzdCAlaW4lIHJvd25hbWVzKFJhZGlhbC5HbGlhLmRhdGFAZGF0YSldKQoKZ2VuZXMubGlzdAoKUmFkaWFsLkdsaWEuZGF0YSA8LSBBZGRNb2R1bGVTY29yZShSYWRpYWwuR2xpYS5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZXMubGlzdCA9IGdlbmVzLmxpc3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lcy5wb29sID0gTlVMTCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG4uYmluID0gNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZWQudXNlID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0cmwuc2l6ZSA9IGxlbmd0aChnZW5lcy5saXN0KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZS5rID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbnJpY2gubmFtZSA9ICJNYXR1cmVfc2lnbmF0dXJlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbS5zZWVkID0gMSkKYGBgCgojIyBQbG90cwoKYGBge3J9CmNvbG9yLnBhbCA8LSBjKCIjNDQwMTU0RkYiLCAiIzQ0M0E4M0ZGIiwgIiMzMTY4OEVGRiIsICIjMjE5MDhDRkYiLCAiIzM1Qjc3OUZGIiwgIiM4RkQ3NDRGRiIsICIjRkRFNzI1RkYiLCAiI0Y5OEMwQUZGIiwgIiNCQjM3NTRGRiIsICIjNTYxMDZFRkYiLCAiIzAwMDAwNEZGIikKCkZlYXR1cmVQbG90KG9iamVjdCA9IFJhZGlhbC5HbGlhLmRhdGEsCiAgICAgICAgICAgIGZlYXR1cmVzLnBsb3QgPSBjKCJFMTJWUF9zaWduYXR1cmUxIiwgIkUxMkRQX3NpZ25hdHVyZTEiLCAiWW91bmdfc2lnbmF0dXJlMSIsICJNYXR1cmVfc2lnbmF0dXJlMSIpLAogICAgICAgICAgICBjb2xzLnVzZSA9ICAgY29sb3IucGFsLAogICAgICAgICAgICByZWR1Y3Rpb24udXNlID0gInVtYXAiLAogICAgICAgICAgICBuby5heGVzID0gVCwKICAgICAgICAgICAgbm8ubGVnZW5kID0gVCwKICAgICAgICAgICAgb3ZlcmxheSA9IEYsCiAgICAgICAgICAgIGRhcmsudGhlbWUgPSBGCiAgICAgICAgICAgICkKYGBgCgojIyBQbG90IHNwYXRpYWwgYW5kIHRlbXBvcmFsIG1hcmtlciBnZW5lcyAKCmBgYHtyIGZpZy5zaG93PSdoaWRlJ30KcGxvdCA8LSBGZWF0dXJlUGxvdChvYmplY3QgPSBSYWRpYWwuR2xpYS5kYXRhLAogICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzLnBsb3QgPSAgYygiWmNjaGMxMiIsICJRcmZwciIsICJTZnJwMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNcHBlZDIiLCAiWmJ0YjIwIiwgIkdtMjkyNjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVGZhcDJjIiwgIkxycm4xIiwgIk5yZzEiKSwKICAgICAgICAgICAgICAgICAgICBjb2xzLnVzZSA9IGMoImdyZXk5MCIsIGJyZXdlci5wYWwoOSwiWWxHbkJ1IikpLAogICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbi51c2UgPSAidW1hcCIsCiAgICAgICAgICAgICAgICAgICAgbm8ubGVnZW5kID0gVCwKICAgICAgICAgICAgICAgICAgICBvdmVybGF5ID0gRiwKICAgICAgICAgICAgICAgICAgICBkYXJrLnRoZW1lID0gRiwKICAgICAgICAgICAgICAgICAgICBkby5yZXR1cm4gPVQsCiAgICAgICAgICAgICAgICAgICAgbm8uYXhlcyA9IFQpCgoKZm9yIChpIGluIDE6bGVuZ3RoKHBsb3QpKXsKICBwbG90W1tpXV0kZGF0YSA8LSBwbG90W1tpXV0kZGF0YVtvcmRlcihwbG90W1tpXV0kZGF0YSRnZW5lKSxdCn0KYGBgCgpgYGB7ciBmaWcuZGltID0gYyg2LDYpfQpjb3dwbG90OjpwbG90X2dyaWQocGxvdGxpc3QgPSBwbG90WzE6OV0sIG5jb2wgPSAzKQpgYGAKCiMgU2Vzc2lvbiBJbmZvCmBgYHtyfQojZGF0ZQpmb3JtYXQoU3lzLnRpbWUoKSwgIiVkICVCLCAlWSwgJUgsJU0iKQoKI1BhY2thZ2VzIHVzZWQKc2Vzc2lvbkluZm8oKQpgYGA=