Load libraries

library(Seurat)
library(princurve)
library(Matrix)
library(dplyr)
library(RColorBrewer)
library(fungible)
library(ggplot2)
library(ggExtra)
library(cowplot)
library(wesanderson)

#Set ggplot theme as classic
theme_set(theme_classic())

Load both datasets

WT <- readRDS("../QC.filtered.clustered.cells.RDS")
KO <- readRDS("./GmncKO.cells.RDS")
#We exclude meninges and immune cells from the KO dataset since we had also excluded theme from the WT
KO <-  subset(KO, idents = c(6:9), invert = T)
WT <- subset(WT, subset = orig.ident == "Hem1")
p1 <- DimPlot(object = WT,
        group.by = "Cell_ident",
        reduction = "spring",
        cols = c("#ebcb2e", #"CR"
            "#e7823a", #"ChP"
            "#4cabdc", # Chp_prog
            "#68b041", #"Dorso-Medial_pallium" 
            "#e46b6b", #"Hem" 
            "#e3c148", #"Medial_pallium"
            "#046c9a", # Pallial
            "#4990c9"#"Thalamic_eminence"
                     )
        )  & NoAxes()

p2 <- DimPlot(KO,
        group.by = "Cell.ident",
        reduction = "spring",
        cols = c("#ebcb2e", #"CR"
            "#e7823a", #"ChP"
            "#4cabdc", # Chp_prog
            "#68b041", #"Dorso-Medial_pallium" 
            "#e46b6b", #"Hem" 
            "#e3c148", #"Medial_pallium"
            "#046c9a", # Pallial
            "#4990c9"#"Thalamic_eminence"
                     )
        )  & NoAxes()

p1 + p2

WT <- NormalizeData(WT, normalization.method = "LogNormalize", scale.factor = 10000, assay = "RNA")
KO <- NormalizeData(KO, normalization.method = "LogNormalize", scale.factor = 10000, assay = "RNA")
WT <- FindVariableFeatures(WT, selection.method = "vst", nfeatures = 3000)
KO <- FindVariableFeatures(KO, selection.method = "vst", nfeatures = 3000)

Integration

WT.KO <- list(WT = WT, KO = KO)

rm(list= ls()[!ls() %in% c("WT.KO")])
gc()
##             used   (Mb) gc trigger   (Mb)   max used   (Mb)
## Ncells   4197456  224.2    7804930  416.9    7804930  416.9
## Vcells 847525831 6466.2 1217970762 9292.4 1201674340 9168.1
features <- SelectIntegrationFeatures(object.list = WT.KO)

WT.KO.integrated <- FindIntegrationAnchors(object.list = WT.KO,
                                           anchor.features = features,
                                           dims = 1:30)
WT.KO.integrated <- IntegrateData(anchorset = WT.KO.integrated,
                                  dims = 1:20)

DefaultAssay(WT.KO.integrated) <- "integrated"

WT.KO.integrated <- ScaleData(WT.KO.integrated, verbose = FALSE)

Generate Spring dimensionality reduction

Export count matrix

dir.create("SpringCoordinates_integrated")
#Export raw expression matrix and gene list to regenerate a spring plot
exprData <- Matrix(as.matrix(WT.KO.integrated@assays$RNA@counts), sparse = TRUE)
writeMM(exprData, "./SpringCoordinates_integrated/ExprData.mtx")
## NULL
# Export gene list
Genelist <- row.names(WT.KO.integrated@assays$RNA@counts)
write.table(Genelist, "./SpringCoordinates_integrated/Genelist.csv", sep="\t", col.names = F, row.names = F, quote = F)
#Export metadata
WT_Cell_ident <- c("WT_Cell_ident", WT.KO.integrated$Cell_ident)
WT_Cell_ident <- paste(WT_Cell_ident, sep=",", collapse=",")

KO_Cell_ident <- c("KO_Cell_ident", as.character(WT.KO.integrated$Cell.ident))
KO_Cell_ident <- paste(KO_Cell_ident, sep=",", collapse=",")

Genotype <- c("Genotype", WT.KO.integrated$orig.ident)
Genotype <- paste(Genotype, sep=",", collapse=",")

Cellgrouping <- rbind(WT_Cell_ident, KO_Cell_ident, Genotype)
write.table(Cellgrouping, "./SpringCoordinates_integrated/Cellgrouping.csv", quote =F, row.names = F, col.names = F)

Import coordinates

spring.coor <- read.table("SpringCoordinates_integrated/coordinates.txt", sep = ",", header = F, row.names = 1)
colnames(spring.coor) <- c("Spring_1", "Spring_2")
Spring.Sym <- function(x){
  x = abs(max(spring.coor$Spring_2)-x)
 }

spring.coor$Spring_2 <- sapply(spring.coor$Spring_2, function(x) Spring.Sym(x))
WT.KO.integrated$Integrated_Spring_1 <- spring.coor$Spring_1
WT.KO.integrated$Integrated_Spring_2 <- spring.coor$Spring_2
spring <- as.matrix(WT.KO.integrated@meta.data %>% select("Integrated_Spring_1", "Integrated_Spring_2"))
  
WT.KO.integrated[["integrated_spring"]] <- CreateDimReducObject(embeddings = spring, key = "Spring_", assay = DefaultAssay(WT.KO.integrated))

Annotate Cajal-Retzius, Pallial neurons and Choroid plexus lineages

WT

WT.KO$WT$Lineage <- sapply(WT.KO$WT$Cell_ident,
                              FUN = function(x) {
                                if (x %in% c("Cajal-Retzius_neurons", "Hem")) {
                                  x = "Cajal-Retzius_neurons"
                                } else if (x %in% c("Pallial_neurons", "Medial_pallium")) {
                                  x = "Pallial_neurons"
                                } else if(x %in% c("ChP", "ChP_progenitors")) {
                                   x =  "Choroid_Plexus"
                                } else {
                                  x = "other"
                                  }
                              })
DimPlot(WT.KO$WT,
        reduction = "spring",
        group.by = "Lineage",
        pt.size = 1,
        cols =   c("#cc391b","#e7823a","#969696","#026c9a")
        ) + NoAxes()

KO

WT.KO$KO$Lineage <- sapply(WT.KO$KO$Cell.ident,
                              FUN = function(x) {
                                if (x %in% c("Neuron_prob.2", "Hem")) {
                                  x = "Cajal-Retzius_neurons"
                                } else if (x %in% c("Neuron_prob.3", "Medial_pallium")) {
                                  x = "Pallial_neurons"
                                } else if (x %in% c("ChP", "ChP_progenitors")) {
                                  x = "Choroid_Plexus"
                                } else {
                                  x = "other"
                                  }
                              })
DimPlot(WT.KO$KO,
        reduction = "spring",
        group.by = "Lineage",
        pt.size = 1,
        cols =   c("#cc391b","#e7823a","#969696","#026c9a")
        ) + NoAxes()

WT.KO.integrated$Lineage <- c(WT.KO$WT$Lineage, WT.KO$KO$Lineage)
DimPlot(WT.KO.integrated,
        reduction = "integrated_spring",
        group.by = "Lineage",
        pt.size = 1,
        cols =   c("#cc391b","#e7823a","#969696","#026c9a")
        ) + NoAxes()

Compute differentiation states scores

WT.KO.integrated <- NormalizeData(WT.KO.integrated,
                                  normalization.method = "LogNormalize",
                                  scale.factor = 10000,
                                  assay = "RNA")

WT.KO.integrated <- ScaleData(WT.KO.integrated,
                              assay = "RNA",
                              verbose = FALSE)

AP

APgenes <- c("Rgcc", "Sparc", "Hes5","Hes1", "Slc1a3",
             "Ddah1", "Ldha", "Hmga2","Sfrp1", "Id4",
             "Creb5", "Ptn", "Lpar1", "Rcn1","Zfp36l1",
             "Sox9", "Sox2", "Nr2e1", "Ttyh1", "Trip6")

WT.KO.integrated <- AddModuleScore(WT.KO.integrated,
                     features = list(APgenes),
                     name = "AP_signature",
                     assay = "RNA")

BP

BPgenes <- c("Eomes", "Igsf8", "Insm1", "Elavl2", "Elavl4",
             "Hes6","Gadd45g", "Neurog2", "Btg2", "Neurog1")

WT.KO.integrated <- AddModuleScore(WT.KO.integrated,
                     features = list(BPgenes),
                     name = "BP_signature",
                     assay = "RNA")

EN

ENgenes <- c("Mfap4", "Nhlh2", "Nhlh1", "Ppp1r14a", "Nav1",
             "Neurod1", "Sorl1", "Svip", "Cxcl12", "Tenm4",
             "Dll3", "Rgmb", "Cntn2", "Vat1")

WT.KO.integrated <- AddModuleScore(WT.KO.integrated,
                     features = list(ENgenes),
                     name = "EN_signature",
                     assay = "RNA")

LN

LNgenes <- c("Snhg11", "Pcsk1n", "Mapt", "Ina", "Stmn4",
             "Gap43", "Tubb2a", "Ly6h","Ptprd", "Mef2c")

WT.KO.integrated <- AddModuleScore(WT.KO.integrated,
                     features = list(LNgenes),
                     name = "LN_signature",
                     assay = "RNA")
WT.KO.integrated$AP_signature <- WT.KO.integrated$AP_signature1
WT.KO.integrated$BP_signature <- WT.KO.integrated$BP_signature1
WT.KO.integrated$EN_signature <- WT.KO.integrated$EN_signature1
WT.KO.integrated$LN_signature <- WT.KO.integrated$LN_signature1
FeaturePlot(object = WT.KO.integrated,
            features = c("AP_signature", "BP_signature",
                              "EN_signature", "LN_signature"),
            pt.size = 0.75,
            cols = rev(brewer.pal(10,"Spectral")),
            reduction = "integrated_spring",
            order = T) & NoAxes() & NoLegend()

Save the object

WT.KO.integrated@meta.data <- WT.KO.integrated@meta.data  %>% dplyr::mutate(Cell.ident.WT = tidyr::replace_na(Cell_ident, "KO"))
WT.KO.integrated@meta.data <- WT.KO.integrated@meta.data  %>% dplyr::mutate(Cell.ident.KO = tidyr::replace_na(Cell.ident, "WT"))

WT.KO.integrated@meta.data <- WT.KO.integrated@meta.data[,c("orig.ident", "nCount_RNA", "nFeature_RNA",
                                                            "Barcodes", "percent.mito", "percent.ribo",
                                                            "Spring_1", "Spring_2", "Cell.ident.WT", "Cell.ident.KO",
                                                            "Integrated_Spring_1", "Integrated_Spring_2",
                                                            "Lineage", "AP_signature", "BP_signature",
                                                            "EN_signature", "LN_signature")]
p1 <- DimPlot(object = WT.KO.integrated,
        group.by = "Cell.ident.WT",
        pt.size = 0.7,
        reduction = "integrated_spring",
        split.by = "orig.ident",
        cols = c("#ebcb2e", #"CR"
            "#e7823a", #"ChP"
            "#4cabdc", # Chp_prog
            "#68b041", #"Dorso-Medial_pallium" 
            "#e46b6b", #"Hem"
            "grey40",
            "#e3c148", #"Medial_pallium"
            "#046c9a", # Pallial
            "#4990c9"#"Thalamic_eminence"
            )
        )  & NoAxes()

p2 <- DimPlot(object = WT.KO.integrated,
        group.by = "Cell.ident.KO",
        pt.size = 0.7,
        reduction = "integrated_spring",
        split.by = "orig.ident",
        cols =  c( "#4cabdc", # Chp_prog
                   "#68b041", #"Dorso-Medial_pallium" 
                   "#e46b6b", #"Hem" 
                   "#e3c148", #"Medial_pallium"
                   "#a9961b",
                   "#ebcb2e",
                   "#046c9a", # Pallial
                   "#4990c9",#"Thalamic_eminence"
            "grey40")
        )  & NoAxes()

p1 / p2

saveRDS(WT.KO.integrated, "./WT_KO.integrated.RDS")
rm(list = ls()[!ls() %in% c("WT.KO.integrated")])
gc()
##             used   (Mb) gc trigger    (Mb)   max used    (Mb)
## Ncells   4278171  228.5    7804930   416.9    7804930   416.9
## Vcells 957793535 7307.4 2644848216 20178.6 2635913545 20110.5

Compute distance between trajectories

WT_KO_trajectories <- subset(WT.KO.integrated, subset = Lineage %in% c("Cajal-Retzius_neurons", "Pallial_neurons"))
DimPlot(WT_KO_trajectories,
        reduction = "integrated_spring",
        group.by = "Lineage",
        split.by = "orig.ident",
        pt.size = 1,
        cols = c("#cc391b", "#026c9a")
        ) + NoAxes()

## Pseudotime WT CR bins

nbreaks = 7
WT.CR <- WT_KO_trajectories@meta.data %>%
                    select("orig.ident", "Barcodes", "Cell.ident.WT","Spring_1", "Spring_2", "Lineage") %>%
                    filter(orig.ident == "Hem1" & Cell.ident.WT == "Cajal-Retzius_neurons")
fit <- principal_curve(as.matrix(WT.CR[,c("Spring_1", "Spring_2")]),
                       smoother='lowess',
                       trace=F,
                       f = 0.7,
                       stretch=0)

WT.CR$Pseudotime <- fit$lambda/max(fit$lambda)

if (cor(WT.CR$Pseudotime, WT_KO_trajectories@assays$RNA@data['Hmga2', WT.CR$Barcodes]) > 0) {
  WT.CR$Pseudotime <- -(WT.CR$Pseudotime - max(WT.CR$Pseudotime))
}

WT.CR$Pseudotime.bins<- cut(WT.CR$Pseudotime, breaks = nbreaks , labels = 1:nbreaks)

Pseudotime WT Pallial bins

WT.Pal <- WT_KO_trajectories@meta.data %>%
                    select("orig.ident", "Barcodes", "Cell.ident.WT","Spring_1", "Spring_2", "Lineage") %>%
                    filter(orig.ident == "Hem1" & Cell.ident.WT == "Pallial_neurons")
fit <- principal_curve(as.matrix(WT.Pal [,c("Spring_1", "Spring_2")]),
                       smoother='lowess',
                       trace=F,
                       f = 0.7,
                       stretch=0)

WT.Pal$Pseudotime <- fit$lambda/max(fit$lambda)

if (cor(WT.Pal$Pseudotime, WT_KO_trajectories@assays$RNA@data['Hmga2', WT.Pal$Barcodes]) > 0) {
  WT.Pal$Pseudotime <- -(WT.Pal$Pseudotime - max(WT.Pal$Pseudotime))
}

WT.Pal$Pseudotime.bins<- cut(WT.Pal$Pseudotime, breaks = nbreaks , labels = 1:nbreaks)

Pseudotime KO CR bins

KO.CR <- WT_KO_trajectories@meta.data %>%
            select("orig.ident", "Barcodes", "Cell.ident.KO","Spring_1", "Spring_2", "Lineage") %>%
            filter(orig.ident == "Gmnc_KO" & Cell.ident.KO == "Neuron_prob.2")
fit <- principal_curve(as.matrix(KO.CR[,c("Spring_1", "Spring_2")]),
                       smoother='lowess',
                       trace=F,
                       f = 0.7,
                       stretch=0)

KO.CR$Pseudotime <- fit$lambda/max(fit$lambda)

if (cor(KO.CR$Pseudotime, WT_KO_trajectories@assays$RNA@data['Hmga2', KO.CR$Barcodes]) > 0) {
  KO.CR$Pseudotime <- -(KO.CR$Pseudotime - max(KO.CR$Pseudotime))
}

KO.CR$Pseudotime.bins<- cut(KO.CR$Pseudotime, breaks = nbreaks , labels = 1:nbreaks)

Pseudotime KO Pallial bins

KO.Pal <- WT_KO_trajectories@meta.data %>%
  select("orig.ident", "Barcodes", "Cell.ident.KO","Spring_1", "Spring_2", "Lineage") %>%
  filter(orig.ident == "Gmnc_KO" & Cell.ident.KO == "Neuron_prob.3")
fit <- principal_curve(as.matrix(KO.Pal [,c("Spring_1", "Spring_2")]),
                       smoother='lowess',
                       trace=F,
                       f = 0.7,
                       stretch=0)

KO.Pal$Pseudotime <- fit$lambda/max(fit$lambda)

if (cor(KO.Pal$Pseudotime, WT_KO_trajectories@assays$RNA@data['Hmga2', KO.Pal$Barcodes]) > 0) {
  KO.Pal$Pseudotime <- -(KO.Pal$Pseudotime - max(KO.Pal$Pseudotime))
}

KO.Pal$Pseudotime.bins<- cut(KO.Pal$Pseudotime, breaks = nbreaks , labels = 1:nbreaks)

Combine pseudotime

p1 <- ggplot(WT.CR, aes(Spring_1, Spring_2)) +
  geom_point(aes(color=Pseudotime), size=2, shape=16) + 
  scale_color_gradientn(colours=rev(colorRampPalette(brewer.pal(n =11, name = "Spectral"))(100)), name='Speudotime score')

p2 <- ggplot(WT.Pal, aes(Spring_1, Spring_2)) +
  geom_point(aes(color=Pseudotime), size=2, shape=16) + 
  scale_color_gradientn(colours=rev(colorRampPalette(brewer.pal(n =11, name = "Spectral"))(100)), name='Speudotime score')

p3 <- ggplot(KO.CR, aes(Spring_1, Spring_2)) +
  geom_point(aes(color=Pseudotime), size=2, shape=16) + 
  scale_color_gradientn(colours=rev(colorRampPalette(brewer.pal(n =11, name = "Spectral"))(100)), name='Speudotime score')

p4 <- ggplot(KO.Pal, aes(Spring_1, Spring_2)) +
  geom_point(aes(color=Pseudotime), size=2, shape=16) + 
  scale_color_gradientn(colours=rev(colorRampPalette(brewer.pal(n =11, name = "Spectral"))(100)), name='Speudotime score')

p1 + p2 + p3 + p4

p1 <- ggplot(WT.CR, aes(Spring_1, Spring_2)) +
  geom_point(aes(color=Pseudotime.bins), size=2, shape=16)

p2 <- ggplot(WT.Pal, aes(Spring_1, Spring_2)) +
  geom_point(aes(color=Pseudotime.bins), size=2, shape=16)

p3 <- ggplot(KO.CR, aes(Spring_1, Spring_2)) +
  geom_point(aes(color=Pseudotime.bins), size=2, shape=16)

p4 <- ggplot(KO.Pal, aes(Spring_1, Spring_2)) +
  geom_point(aes(color=Pseudotime.bins), size=2, shape=16)

p1 + p2 + p3 + p4

traj.data <- rbind(WT.CR[,c("Barcodes", "Pseudotime.bins")], WT.Pal[,c("Barcodes", "Pseudotime.bins")],
                   KO.CR[,c("Barcodes", "Pseudotime.bins")], KO.Pal[,c("Barcodes", "Pseudotime.bins")])

rownames(traj.data) <- traj.data$Barcodes

WT_KO_trajectories$Pseudotime.bins <- sapply(WT_KO_trajectories$Barcodes,
                                              FUN = function(x) {
                                                if (x %in% traj.data$Barcodes) {
                                                  x = traj.data[x,"Pseudotime.bins"]
                                               } else {
                                                  x = 1
                                                  }
                                              })
DimPlot(WT_KO_trajectories,
        reduction = "integrated_spring",
        group.by = "Pseudotime.bins",
        pt.size = 1,
        #cols = c("#cc391b", "#026c9a")
        ) + NoAxes()

Cosine distance between average expression

average scaled expression by lineage and by genotype

# WT Cajal-Retzius
WT_CR <- subset(WT_KO_trajectories, subset = orig.ident == "Hem1" & Lineage == "Cajal-Retzius_neurons")
  
WT_CR.averages <- AverageExpression(WT_CR,
                                    group.by = "Pseudotime.bins",
                                    assays = "integrated",
                                    slot = "scale.data")

# KO Cajal-Retzius
KO_CR <- subset(WT_KO_trajectories, subset = orig.ident == "Gmnc_KO" & Lineage == "Cajal-Retzius_neurons")

KO_CR.averages <- AverageExpression(KO_CR,
                                    group.by = "Pseudotime.bins",
                                    assays = "integrated",
                                    slot = "scale.data")
  
# WT Pallial neurons
WT_Pal <- subset(WT_KO_trajectories, subset = orig.ident == "Hem1" & Lineage == "Pallial_neurons")

WT_Pal.averages <- AverageExpression(WT_Pal,
                                    group.by = "Pseudotime.bins",
                                    assays = "integrated",
                                    slot = "scale.data")
  
# KO Pallial neurons  
KO_Pal <- subset(WT_KO_trajectories, subset = orig.ident == "Gmnc_KO" & Lineage == "Pallial_neurons")

KO_Pal.averages <- AverageExpression(KO_Pal,
                                    group.by = "Pseudotime.bins",
                                    assays = "integrated",
                                    slot = "scale.data")

Distance to WT pallial neurons

# WT CR
Smoothed.point.cor <- pdist::pdist(X= t(WT_CR.averages$integrated),
                                   Y= t(WT_Pal.averages$integrated))

WT.CR_WT.Pal.dist <- diag(as.matrix(Smoothed.point.cor))


Smoothed.point.cor <- pdist::pdist(X= t(WT_CR.averages$integrated),
                                   Y= t(KO_Pal.averages$integrated))

WT.CR_KO.Pal.dist <- diag(as.matrix(Smoothed.point.cor))

Smoothed.point.cor <- pdist::pdist(X= t(WT_CR.averages$integrated),
                                   Y= t(KO_CR.averages$integrated))

WT.CR_KO.CR.dist <- diag(as.matrix(Smoothed.point.cor))

Smoothed.point.cor <- pdist::pdist(X= t(KO_CR.averages$integrated),
                                   Y= t(WT_Pal.averages$integrated))

KO.CR_WT.Pal.dist <- diag(as.matrix(Smoothed.point.cor))

Smoothed.point.cor <- pdist::pdist(X= t(KO_CR.averages$integrated),
                                   Y= t(KO_Pal.averages$integrated))

KO.CR_KO.Pal.dist <- diag(as.matrix(Smoothed.point.cor))

Smoothed.point.cor <- pdist::pdist(X= t(WT_Pal.averages$integrated),
                                   Y= t(KO_Pal.averages$integrated))

WT.Pal_KO.Pal.dist <- diag(as.matrix(Smoothed.point.cor))
data <- data.frame(Distance = c(WT.CR_WT.Pal.dist, WT.CR_KO.Pal.dist, WT.CR_KO.CR.dist,
                                KO.CR_WT.Pal.dist, KO.CR_KO.Pal.dist, WT.Pal_KO.Pal.dist),
                   Trajectory = rep(c("WT.CR_WT.Pal.dist", "WT.CR_KO.Pal.dist", "WT.CR_KO.CR.dist",
                                      "KO.CR_WT.Pal.dist", "KO.CR_KO.Pal.dist", "WT.Pal_KO.Pal.dist"), each=nbreaks),
                   Pseudotime.bin = factor(rep(paste0("Bin_",1:nbreaks), 3),levels = paste0("Bin_",1:nbreaks)))

p1 <- DimPlot(WT_KO_trajectories,
        reduction = "integrated_spring",
        group.by = "Pseudotime.bins",
        pt.size = 1,
        #cols = c("#cc391b", "#026c9a")
        ) + NoAxes()

p2 <- ggplot(data, aes(x= Pseudotime.bin, y= Distance, color= Trajectory, group = Trajectory)) +
              geom_line() +
              geom_point()

p1 + p2

Plot late neurons lineage markers

WT_KO_LN <- subset(WT_KO_trajectories, subset = Pseudotime.bins %in% c(6,7))
DefaultAssay(WT_KO_LN) <- "RNA"

p1 <- DimPlot(WT_KO_LN,
        reduction = "integrated_spring",
        group.by = "Lineage",
        pt.size = 1,
        cols = c("#cc391b", "#026c9a")
        ) + NoAxes()

p2 <- DimPlot(WT_KO_LN,
        reduction = "integrated_spring",
        group.by = "orig.ident",
        pt.size = 1,
        cols = c("#cc391b", "#026c9a")
        ) + NoAxes()

p3 <- FeaturePlot(object = WT_KO_LN,
            features = c("Foxg1", "Zfpm2","Prdm8",
                         "Reln", "Zic5", "Zfp503"),
            pt.size = 1,
            cols = c("grey90", brewer.pal(9,"YlGnBu")),
            reduction = "integrated_spring",
            slot = "data",
            order = T) & NoAxes() & NoLegend()

(p1 + p2) + (p3)

Session Info

#date
format(Sys.time(), "%d %B, %Y, %H,%M")
## [1] "14 June, 2022, 10,59"
#Packages used
sessionInfo()
## R version 4.1.1 (2021-08-10)
## Platform: x86_64-conda-linux-gnu (64-bit)
## Running under: CentOS Linux 7 (Core)
## 
## Matrix products: default
## BLAS/LAPACK: /shared/ifbstor1/software/miniconda/envs/r-4.1.1/lib/libopenblasp-r0.3.18.so
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] wesanderson_0.3.6  cowplot_1.1.1      ggExtra_0.9        ggplot2_3.3.6     
##  [5] fungible_2.2       RColorBrewer_1.1-3 dplyr_1.0.9        Matrix_1.3-4      
##  [9] princurve_2.1.6    sp_1.4-7           SeuratObject_4.1.0 Seurat_4.0.5      
## 
## loaded via a namespace (and not attached):
##   [1] plyr_1.8.7            igraph_1.2.9          GPArotation_2022.4-1 
##   [4] lazyeval_0.2.2        splines_4.1.1         gmp_0.6-2.1          
##   [7] listenv_0.8.0         scattermore_0.8       digest_0.6.29        
##  [10] htmltools_0.5.2       fansi_1.0.3           magrittr_2.0.3       
##  [13] tensor_1.5            cluster_2.1.2         ROCR_1.0-11          
##  [16] globals_0.14.0        matrixStats_0.62.0    spatstat.sparse_2.1-1
##  [19] pdist_1.2             colorspace_2.0-3      ggrepel_0.9.1        
##  [22] xfun_0.31             rgdal_1.5-23          crayon_1.5.1         
##  [25] jsonlite_1.8.0        progressr_0.10.0      spatstat.data_2.2-0  
##  [28] survival_3.2-13       zoo_1.8-10            glue_1.5.1           
##  [31] polyclip_1.10-0       gtable_0.3.0          leiden_0.3.10        
##  [34] future.apply_1.9.0    Rmpfr_0.8-7           abind_1.4-5          
##  [37] scales_1.2.0          mvtnorm_1.1-3         DBI_1.1.2            
##  [40] spatstat.random_2.1-0 miniUI_0.1.1.1        Rcpp_1.0.8.3         
##  [43] viridisLite_0.4.0     xtable_1.8-4          clue_0.3-60          
##  [46] reticulate_1.24       spatstat.core_2.4-2   bit_4.0.4            
##  [49] CVXR_1.0-10           htmlwidgets_1.5.4     httr_1.4.2           
##  [52] ellipsis_0.3.2        ica_1.0-2             pkgconfig_2.0.3      
##  [55] farver_2.1.0          sass_0.4.1            uwot_0.1.11          
##  [58] deldir_1.0-6          utf8_1.2.2            tidyselect_1.1.2     
##  [61] labeling_0.4.2        rlang_1.0.2           reshape2_1.4.4       
##  [64] later_1.3.0           munsell_0.5.0         tools_4.1.1          
##  [67] cli_3.3.0             generics_0.1.2        ggridges_0.5.3       
##  [70] evaluate_0.14         stringr_1.4.0         fastmap_1.1.0        
##  [73] yaml_2.3.5            goftest_1.2-3         knitr_1.37           
##  [76] bit64_4.0.5           fitdistrplus_1.1-8    purrr_0.3.4          
##  [79] RANN_2.6.1            pbapply_1.5-0         future_1.25.0        
##  [82] nlme_3.1-153          mime_0.12             DEoptim_2.2-6        
##  [85] compiler_4.1.1        rstudioapi_0.13       plotly_4.10.0        
##  [88] png_0.1-7             spatstat.utils_2.3-0  tibble_3.1.6         
##  [91] bslib_0.3.1           stringi_1.7.6         highr_0.9            
##  [94] rgeos_0.5-9           lattice_0.20-45       vctrs_0.4.1          
##  [97] pillar_1.7.0          lifecycle_1.0.1       spatstat.geom_2.4-0  
## [100] lmtest_0.9-40         jquerylib_0.1.4       RcppAnnoy_0.0.19     
## [103] data.table_1.14.2     irlba_2.3.5           httpuv_1.6.5         
## [106] patchwork_1.1.1       R6_2.5.1              promises_1.2.0.1     
## [109] KernSmooth_2.23-20    gridExtra_2.3         parallelly_1.31.1    
## [112] nleqslv_3.3.2         codetools_0.2-18      MASS_7.3-54          
## [115] assertthat_0.2.1      withr_2.4.3           sctransform_0.3.3    
## [118] mgcv_1.8-38           parallel_4.1.1        grid_4.1.1           
## [121] rpart_4.1-15          tidyr_1.2.0           Rcsdp_0.1.57.2       
## [124] rmarkdown_2.11        Rtsne_0.16            shiny_1.7.1

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

LS0tCnRpdGxlOiAiSW50ZWdyYXRpb24gb2YgV1QgYW5kIEtPIGRhdGFzZXQiCmF1dGhvcjoKICAgLSBNYXR0aGlldSBNb3JlYXVeW0luc3RpdHV0ZSBvZiBQc3ljaGlhdHJ5IGFuZCBOZXVyb3NjaWVuY2Ugb2YgUGFyaXMsIElOU0VSTSBVMTI2NiwgNzUwMTQsIFBhcmlzLCBGcmFuY2UsIG1hdHRoaWV1Lm1vcmVhdUBpbnNlcm0uZnJdIFshW10oaHR0cHM6Ly9vcmNpZC5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9pbWFnZXMvb3JjaWRfMTZ4MTYucG5nKV0oaHR0cHM6Ly9vcmNpZC5vcmcvMDAwMC0wMDAyLTI1OTItMjM3MykKZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgJUIsICVZJylgIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6IAogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICBkZl9wcmludDogdGliYmxlCiAgICBoaWdobGlnaHQ6IGhhZGRvY2sKICAgIHRoZW1lOiBjb3NtbwogICAgY3NzOiAiLi4vc3R5bGUuY3NzIgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IHllcwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGZpZy5hbGlnbiA9ICdjZW50ZXInLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBjYWNoZS5sYXp5ID0gRkFMU0UpCmBgYAoKIyBMb2FkIGxpYnJhcmllcwoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShTZXVyYXQpCmxpYnJhcnkocHJpbmN1cnZlKQpsaWJyYXJ5KE1hdHJpeCkKbGlicmFyeShkcGx5cikKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkoZnVuZ2libGUpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ0V4dHJhKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkod2VzYW5kZXJzb24pCgojU2V0IGdncGxvdCB0aGVtZSBhcyBjbGFzc2ljCnRoZW1lX3NldCh0aGVtZV9jbGFzc2ljKCkpCmBgYAoKIyBMb2FkIGJvdGggZGF0YXNldHMKCmBgYHtyfQpXVCA8LSByZWFkUkRTKCIuLi9RQy5maWx0ZXJlZC5jbHVzdGVyZWQuY2VsbHMuUkRTIikKS08gPC0gcmVhZFJEUygiLi9HbW5jS08uY2VsbHMuUkRTIikKYGBgCgpgYGB7cn0KI1dlIGV4Y2x1ZGUgbWVuaW5nZXMgYW5kIGltbXVuZSBjZWxscyBmcm9tIHRoZSBLTyBkYXRhc2V0IHNpbmNlIHdlIGhhZCBhbHNvIGV4Y2x1ZGVkIHRoZW1lIGZyb20gdGhlIFdUCktPIDwtICBzdWJzZXQoS08sIGlkZW50cyA9IGMoNjo5KSwgaW52ZXJ0ID0gVCkKV1QgPC0gc3Vic2V0KFdULCBzdWJzZXQgPSBvcmlnLmlkZW50ID09ICJIZW0xIikKYGBgCgoKYGBge3J9CnAxIDwtIERpbVBsb3Qob2JqZWN0ID0gV1QsCiAgICAgICAgZ3JvdXAuYnkgPSAiQ2VsbF9pZGVudCIsCiAgICAgICAgcmVkdWN0aW9uID0gInNwcmluZyIsCiAgICAgICAgY29scyA9IGMoIiNlYmNiMmUiLCAjIkNSIgogICAgICAgICAgICAiI2U3ODIzYSIsICMiQ2hQIgogICAgICAgICAgICAiIzRjYWJkYyIsICMgQ2hwX3Byb2cKICAgICAgICAgICAgIiM2OGIwNDEiLCAjIkRvcnNvLU1lZGlhbF9wYWxsaXVtIiAKICAgICAgICAgICAgIiNlNDZiNmIiLCAjIkhlbSIgCiAgICAgICAgICAgICIjZTNjMTQ4IiwgIyJNZWRpYWxfcGFsbGl1bSIKICAgICAgICAgICAgIiMwNDZjOWEiLCAjIFBhbGxpYWwKICAgICAgICAgICAgIiM0OTkwYzkiIyJUaGFsYW1pY19lbWluZW5jZSIKICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICkgICYgTm9BeGVzKCkKCnAyIDwtIERpbVBsb3QoS08sCiAgICAgICAgZ3JvdXAuYnkgPSAiQ2VsbC5pZGVudCIsCiAgICAgICAgcmVkdWN0aW9uID0gInNwcmluZyIsCiAgICAgICAgY29scyA9IGMoIiNlYmNiMmUiLCAjIkNSIgogICAgICAgICAgICAiI2U3ODIzYSIsICMiQ2hQIgogICAgICAgICAgICAiIzRjYWJkYyIsICMgQ2hwX3Byb2cKICAgICAgICAgICAgIiM2OGIwNDEiLCAjIkRvcnNvLU1lZGlhbF9wYWxsaXVtIiAKICAgICAgICAgICAgIiNlNDZiNmIiLCAjIkhlbSIgCiAgICAgICAgICAgICIjZTNjMTQ4IiwgIyJNZWRpYWxfcGFsbGl1bSIKICAgICAgICAgICAgIiMwNDZjOWEiLCAjIFBhbGxpYWwKICAgICAgICAgICAgIiM0OTkwYzkiIyJUaGFsYW1pY19lbWluZW5jZSIKICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICkgICYgTm9BeGVzKCkKCnAxICsgcDIKYGBgCgpgYGB7cn0KV1QgPC0gTm9ybWFsaXplRGF0YShXVCwgbm9ybWFsaXphdGlvbi5tZXRob2QgPSAiTG9nTm9ybWFsaXplIiwgc2NhbGUuZmFjdG9yID0gMTAwMDAsIGFzc2F5ID0gIlJOQSIpCktPIDwtIE5vcm1hbGl6ZURhdGEoS08sIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIkxvZ05vcm1hbGl6ZSIsIHNjYWxlLmZhY3RvciA9IDEwMDAwLCBhc3NheSA9ICJSTkEiKQpgYGAKCmBgYHtyIGNhY2hlPVRSVUV9CldUIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKFdULCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDMwMDApCktPIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKEtPLCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDMwMDApCmBgYAoKIyBJbnRlZ3JhdGlvbgoKYGBge3J9CldULktPIDwtIGxpc3QoV1QgPSBXVCwgS08gPSBLTykKCnJtKGxpc3Q9IGxzKClbIWxzKCkgJWluJSBjKCJXVC5LTyIpXSkKZ2MoKQpgYGAKYGBge3IgY2FjaGU9VFJVRX0KZmVhdHVyZXMgPC0gU2VsZWN0SW50ZWdyYXRpb25GZWF0dXJlcyhvYmplY3QubGlzdCA9IFdULktPKQoKV1QuS08uaW50ZWdyYXRlZCA8LSBGaW5kSW50ZWdyYXRpb25BbmNob3JzKG9iamVjdC5saXN0ID0gV1QuS08sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbmNob3IuZmVhdHVyZXMgPSBmZWF0dXJlcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSAxOjMwKQpgYGAKCgpgYGB7ciBjYWNoZT1UUlVFfQpXVC5LTy5pbnRlZ3JhdGVkIDwtIEludGVncmF0ZURhdGEoYW5jaG9yc2V0ID0gV1QuS08uaW50ZWdyYXRlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSAxOjIwKQoKRGVmYXVsdEFzc2F5KFdULktPLmludGVncmF0ZWQpIDwtICJpbnRlZ3JhdGVkIgoKV1QuS08uaW50ZWdyYXRlZCA8LSBTY2FsZURhdGEoV1QuS08uaW50ZWdyYXRlZCwgdmVyYm9zZSA9IEZBTFNFKQpgYGAKCiMgR2VuZXJhdGUgU3ByaW5nIGRpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbgoKIyMgRXhwb3J0IGNvdW50IG1hdHJpeAoKYGBge3J9CmRpci5jcmVhdGUoIlNwcmluZ0Nvb3JkaW5hdGVzX2ludGVncmF0ZWQiKQpgYGAKCmBgYHtyfQojRXhwb3J0IHJhdyBleHByZXNzaW9uIG1hdHJpeCBhbmQgZ2VuZSBsaXN0IHRvIHJlZ2VuZXJhdGUgYSBzcHJpbmcgcGxvdApleHByRGF0YSA8LSBNYXRyaXgoYXMubWF0cml4KFdULktPLmludGVncmF0ZWRAYXNzYXlzJFJOQUBjb3VudHMpLCBzcGFyc2UgPSBUUlVFKQp3cml0ZU1NKGV4cHJEYXRhLCAiLi9TcHJpbmdDb29yZGluYXRlc19pbnRlZ3JhdGVkL0V4cHJEYXRhLm10eCIpCmBgYAoKYGBge3J9CiMgRXhwb3J0IGdlbmUgbGlzdApHZW5lbGlzdCA8LSByb3cubmFtZXMoV1QuS08uaW50ZWdyYXRlZEBhc3NheXMkUk5BQGNvdW50cykKd3JpdGUudGFibGUoR2VuZWxpc3QsICIuL1NwcmluZ0Nvb3JkaW5hdGVzX2ludGVncmF0ZWQvR2VuZWxpc3QuY3N2Iiwgc2VwPSJcdCIsIGNvbC5uYW1lcyA9IEYsIHJvdy5uYW1lcyA9IEYsIHF1b3RlID0gRikKYGBgCgpgYGB7cn0KI0V4cG9ydCBtZXRhZGF0YQpXVF9DZWxsX2lkZW50IDwtIGMoIldUX0NlbGxfaWRlbnQiLCBXVC5LTy5pbnRlZ3JhdGVkJENlbGxfaWRlbnQpCldUX0NlbGxfaWRlbnQgPC0gcGFzdGUoV1RfQ2VsbF9pZGVudCwgc2VwPSIsIiwgY29sbGFwc2U9IiwiKQoKS09fQ2VsbF9pZGVudCA8LSBjKCJLT19DZWxsX2lkZW50IiwgYXMuY2hhcmFjdGVyKFdULktPLmludGVncmF0ZWQkQ2VsbC5pZGVudCkpCktPX0NlbGxfaWRlbnQgPC0gcGFzdGUoS09fQ2VsbF9pZGVudCwgc2VwPSIsIiwgY29sbGFwc2U9IiwiKQoKR2Vub3R5cGUgPC0gYygiR2Vub3R5cGUiLCBXVC5LTy5pbnRlZ3JhdGVkJG9yaWcuaWRlbnQpCkdlbm90eXBlIDwtIHBhc3RlKEdlbm90eXBlLCBzZXA9IiwiLCBjb2xsYXBzZT0iLCIpCgpDZWxsZ3JvdXBpbmcgPC0gcmJpbmQoV1RfQ2VsbF9pZGVudCwgS09fQ2VsbF9pZGVudCwgR2Vub3R5cGUpCndyaXRlLnRhYmxlKENlbGxncm91cGluZywgIi4vU3ByaW5nQ29vcmRpbmF0ZXNfaW50ZWdyYXRlZC9DZWxsZ3JvdXBpbmcuY3N2IiwgcXVvdGUgPUYsIHJvdy5uYW1lcyA9IEYsIGNvbC5uYW1lcyA9IEYpCmBgYAoKCiMjIEltcG9ydCBjb29yZGluYXRlcwoKYGBge3J9CnNwcmluZy5jb29yIDwtIHJlYWQudGFibGUoIlNwcmluZ0Nvb3JkaW5hdGVzX2ludGVncmF0ZWQvY29vcmRpbmF0ZXMudHh0Iiwgc2VwID0gIiwiLCBoZWFkZXIgPSBGLCByb3cubmFtZXMgPSAxKQpjb2xuYW1lcyhzcHJpbmcuY29vcikgPC0gYygiU3ByaW5nXzEiLCAiU3ByaW5nXzIiKQpgYGAKCmBgYHtyfQpTcHJpbmcuU3ltIDwtIGZ1bmN0aW9uKHgpewogIHggPSBhYnMobWF4KHNwcmluZy5jb29yJFNwcmluZ18yKS14KQogfQoKc3ByaW5nLmNvb3IkU3ByaW5nXzIgPC0gc2FwcGx5KHNwcmluZy5jb29yJFNwcmluZ18yLCBmdW5jdGlvbih4KSBTcHJpbmcuU3ltKHgpKQpgYGAKCmBgYHtyfQpXVC5LTy5pbnRlZ3JhdGVkJEludGVncmF0ZWRfU3ByaW5nXzEgPC0gc3ByaW5nLmNvb3IkU3ByaW5nXzEKV1QuS08uaW50ZWdyYXRlZCRJbnRlZ3JhdGVkX1NwcmluZ18yIDwtIHNwcmluZy5jb29yJFNwcmluZ18yCmBgYAoKCmBgYHtyfQpzcHJpbmcgPC0gYXMubWF0cml4KFdULktPLmludGVncmF0ZWRAbWV0YS5kYXRhICU+JSBzZWxlY3QoIkludGVncmF0ZWRfU3ByaW5nXzEiLCAiSW50ZWdyYXRlZF9TcHJpbmdfMiIpKQogIApXVC5LTy5pbnRlZ3JhdGVkW1siaW50ZWdyYXRlZF9zcHJpbmciXV0gPC0gQ3JlYXRlRGltUmVkdWNPYmplY3QoZW1iZWRkaW5ncyA9IHNwcmluZywga2V5ID0gIlNwcmluZ18iLCBhc3NheSA9IERlZmF1bHRBc3NheShXVC5LTy5pbnRlZ3JhdGVkKSkKYGBgCgoKIyBBbm5vdGF0ZSBDYWphbC1SZXR6aXVzLCBQYWxsaWFsIG5ldXJvbnMgYW5kIENob3JvaWQgcGxleHVzIGxpbmVhZ2VzCgojIyBXVCAKCmBgYHtyfQpXVC5LTyRXVCRMaW5lYWdlIDwtIHNhcHBseShXVC5LTyRXVCRDZWxsX2lkZW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSBmdW5jdGlvbih4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHggJWluJSBjKCJDYWphbC1SZXR6aXVzX25ldXJvbnMiLCAiSGVtIikpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAiQ2FqYWwtUmV0eml1c19uZXVyb25zIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoeCAlaW4lIGMoIlBhbGxpYWxfbmV1cm9ucyIsICJNZWRpYWxfcGFsbGl1bSIpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gIlBhbGxpYWxfbmV1cm9ucyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoeCAlaW4lIGMoIkNoUCIsICJDaFBfcHJvZ2VuaXRvcnMiKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAgIkNob3JvaWRfUGxleHVzIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gIm90aGVyIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KQpgYGAKCmBgYHtyfQpEaW1QbG90KFdULktPJFdULAogICAgICAgIHJlZHVjdGlvbiA9ICJzcHJpbmciLAogICAgICAgIGdyb3VwLmJ5ID0gIkxpbmVhZ2UiLAogICAgICAgIHB0LnNpemUgPSAxLAogICAgICAgIGNvbHMgPSAgIGMoIiNjYzM5MWIiLCIjZTc4MjNhIiwiIzk2OTY5NiIsIiMwMjZjOWEiKQogICAgICAgICkgKyBOb0F4ZXMoKQpgYGAKCiMjIEtPCgpgYGB7cn0KV1QuS08kS08kTGluZWFnZSA8LSBzYXBwbHkoV1QuS08kS08kQ2VsbC5pZGVudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gZnVuY3Rpb24oeCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh4ICVpbiUgYygiTmV1cm9uX3Byb2IuMiIsICJIZW0iKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9ICJDYWphbC1SZXR6aXVzX25ldXJvbnMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh4ICVpbiUgYygiTmV1cm9uX3Byb2IuMyIsICJNZWRpYWxfcGFsbGl1bSIpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gIlBhbGxpYWxfbmV1cm9ucyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHggJWluJSBjKCJDaFAiLCAiQ2hQX3Byb2dlbml0b3JzIikpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAiQ2hvcm9pZF9QbGV4dXMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAib3RoZXIiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pCmBgYAoKYGBge3J9CkRpbVBsb3QoV1QuS08kS08sCiAgICAgICAgcmVkdWN0aW9uID0gInNwcmluZyIsCiAgICAgICAgZ3JvdXAuYnkgPSAiTGluZWFnZSIsCiAgICAgICAgcHQuc2l6ZSA9IDEsCiAgICAgICAgY29scyA9ICAgYygiI2NjMzkxYiIsIiNlNzgyM2EiLCIjOTY5Njk2IiwiIzAyNmM5YSIpCiAgICAgICAgKSArIE5vQXhlcygpCmBgYAoKYGBge3J9CldULktPLmludGVncmF0ZWQkTGluZWFnZSA8LSBjKFdULktPJFdUJExpbmVhZ2UsIFdULktPJEtPJExpbmVhZ2UpCmBgYAoKYGBge3J9CkRpbVBsb3QoV1QuS08uaW50ZWdyYXRlZCwKICAgICAgICByZWR1Y3Rpb24gPSAiaW50ZWdyYXRlZF9zcHJpbmciLAogICAgICAgIGdyb3VwLmJ5ID0gIkxpbmVhZ2UiLAogICAgICAgIHB0LnNpemUgPSAxLAogICAgICAgIGNvbHMgPSAgIGMoIiNjYzM5MWIiLCIjZTc4MjNhIiwiIzk2OTY5NiIsIiMwMjZjOWEiKQogICAgICAgICkgKyBOb0F4ZXMoKQpgYGAKCiMgQ29tcHV0ZSBkaWZmZXJlbnRpYXRpb24gc3RhdGVzIHNjb3JlcwoKYGBge3J9CldULktPLmludGVncmF0ZWQgPC0gTm9ybWFsaXplRGF0YShXVC5LTy5pbnRlZ3JhdGVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9ybWFsaXphdGlvbi5tZXRob2QgPSAiTG9nTm9ybWFsaXplIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlLmZhY3RvciA9IDEwMDAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXkgPSAiUk5BIikKCldULktPLmludGVncmF0ZWQgPC0gU2NhbGVEYXRhKFdULktPLmludGVncmF0ZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2F5ID0gIlJOQSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBGQUxTRSkKYGBgCgpBUAoKYGBge3J9CkFQZ2VuZXMgPC0gYygiUmdjYyIsICJTcGFyYyIsICJIZXM1IiwiSGVzMSIsICJTbGMxYTMiLAogICAgICAgICAgICAgIkRkYWgxIiwgIkxkaGEiLCAiSG1nYTIiLCJTZnJwMSIsICJJZDQiLAogICAgICAgICAgICAgIkNyZWI1IiwgIlB0biIsICJMcGFyMSIsICJSY24xIiwiWmZwMzZsMSIsCiAgICAgICAgICAgICAiU294OSIsICJTb3gyIiwgIk5yMmUxIiwgIlR0eWgxIiwgIlRyaXA2IikKCldULktPLmludGVncmF0ZWQgPC0gQWRkTW9kdWxlU2NvcmUoV1QuS08uaW50ZWdyYXRlZCwKICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSBsaXN0KEFQZ2VuZXMpLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gIkFQX3NpZ25hdHVyZSIsCiAgICAgICAgICAgICAgICAgICAgIGFzc2F5ID0gIlJOQSIpCmBgYAoKQlAKCmBgYHtyfQpCUGdlbmVzIDwtIGMoIkVvbWVzIiwgIklnc2Y4IiwgIkluc20xIiwgIkVsYXZsMiIsICJFbGF2bDQiLAogICAgICAgICAgICAgIkhlczYiLCJHYWRkNDVnIiwgIk5ldXJvZzIiLCAiQnRnMiIsICJOZXVyb2cxIikKCldULktPLmludGVncmF0ZWQgPC0gQWRkTW9kdWxlU2NvcmUoV1QuS08uaW50ZWdyYXRlZCwKICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSBsaXN0KEJQZ2VuZXMpLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gIkJQX3NpZ25hdHVyZSIsCiAgICAgICAgICAgICAgICAgICAgIGFzc2F5ID0gIlJOQSIpCmBgYAoKRU4KCmBgYHtyfQpFTmdlbmVzIDwtIGMoIk1mYXA0IiwgIk5obGgyIiwgIk5obGgxIiwgIlBwcDFyMTRhIiwgIk5hdjEiLAogICAgICAgICAgICAgIk5ldXJvZDEiLCAiU29ybDEiLCAiU3ZpcCIsICJDeGNsMTIiLCAiVGVubTQiLAogICAgICAgICAgICAgIkRsbDMiLCAiUmdtYiIsICJDbnRuMiIsICJWYXQxIikKCldULktPLmludGVncmF0ZWQgPC0gQWRkTW9kdWxlU2NvcmUoV1QuS08uaW50ZWdyYXRlZCwKICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSBsaXN0KEVOZ2VuZXMpLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gIkVOX3NpZ25hdHVyZSIsCiAgICAgICAgICAgICAgICAgICAgIGFzc2F5ID0gIlJOQSIpCmBgYAoKTE4KCmBgYHtyfQpMTmdlbmVzIDwtIGMoIlNuaGcxMSIsICJQY3NrMW4iLCAiTWFwdCIsICJJbmEiLCAiU3RtbjQiLAogICAgICAgICAgICAgIkdhcDQzIiwgIlR1YmIyYSIsICJMeTZoIiwiUHRwcmQiLCAiTWVmMmMiKQoKV1QuS08uaW50ZWdyYXRlZCA8LSBBZGRNb2R1bGVTY29yZShXVC5LTy5pbnRlZ3JhdGVkLAogICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9IGxpc3QoTE5nZW5lcyksCiAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiTE5fc2lnbmF0dXJlIiwKICAgICAgICAgICAgICAgICAgICAgYXNzYXkgPSAiUk5BIikKYGBgCgpgYGB7cn0KV1QuS08uaW50ZWdyYXRlZCRBUF9zaWduYXR1cmUgPC0gV1QuS08uaW50ZWdyYXRlZCRBUF9zaWduYXR1cmUxCldULktPLmludGVncmF0ZWQkQlBfc2lnbmF0dXJlIDwtIFdULktPLmludGVncmF0ZWQkQlBfc2lnbmF0dXJlMQpXVC5LTy5pbnRlZ3JhdGVkJEVOX3NpZ25hdHVyZSA8LSBXVC5LTy5pbnRlZ3JhdGVkJEVOX3NpZ25hdHVyZTEKV1QuS08uaW50ZWdyYXRlZCRMTl9zaWduYXR1cmUgPC0gV1QuS08uaW50ZWdyYXRlZCRMTl9zaWduYXR1cmUxCmBgYAoKCmBgYHtyfQpGZWF0dXJlUGxvdChvYmplY3QgPSBXVC5LTy5pbnRlZ3JhdGVkLAogICAgICAgICAgICBmZWF0dXJlcyA9IGMoIkFQX3NpZ25hdHVyZSIsICJCUF9zaWduYXR1cmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRU5fc2lnbmF0dXJlIiwgIkxOX3NpZ25hdHVyZSIpLAogICAgICAgICAgICBwdC5zaXplID0gMC43NSwKICAgICAgICAgICAgY29scyA9IHJldihicmV3ZXIucGFsKDEwLCJTcGVjdHJhbCIpKSwKICAgICAgICAgICAgcmVkdWN0aW9uID0gImludGVncmF0ZWRfc3ByaW5nIiwKICAgICAgICAgICAgb3JkZXIgPSBUKSAmIE5vQXhlcygpICYgTm9MZWdlbmQoKQpgYGAKCiMgU2F2ZSB0aGUgb2JqZWN0CgpgYGB7cn0KV1QuS08uaW50ZWdyYXRlZEBtZXRhLmRhdGEgPC0gV1QuS08uaW50ZWdyYXRlZEBtZXRhLmRhdGEgICU+JSBkcGx5cjo6bXV0YXRlKENlbGwuaWRlbnQuV1QgPSB0aWR5cjo6cmVwbGFjZV9uYShDZWxsX2lkZW50LCAiS08iKSkKV1QuS08uaW50ZWdyYXRlZEBtZXRhLmRhdGEgPC0gV1QuS08uaW50ZWdyYXRlZEBtZXRhLmRhdGEgICU+JSBkcGx5cjo6bXV0YXRlKENlbGwuaWRlbnQuS08gPSB0aWR5cjo6cmVwbGFjZV9uYShDZWxsLmlkZW50LCAiV1QiKSkKCldULktPLmludGVncmF0ZWRAbWV0YS5kYXRhIDwtIFdULktPLmludGVncmF0ZWRAbWV0YS5kYXRhWyxjKCJvcmlnLmlkZW50IiwgIm5Db3VudF9STkEiLCAibkZlYXR1cmVfUk5BIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJhcmNvZGVzIiwgInBlcmNlbnQubWl0byIsICJwZXJjZW50LnJpYm8iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU3ByaW5nXzEiLCAiU3ByaW5nXzIiLCAiQ2VsbC5pZGVudC5XVCIsICJDZWxsLmlkZW50LktPIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkludGVncmF0ZWRfU3ByaW5nXzEiLCAiSW50ZWdyYXRlZF9TcHJpbmdfMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJMaW5lYWdlIiwgIkFQX3NpZ25hdHVyZSIsICJCUF9zaWduYXR1cmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRU5fc2lnbmF0dXJlIiwgIkxOX3NpZ25hdHVyZSIpXQoKCmBgYAoKCmBgYHtyfQpwMSA8LSBEaW1QbG90KG9iamVjdCA9IFdULktPLmludGVncmF0ZWQsCiAgICAgICAgZ3JvdXAuYnkgPSAiQ2VsbC5pZGVudC5XVCIsCiAgICAgICAgcHQuc2l6ZSA9IDAuNywKICAgICAgICByZWR1Y3Rpb24gPSAiaW50ZWdyYXRlZF9zcHJpbmciLAogICAgICAgIHNwbGl0LmJ5ID0gIm9yaWcuaWRlbnQiLAogICAgICAgIGNvbHMgPSBjKCIjZWJjYjJlIiwgIyJDUiIKICAgICAgICAgICAgIiNlNzgyM2EiLCAjIkNoUCIKICAgICAgICAgICAgIiM0Y2FiZGMiLCAjIENocF9wcm9nCiAgICAgICAgICAgICIjNjhiMDQxIiwgIyJEb3Jzby1NZWRpYWxfcGFsbGl1bSIgCiAgICAgICAgICAgICIjZTQ2YjZiIiwgIyJIZW0iCiAgICAgICAgICAgICJncmV5NDAiLAogICAgICAgICAgICAiI2UzYzE0OCIsICMiTWVkaWFsX3BhbGxpdW0iCiAgICAgICAgICAgICIjMDQ2YzlhIiwgIyBQYWxsaWFsCiAgICAgICAgICAgICIjNDk5MGM5IiMiVGhhbGFtaWNfZW1pbmVuY2UiCiAgICAgICAgICAgICkKICAgICAgICApICAmIE5vQXhlcygpCgpwMiA8LSBEaW1QbG90KG9iamVjdCA9IFdULktPLmludGVncmF0ZWQsCiAgICAgICAgZ3JvdXAuYnkgPSAiQ2VsbC5pZGVudC5LTyIsCiAgICAgICAgcHQuc2l6ZSA9IDAuNywKICAgICAgICByZWR1Y3Rpb24gPSAiaW50ZWdyYXRlZF9zcHJpbmciLAogICAgICAgIHNwbGl0LmJ5ID0gIm9yaWcuaWRlbnQiLAogICAgICAgIGNvbHMgPSAgYyggIiM0Y2FiZGMiLCAjIENocF9wcm9nCiAgICAgICAgICAgICAgICAgICAiIzY4YjA0MSIsICMiRG9yc28tTWVkaWFsX3BhbGxpdW0iIAogICAgICAgICAgICAgICAgICAgIiNlNDZiNmIiLCAjIkhlbSIgCiAgICAgICAgICAgICAgICAgICAiI2UzYzE0OCIsICMiTWVkaWFsX3BhbGxpdW0iCiAgICAgICAgICAgICAgICAgICAiI2E5OTYxYiIsCiAgICAgICAgICAgICAgICAgICAiI2ViY2IyZSIsCiAgICAgICAgICAgICAgICAgICAiIzA0NmM5YSIsICMgUGFsbGlhbAogICAgICAgICAgICAgICAgICAgIiM0OTkwYzkiLCMiVGhhbGFtaWNfZW1pbmVuY2UiCiAgICAgICAgICAgICJncmV5NDAiKQogICAgICAgICkgICYgTm9BeGVzKCkKCnAxIC8gcDIKYGBgCgpgYGB7ciBTYXZlIFJEUywgaW5jbHVkZT1ULCBldmFsPUZBTFNFfQpzYXZlUkRTKFdULktPLmludGVncmF0ZWQsICIuL1dUX0tPLmludGVncmF0ZWQuUkRTIikKYGBgCgpgYGB7cn0Kcm0obGlzdCA9IGxzKClbIWxzKCkgJWluJSBjKCJXVC5LTy5pbnRlZ3JhdGVkIildKQpnYygpCmBgYAoKIyBDb21wdXRlIGRpc3RhbmNlIGJldHdlZW4gdHJhamVjdG9yaWVzCgpgYGB7cn0KV1RfS09fdHJhamVjdG9yaWVzIDwtIHN1YnNldChXVC5LTy5pbnRlZ3JhdGVkLCBzdWJzZXQgPSBMaW5lYWdlICVpbiUgYygiQ2FqYWwtUmV0eml1c19uZXVyb25zIiwgIlBhbGxpYWxfbmV1cm9ucyIpKQpgYGAKCmBgYHtyfQpEaW1QbG90KFdUX0tPX3RyYWplY3RvcmllcywKICAgICAgICByZWR1Y3Rpb24gPSAiaW50ZWdyYXRlZF9zcHJpbmciLAogICAgICAgIGdyb3VwLmJ5ID0gIkxpbmVhZ2UiLAogICAgICAgIHNwbGl0LmJ5ID0gIm9yaWcuaWRlbnQiLAogICAgICAgIHB0LnNpemUgPSAxLAogICAgICAgIGNvbHMgPSBjKCIjY2MzOTFiIiwgIiMwMjZjOWEiKQogICAgICAgICkgKyBOb0F4ZXMoKQpgYGAKIyMgUHNldWRvdGltZSBXVCBDUiBiaW5zCgpgYGB7cn0KbmJyZWFrcyA9IDcKYGBgCgoKYGBge3J9CldULkNSIDwtIFdUX0tPX3RyYWplY3Rvcmllc0BtZXRhLmRhdGEgJT4lCiAgICAgICAgICAgICAgICAgICAgc2VsZWN0KCJvcmlnLmlkZW50IiwgIkJhcmNvZGVzIiwgIkNlbGwuaWRlbnQuV1QiLCJTcHJpbmdfMSIsICJTcHJpbmdfMiIsICJMaW5lYWdlIikgJT4lCiAgICAgICAgICAgICAgICAgICAgZmlsdGVyKG9yaWcuaWRlbnQgPT0gIkhlbTEiICYgQ2VsbC5pZGVudC5XVCA9PSAiQ2FqYWwtUmV0eml1c19uZXVyb25zIikKYGBgCgoKYGBge3J9CmZpdCA8LSBwcmluY2lwYWxfY3VydmUoYXMubWF0cml4KFdULkNSWyxjKCJTcHJpbmdfMSIsICJTcHJpbmdfMiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgc21vb3RoZXI9J2xvd2VzcycsCiAgICAgICAgICAgICAgICAgICAgICAgdHJhY2U9RiwKICAgICAgICAgICAgICAgICAgICAgICBmID0gMC43LAogICAgICAgICAgICAgICAgICAgICAgIHN0cmV0Y2g9MCkKCldULkNSJFBzZXVkb3RpbWUgPC0gZml0JGxhbWJkYS9tYXgoZml0JGxhbWJkYSkKCmlmIChjb3IoV1QuQ1IkUHNldWRvdGltZSwgV1RfS09fdHJhamVjdG9yaWVzQGFzc2F5cyRSTkFAZGF0YVsnSG1nYTInLCBXVC5DUiRCYXJjb2Rlc10pID4gMCkgewogIFdULkNSJFBzZXVkb3RpbWUgPC0gLShXVC5DUiRQc2V1ZG90aW1lIC0gbWF4KFdULkNSJFBzZXVkb3RpbWUpKQp9CgpXVC5DUiRQc2V1ZG90aW1lLmJpbnM8LSBjdXQoV1QuQ1IkUHNldWRvdGltZSwgYnJlYWtzID0gbmJyZWFrcyAsIGxhYmVscyA9IDE6bmJyZWFrcykKYGBgCgojIyBQc2V1ZG90aW1lIFdUIFBhbGxpYWwgYmlucwoKYGBge3J9CldULlBhbCA8LSBXVF9LT190cmFqZWN0b3JpZXNAbWV0YS5kYXRhICU+JQogICAgICAgICAgICAgICAgICAgIHNlbGVjdCgib3JpZy5pZGVudCIsICJCYXJjb2RlcyIsICJDZWxsLmlkZW50LldUIiwiU3ByaW5nXzEiLCAiU3ByaW5nXzIiLCAiTGluZWFnZSIpICU+JQogICAgICAgICAgICAgICAgICAgIGZpbHRlcihvcmlnLmlkZW50ID09ICJIZW0xIiAmIENlbGwuaWRlbnQuV1QgPT0gIlBhbGxpYWxfbmV1cm9ucyIpCmBgYAoKCmBgYHtyfQpmaXQgPC0gcHJpbmNpcGFsX2N1cnZlKGFzLm1hdHJpeChXVC5QYWwgWyxjKCJTcHJpbmdfMSIsICJTcHJpbmdfMiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgc21vb3RoZXI9J2xvd2VzcycsCiAgICAgICAgICAgICAgICAgICAgICAgdHJhY2U9RiwKICAgICAgICAgICAgICAgICAgICAgICBmID0gMC43LAogICAgICAgICAgICAgICAgICAgICAgIHN0cmV0Y2g9MCkKCldULlBhbCRQc2V1ZG90aW1lIDwtIGZpdCRsYW1iZGEvbWF4KGZpdCRsYW1iZGEpCgppZiAoY29yKFdULlBhbCRQc2V1ZG90aW1lLCBXVF9LT190cmFqZWN0b3JpZXNAYXNzYXlzJFJOQUBkYXRhWydIbWdhMicsIFdULlBhbCRCYXJjb2Rlc10pID4gMCkgewogIFdULlBhbCRQc2V1ZG90aW1lIDwtIC0oV1QuUGFsJFBzZXVkb3RpbWUgLSBtYXgoV1QuUGFsJFBzZXVkb3RpbWUpKQp9CgpXVC5QYWwkUHNldWRvdGltZS5iaW5zPC0gY3V0KFdULlBhbCRQc2V1ZG90aW1lLCBicmVha3MgPSBuYnJlYWtzICwgbGFiZWxzID0gMTpuYnJlYWtzKQpgYGAKCiMjIFBzZXVkb3RpbWUgS08gQ1IgYmlucwoKYGBge3J9CktPLkNSIDwtIFdUX0tPX3RyYWplY3Rvcmllc0BtZXRhLmRhdGEgJT4lCiAgICAgICAgICAgIHNlbGVjdCgib3JpZy5pZGVudCIsICJCYXJjb2RlcyIsICJDZWxsLmlkZW50LktPIiwiU3ByaW5nXzEiLCAiU3ByaW5nXzIiLCAiTGluZWFnZSIpICU+JQogICAgICAgICAgICBmaWx0ZXIob3JpZy5pZGVudCA9PSAiR21uY19LTyIgJiBDZWxsLmlkZW50LktPID09ICJOZXVyb25fcHJvYi4yIikKYGBgCgoKYGBge3J9CmZpdCA8LSBwcmluY2lwYWxfY3VydmUoYXMubWF0cml4KEtPLkNSWyxjKCJTcHJpbmdfMSIsICJTcHJpbmdfMiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgc21vb3RoZXI9J2xvd2VzcycsCiAgICAgICAgICAgICAgICAgICAgICAgdHJhY2U9RiwKICAgICAgICAgICAgICAgICAgICAgICBmID0gMC43LAogICAgICAgICAgICAgICAgICAgICAgIHN0cmV0Y2g9MCkKCktPLkNSJFBzZXVkb3RpbWUgPC0gZml0JGxhbWJkYS9tYXgoZml0JGxhbWJkYSkKCmlmIChjb3IoS08uQ1IkUHNldWRvdGltZSwgV1RfS09fdHJhamVjdG9yaWVzQGFzc2F5cyRSTkFAZGF0YVsnSG1nYTInLCBLTy5DUiRCYXJjb2Rlc10pID4gMCkgewogIEtPLkNSJFBzZXVkb3RpbWUgPC0gLShLTy5DUiRQc2V1ZG90aW1lIC0gbWF4KEtPLkNSJFBzZXVkb3RpbWUpKQp9CgpLTy5DUiRQc2V1ZG90aW1lLmJpbnM8LSBjdXQoS08uQ1IkUHNldWRvdGltZSwgYnJlYWtzID0gbmJyZWFrcyAsIGxhYmVscyA9IDE6bmJyZWFrcykKYGBgCgojIyBQc2V1ZG90aW1lIEtPIFBhbGxpYWwgYmlucwoKYGBge3J9CktPLlBhbCA8LSBXVF9LT190cmFqZWN0b3JpZXNAbWV0YS5kYXRhICU+JQogIHNlbGVjdCgib3JpZy5pZGVudCIsICJCYXJjb2RlcyIsICJDZWxsLmlkZW50LktPIiwiU3ByaW5nXzEiLCAiU3ByaW5nXzIiLCAiTGluZWFnZSIpICU+JQogIGZpbHRlcihvcmlnLmlkZW50ID09ICJHbW5jX0tPIiAmIENlbGwuaWRlbnQuS08gPT0gIk5ldXJvbl9wcm9iLjMiKQpgYGAKCgpgYGB7cn0KZml0IDwtIHByaW5jaXBhbF9jdXJ2ZShhcy5tYXRyaXgoS08uUGFsIFssYygiU3ByaW5nXzEiLCAiU3ByaW5nXzIiKV0pLAogICAgICAgICAgICAgICAgICAgICAgIHNtb290aGVyPSdsb3dlc3MnLAogICAgICAgICAgICAgICAgICAgICAgIHRyYWNlPUYsCiAgICAgICAgICAgICAgICAgICAgICAgZiA9IDAuNywKICAgICAgICAgICAgICAgICAgICAgICBzdHJldGNoPTApCgpLTy5QYWwkUHNldWRvdGltZSA8LSBmaXQkbGFtYmRhL21heChmaXQkbGFtYmRhKQoKaWYgKGNvcihLTy5QYWwkUHNldWRvdGltZSwgV1RfS09fdHJhamVjdG9yaWVzQGFzc2F5cyRSTkFAZGF0YVsnSG1nYTInLCBLTy5QYWwkQmFyY29kZXNdKSA+IDApIHsKICBLTy5QYWwkUHNldWRvdGltZSA8LSAtKEtPLlBhbCRQc2V1ZG90aW1lIC0gbWF4KEtPLlBhbCRQc2V1ZG90aW1lKSkKfQoKS08uUGFsJFBzZXVkb3RpbWUuYmluczwtIGN1dChLTy5QYWwkUHNldWRvdGltZSwgYnJlYWtzID0gbmJyZWFrcyAsIGxhYmVscyA9IDE6bmJyZWFrcykKYGBgCgojIyBDb21iaW5lIHBzZXVkb3RpbWUKCmBgYHtyfQpwMSA8LSBnZ3Bsb3QoV1QuQ1IsIGFlcyhTcHJpbmdfMSwgU3ByaW5nXzIpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3I9UHNldWRvdGltZSksIHNpemU9Miwgc2hhcGU9MTYpICsgCiAgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG91cnM9cmV2KGNvbG9yUmFtcFBhbGV0dGUoYnJld2VyLnBhbChuID0xMSwgbmFtZSA9ICJTcGVjdHJhbCIpKSgxMDApKSwgbmFtZT0nU3BldWRvdGltZSBzY29yZScpCgpwMiA8LSBnZ3Bsb3QoV1QuUGFsLCBhZXMoU3ByaW5nXzEsIFNwcmluZ18yKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yPVBzZXVkb3RpbWUpLCBzaXplPTIsIHNoYXBlPTE2KSArIAogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzPXJldihjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwobiA9MTEsIG5hbWUgPSAiU3BlY3RyYWwiKSkoMTAwKSksIG5hbWU9J1NwZXVkb3RpbWUgc2NvcmUnKQoKcDMgPC0gZ2dwbG90KEtPLkNSLCBhZXMoU3ByaW5nXzEsIFNwcmluZ18yKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yPVBzZXVkb3RpbWUpLCBzaXplPTIsIHNoYXBlPTE2KSArIAogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzPXJldihjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwobiA9MTEsIG5hbWUgPSAiU3BlY3RyYWwiKSkoMTAwKSksIG5hbWU9J1NwZXVkb3RpbWUgc2NvcmUnKQoKcDQgPC0gZ2dwbG90KEtPLlBhbCwgYWVzKFNwcmluZ18xLCBTcHJpbmdfMikpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1Qc2V1ZG90aW1lKSwgc2l6ZT0yLCBzaGFwZT0xNikgKyAKICBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3Vycz1yZXYoY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKG4gPTExLCBuYW1lID0gIlNwZWN0cmFsIikpKDEwMCkpLCBuYW1lPSdTcGV1ZG90aW1lIHNjb3JlJykKCnAxICsgcDIgKyBwMyArIHA0CmBgYAoKYGBge3J9CnAxIDwtIGdncGxvdChXVC5DUiwgYWVzKFNwcmluZ18xLCBTcHJpbmdfMikpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1Qc2V1ZG90aW1lLmJpbnMpLCBzaXplPTIsIHNoYXBlPTE2KQoKcDIgPC0gZ2dwbG90KFdULlBhbCwgYWVzKFNwcmluZ18xLCBTcHJpbmdfMikpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1Qc2V1ZG90aW1lLmJpbnMpLCBzaXplPTIsIHNoYXBlPTE2KQoKcDMgPC0gZ2dwbG90KEtPLkNSLCBhZXMoU3ByaW5nXzEsIFNwcmluZ18yKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yPVBzZXVkb3RpbWUuYmlucyksIHNpemU9Miwgc2hhcGU9MTYpCgpwNCA8LSBnZ3Bsb3QoS08uUGFsLCBhZXMoU3ByaW5nXzEsIFNwcmluZ18yKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yPVBzZXVkb3RpbWUuYmlucyksIHNpemU9Miwgc2hhcGU9MTYpCgpwMSArIHAyICsgcDMgKyBwNApgYGAKCmBgYHtyfQp0cmFqLmRhdGEgPC0gcmJpbmQoV1QuQ1JbLGMoIkJhcmNvZGVzIiwgIlBzZXVkb3RpbWUuYmlucyIpXSwgV1QuUGFsWyxjKCJCYXJjb2RlcyIsICJQc2V1ZG90aW1lLmJpbnMiKV0sCiAgICAgICAgICAgICAgICAgICBLTy5DUlssYygiQmFyY29kZXMiLCAiUHNldWRvdGltZS5iaW5zIildLCBLTy5QYWxbLGMoIkJhcmNvZGVzIiwgIlBzZXVkb3RpbWUuYmlucyIpXSkKCnJvd25hbWVzKHRyYWouZGF0YSkgPC0gdHJhai5kYXRhJEJhcmNvZGVzCgpXVF9LT190cmFqZWN0b3JpZXMkUHNldWRvdGltZS5iaW5zIDwtIHNhcHBseShXVF9LT190cmFqZWN0b3JpZXMkQmFyY29kZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSBmdW5jdGlvbih4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh4ICVpbiUgdHJhai5kYXRhJEJhcmNvZGVzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IHRyYWouZGF0YVt4LCJQc2V1ZG90aW1lLmJpbnMiXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IDEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KQpgYGAKCmBgYHtyfQpEaW1QbG90KFdUX0tPX3RyYWplY3RvcmllcywKICAgICAgICByZWR1Y3Rpb24gPSAiaW50ZWdyYXRlZF9zcHJpbmciLAogICAgICAgIGdyb3VwLmJ5ID0gIlBzZXVkb3RpbWUuYmlucyIsCiAgICAgICAgcHQuc2l6ZSA9IDEsCiAgICAgICAgI2NvbHMgPSBjKCIjY2MzOTFiIiwgIiMwMjZjOWEiKQogICAgICAgICkgKyBOb0F4ZXMoKQpgYGAKCiMgQ29zaW5lIGRpc3RhbmNlIGJldHdlZW4gYXZlcmFnZSBleHByZXNzaW9uCgojIyBhdmVyYWdlIHNjYWxlZCBleHByZXNzaW9uIGJ5IGxpbmVhZ2UgYW5kIGJ5IGdlbm90eXBlCgpgYGB7cn0KIyBXVCBDYWphbC1SZXR6aXVzCldUX0NSIDwtIHN1YnNldChXVF9LT190cmFqZWN0b3JpZXMsIHN1YnNldCA9IG9yaWcuaWRlbnQgPT0gIkhlbTEiICYgTGluZWFnZSA9PSAiQ2FqYWwtUmV0eml1c19uZXVyb25zIikKICAKV1RfQ1IuYXZlcmFnZXMgPC0gQXZlcmFnZUV4cHJlc3Npb24oV1RfQ1IsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLmJ5ID0gIlBzZXVkb3RpbWUuYmlucyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2F5cyA9ICJpbnRlZ3JhdGVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICJzY2FsZS5kYXRhIikKCiMgS08gQ2FqYWwtUmV0eml1cwpLT19DUiA8LSBzdWJzZXQoV1RfS09fdHJhamVjdG9yaWVzLCBzdWJzZXQgPSBvcmlnLmlkZW50ID09ICJHbW5jX0tPIiAmIExpbmVhZ2UgPT0gIkNhamFsLVJldHppdXNfbmV1cm9ucyIpCgpLT19DUi5hdmVyYWdlcyA8LSBBdmVyYWdlRXhwcmVzc2lvbihLT19DUiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAiUHNldWRvdGltZS5iaW5zIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXlzID0gImludGVncmF0ZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gInNjYWxlLmRhdGEiKQogIAojIFdUIFBhbGxpYWwgbmV1cm9ucwpXVF9QYWwgPC0gc3Vic2V0KFdUX0tPX3RyYWplY3Rvcmllcywgc3Vic2V0ID0gb3JpZy5pZGVudCA9PSAiSGVtMSIgJiBMaW5lYWdlID09ICJQYWxsaWFsX25ldXJvbnMiKQoKV1RfUGFsLmF2ZXJhZ2VzIDwtIEF2ZXJhZ2VFeHByZXNzaW9uKFdUX1BhbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAiUHNldWRvdGltZS5iaW5zIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXlzID0gImludGVncmF0ZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gInNjYWxlLmRhdGEiKQogIAojIEtPIFBhbGxpYWwgbmV1cm9ucyAgCktPX1BhbCA8LSBzdWJzZXQoV1RfS09fdHJhamVjdG9yaWVzLCBzdWJzZXQgPSBvcmlnLmlkZW50ID09ICJHbW5jX0tPIiAmIExpbmVhZ2UgPT0gIlBhbGxpYWxfbmV1cm9ucyIpCgpLT19QYWwuYXZlcmFnZXMgPC0gQXZlcmFnZUV4cHJlc3Npb24oS09fUGFsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cC5ieSA9ICJQc2V1ZG90aW1lLmJpbnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheXMgPSAiaW50ZWdyYXRlZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAic2NhbGUuZGF0YSIpCmBgYAoKIyMgRGlzdGFuY2UgdG8gV1QgcGFsbGlhbCBuZXVyb25zCgpgYGB7cn0KIyBXVCBDUgpTbW9vdGhlZC5wb2ludC5jb3IgPC0gcGRpc3Q6OnBkaXN0KFg9IHQoV1RfQ1IuYXZlcmFnZXMkaW50ZWdyYXRlZCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgWT0gdChXVF9QYWwuYXZlcmFnZXMkaW50ZWdyYXRlZCkpCgpXVC5DUl9XVC5QYWwuZGlzdCA8LSBkaWFnKGFzLm1hdHJpeChTbW9vdGhlZC5wb2ludC5jb3IpKQoKClNtb290aGVkLnBvaW50LmNvciA8LSBwZGlzdDo6cGRpc3QoWD0gdChXVF9DUi5hdmVyYWdlcyRpbnRlZ3JhdGVkKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBZPSB0KEtPX1BhbC5hdmVyYWdlcyRpbnRlZ3JhdGVkKSkKCldULkNSX0tPLlBhbC5kaXN0IDwtIGRpYWcoYXMubWF0cml4KFNtb290aGVkLnBvaW50LmNvcikpCgpTbW9vdGhlZC5wb2ludC5jb3IgPC0gcGRpc3Q6OnBkaXN0KFg9IHQoV1RfQ1IuYXZlcmFnZXMkaW50ZWdyYXRlZCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgWT0gdChLT19DUi5hdmVyYWdlcyRpbnRlZ3JhdGVkKSkKCldULkNSX0tPLkNSLmRpc3QgPC0gZGlhZyhhcy5tYXRyaXgoU21vb3RoZWQucG9pbnQuY29yKSkKClNtb290aGVkLnBvaW50LmNvciA8LSBwZGlzdDo6cGRpc3QoWD0gdChLT19DUi5hdmVyYWdlcyRpbnRlZ3JhdGVkKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBZPSB0KFdUX1BhbC5hdmVyYWdlcyRpbnRlZ3JhdGVkKSkKCktPLkNSX1dULlBhbC5kaXN0IDwtIGRpYWcoYXMubWF0cml4KFNtb290aGVkLnBvaW50LmNvcikpCgpTbW9vdGhlZC5wb2ludC5jb3IgPC0gcGRpc3Q6OnBkaXN0KFg9IHQoS09fQ1IuYXZlcmFnZXMkaW50ZWdyYXRlZCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgWT0gdChLT19QYWwuYXZlcmFnZXMkaW50ZWdyYXRlZCkpCgpLTy5DUl9LTy5QYWwuZGlzdCA8LSBkaWFnKGFzLm1hdHJpeChTbW9vdGhlZC5wb2ludC5jb3IpKQoKU21vb3RoZWQucG9pbnQuY29yIDwtIHBkaXN0OjpwZGlzdChYPSB0KFdUX1BhbC5hdmVyYWdlcyRpbnRlZ3JhdGVkKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBZPSB0KEtPX1BhbC5hdmVyYWdlcyRpbnRlZ3JhdGVkKSkKCldULlBhbF9LTy5QYWwuZGlzdCA8LSBkaWFnKGFzLm1hdHJpeChTbW9vdGhlZC5wb2ludC5jb3IpKQpgYGAKCgoKYGBge3J9CmRhdGEgPC0gZGF0YS5mcmFtZShEaXN0YW5jZSA9IGMoV1QuQ1JfV1QuUGFsLmRpc3QsIFdULkNSX0tPLlBhbC5kaXN0LCBXVC5DUl9LTy5DUi5kaXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEtPLkNSX1dULlBhbC5kaXN0LCBLTy5DUl9LTy5QYWwuZGlzdCwgV1QuUGFsX0tPLlBhbC5kaXN0KSwKICAgICAgICAgICAgICAgICAgIFRyYWplY3RvcnkgPSByZXAoYygiV1QuQ1JfV1QuUGFsLmRpc3QiLCAiV1QuQ1JfS08uUGFsLmRpc3QiLCAiV1QuQ1JfS08uQ1IuZGlzdCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIktPLkNSX1dULlBhbC5kaXN0IiwgIktPLkNSX0tPLlBhbC5kaXN0IiwgIldULlBhbF9LTy5QYWwuZGlzdCIpLCBlYWNoPW5icmVha3MpLAogICAgICAgICAgICAgICAgICAgUHNldWRvdGltZS5iaW4gPSBmYWN0b3IocmVwKHBhc3RlMCgiQmluXyIsMTpuYnJlYWtzKSwgMyksbGV2ZWxzID0gcGFzdGUwKCJCaW5fIiwxOm5icmVha3MpKSkKCnAxIDwtIERpbVBsb3QoV1RfS09fdHJhamVjdG9yaWVzLAogICAgICAgIHJlZHVjdGlvbiA9ICJpbnRlZ3JhdGVkX3NwcmluZyIsCiAgICAgICAgZ3JvdXAuYnkgPSAiUHNldWRvdGltZS5iaW5zIiwKICAgICAgICBwdC5zaXplID0gMSwKICAgICAgICAjY29scyA9IGMoIiNjYzM5MWIiLCAiIzAyNmM5YSIpCiAgICAgICAgKSArIE5vQXhlcygpCgpwMiA8LSBnZ3Bsb3QoZGF0YSwgYWVzKHg9IFBzZXVkb3RpbWUuYmluLCB5PSBEaXN0YW5jZSwgY29sb3I9IFRyYWplY3RvcnksIGdyb3VwID0gVHJhamVjdG9yeSkpICsKICAgICAgICAgICAgICBnZW9tX2xpbmUoKSArCiAgICAgICAgICAgICAgZ2VvbV9wb2ludCgpCgpwMSArIHAyCmBgYAoKIyBQbG90IGxhdGUgbmV1cm9ucyBsaW5lYWdlIG1hcmtlcnMKCmBgYHtyfQpXVF9LT19MTiA8LSBzdWJzZXQoV1RfS09fdHJhamVjdG9yaWVzLCBzdWJzZXQgPSBQc2V1ZG90aW1lLmJpbnMgJWluJSBjKDYsNykpCmBgYAoKYGBge3J9CkRlZmF1bHRBc3NheShXVF9LT19MTikgPC0gIlJOQSIKCnAxIDwtIERpbVBsb3QoV1RfS09fTE4sCiAgICAgICAgcmVkdWN0aW9uID0gImludGVncmF0ZWRfc3ByaW5nIiwKICAgICAgICBncm91cC5ieSA9ICJMaW5lYWdlIiwKICAgICAgICBwdC5zaXplID0gMSwKICAgICAgICBjb2xzID0gYygiI2NjMzkxYiIsICIjMDI2YzlhIikKICAgICAgICApICsgTm9BeGVzKCkKCnAyIDwtIERpbVBsb3QoV1RfS09fTE4sCiAgICAgICAgcmVkdWN0aW9uID0gImludGVncmF0ZWRfc3ByaW5nIiwKICAgICAgICBncm91cC5ieSA9ICJvcmlnLmlkZW50IiwKICAgICAgICBwdC5zaXplID0gMSwKICAgICAgICBjb2xzID0gYygiI2NjMzkxYiIsICIjMDI2YzlhIikKICAgICAgICApICsgTm9BeGVzKCkKCnAzIDwtIEZlYXR1cmVQbG90KG9iamVjdCA9IFdUX0tPX0xOLAogICAgICAgICAgICBmZWF0dXJlcyA9IGMoIkZveGcxIiwgIlpmcG0yIiwiUHJkbTgiLAogICAgICAgICAgICAgICAgICAgICAgICAgIlJlbG4iLCAiWmljNSIsICJaZnA1MDMiKSwKICAgICAgICAgICAgcHQuc2l6ZSA9IDEsCiAgICAgICAgICAgIGNvbHMgPSBjKCJncmV5OTAiLCBicmV3ZXIucGFsKDksIllsR25CdSIpKSwKICAgICAgICAgICAgcmVkdWN0aW9uID0gImludGVncmF0ZWRfc3ByaW5nIiwKICAgICAgICAgICAgc2xvdCA9ICJkYXRhIiwKICAgICAgICAgICAgb3JkZXIgPSBUKSAmIE5vQXhlcygpICYgTm9MZWdlbmQoKQoKKHAxICsgcDIpICsgKHAzKQpgYGAKCgojIFNlc3Npb24gSW5mbwoKYGBge3J9CiNkYXRlCmZvcm1hdChTeXMudGltZSgpLCAiJWQgJUIsICVZLCAlSCwlTSIpCgojUGFja2FnZXMgdXNlZApzZXNzaW9uSW5mbygpCmBgYA==