Load libraries

library(Seurat)
library(scrattch.hicat)
library(FateID)
library(Matrix)
library(dplyr)
library(RColorBrewer)
library(ggplot2)
library(ggExtra)
library(cowplot)
library(reticulate)
library(wesanderson)
library(princurve)
use_python("/usr/bin/python3")

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

Project progenitors domain ident from WT

# Load the raw counts matrix
path.ref <- "/mnt/B8926B8E926B5044/2017-2021_Pierani-lab/Projet_CR_transcriptome_scRNAseq/Datasets/E11-12_Hem-Wnt3aCre_11-19/hemCR/QC.filtered.clustered.cells.RDS"


WT.KO <- list(WT = readRDS(path.ref) %>%
                subset(subset = orig.ident == "Hem1" & Cell_ident %in% c("ChP_progenitors", "ChP",
                                                                         "Dorso-Medial_pallium", "Medial_pallium",
                                                                         "Hem", "Thalamic_eminence") ),
              KO = readRDS("Pidd1KO.cells.RDS") %>% subset(idents = c(0,1,3,6)))

gc()
##             used   (Mb) gc trigger   (Mb)  max used   (Mb)
## Ncells   2781542  148.6    4507117  240.8   4507117  240.8
## Vcells 388970477 2967.7  807840593 6163.4 798973275 6095.7
p1 <- DimPlot(object = WT.KO[["WT"]],
        group.by = "Cell.state",
        reduction = "spring",
        cols = c("#31b6bd", "#ebcb2e", "#9ec22f", "#cc3a1b", "#d14c8d", "#4cabdc", "#5ab793", "#e7823a", "#046c9a", "#4990c9"),
        pt.size = 1.5
        )  & NoAxes()

p2 <- DimPlot(WT.KO[["KO"]],
        reduction = "spring",
        group.by = "Broadclust.ident",
        cols = c("#ebcb2e", "#9ec22f", "#a9961b", "#cc3a1b"),
        pt.size = 1.5) & NoAxes()

p1 + p2

WT.KO[["WT"]] <- NormalizeData(WT.KO[["WT"]], normalization.method = "LogNormalize", scale.factor = 10000, assay = "RNA")
WT.KO[["KO"]] <- NormalizeData(WT.KO[["KO"]], normalization.method = "LogNormalize", scale.factor = 10000, assay = "RNA")
WT.KO[["WT"]] <- FindVariableFeatures(WT.KO[["WT"]], selection.method = "vst", nfeatures = 2000)
WT.KO[["KO"]] <- FindVariableFeatures(WT.KO[["KO"]], selection.method = "vst", nfeatures = 2000)
features <- SelectIntegrationFeatures(object.list = WT.KO, nfeatures = 1500)

Transfert identity labels WT to KO

KO.anchors <- FindTransferAnchors(reference = WT.KO[["WT"]],
                                  query = WT.KO[["KO"]],
                                  features = features,
                                  reduction = "rpca",
                                  k.anchor = 5,
                                  k.filter = 100,
                                  k.score = 30,
                                  npcs = 20,
                                  dims = 1:20,
                                  max.features = 200)

predictions <- TransferData(anchorset = KO.anchors,
                            refdata = WT.KO[["WT"]]$Cell.state,
                            dims = 1:20)

WT.KO[["KO"]] <- AddMetaData(WT.KO[["KO"]], metadata = predictions)
cols <- brewer.pal(n =11, name = "Spectral")

ggplot(WT.KO[["KO"]]@meta.data, aes(Spring_1, Spring_2)) +
  geom_point(aes(color=prediction.score.max), size=1, shape=16) + 
  scale_color_gradientn(colours=rev(cols), name='prediction.score.max')

p1 <- DimPlot(object = WT.KO[["WT"]],
        group.by = "Cell.state",
        reduction = "spring",
        cols = c("#7293c8", "#b79f0b", "#3ca73f","#31b6bd",
                 "#ebcb2e", "#9ec22f", "#a9961b", "#cc3a1b"),
        pt.size = 1)  & NoAxes()

p2 <- DimPlot(WT.KO[["KO"]],
              group.by = "predicted.id",
              reduction = "spring",
              cols = c("#7293c8","#31b6bd",
                 "#ebcb2e", "#9ec22f", "#a9961b", "#cc3a1b"),
              pt.size = 1) & NoAxes()

p1 + p2

Transfert to the full dataset

Projected.idents <- WT.KO[["KO"]]@meta.data

rm(list = ls()[!ls() %in% c("Projected.idents")])
gc()
##             used   (Mb) gc trigger   (Mb)  max used   (Mb)
## Ncells   2940800  157.1    4507117  240.8   4507117  240.8
## Vcells 389436188 2971.2 1007133240 7683.9 908772642 6933.4
Raw.data <- readRDS("Pidd1KO.cells.RDS")

Raw.data$Cell.ident <- sapply(Raw.data$Barcodes,
                              FUN = function(x) {
                                if (x %in% Projected.idents $Barcodes) {
                                  x = Projected.idents[x, "predicted.id"]
                                } else {
                                  x = Raw.data@meta.data[x, "Broadclust.ident"]
                                  }
                              })
DimPlot(object = Raw.data,
        group.by = "Cell.ident",
        reduction = "spring",
        cols = c("#4cabdc", "#7293c8", "grey40", "#7293c8","#31b6bd",
                 "#ebcb2e", "#9ec22f", "#a9961b", "#cc3a1b"),
        pt.size = 0.5)  & NoAxes()

rm(list = ls()[!ls() %in% "Raw.data"])
gc()
##             used   (Mb) gc trigger   (Mb)  max used   (Mb)
## Ncells   2934993  156.8    4507117  240.8   4507117  240.8
## Vcells 288562628 2201.6  805706592 6147.1 908772642 6933.4

Annotate differentiating neurons

Cell state score

# AP

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

Raw.data <- AddModuleScore(Raw.data,
                     features = list(APgenes),
                     name = "AP_signature")
# BP

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

Raw.data<- AddModuleScore(Raw.data,
                     features = list(BPgenes),
                     name = "BP_signature")
# EN

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

Raw.data <- AddModuleScore(Raw.data,
                           features = list(ENgenes),
                           name = "EN_signature")
# LN

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

Raw.data <- AddModuleScore(Raw.data,
                           features = list(LNgenes),
                           name = "LN_signature")
FeaturePlot(object = Raw.data,
            features = c("AP_signature1", "BP_signature1",
                              "EN_signature1", "LN_signature1"),
            pt.size = 0.75,
            cols = rev(brewer.pal(10,"Spectral")),
            reduction = "spring",
            order = T) & NoAxes() & NoLegend()

Annotate most mature neurons

LN.data <- Raw.data %>% subset(subset = Cell.ident %in% c(3,6))
# K-means clustering based on AP, SP and Pal signature scores
set.seed(100)
cl <- kmeans(cbind(LN.data$BP_signature1,
                   LN.data$EN_signature1,
                   LN.data$LN_signature1), 2)

LN.data$kmeanClust <- paste0("Clust.",cl$cluster)
col.pal <- wes_palette("GrandBudapest1", 4, type = "discrete")

p1 <- ggplot(LN.data@meta.data, aes(x=LN_signature1, y=EN_signature1, colour = kmeanClust)) +
  scale_color_manual(values=col.pal) +
  geom_point() + 
  theme(legend.position="none")
ggMarginal(p1, type = "histogram", fill="lightgrey")

DimPlot(object = LN.data,
        group.by = "kmeanClust",
        reduction = "spring",
        cols = col.pal,
        pt.size = 0.5)  & NoAxes()

LN.data <- LN.data  %>% subset(subset = kmeanClust == "Clust.2" & Spring_2 > 2500)

DimPlot(object = LN.data,
        group.by = "kmeanClust",
        reduction = "spring",
        cols = c("#4cabdc", "#7293c8", "grey40"),
        pt.size = 0.5)  & NoAxes()

Prepare the dataset for clustering with scrattch.hicat

# Exclude genes detected in less than 3 cells
num.cells <- Matrix::rowSums(LN.data@assays[["RNA"]]@counts > 0)
genes.use <- names(x = num.cells[which(x = num.cells >= 3)])

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

genes.use <- genes.use[!genes.use %in% GenesToRemove]
dgeMatrix_count <- as.matrix(LN.data@assays[["RNA"]]@counts)[rownames(LN.data@assays[["RNA"]]@counts) %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)
gene.counts <- log2(colSums(as.matrix(Data.matrix$norm.dat) > 0))
nUMI <- log2(colSums(Data.matrix$raw.dat))
perctMito <- LN.data$percent.mito
perctRibo <- LN.data$percent.ribo
LNscore <- LN.data$LN_signature1

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

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

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

rm(gene.counts, nUMI, perctMito, perctRibo, LNscore)

Run scrattch.hicat

# 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 = 200,
                     min.cells   = 10)
iter.result <- iter_clust(norm.dat, 
                          counts = raw.dat,
                          dim.method = "pca",
                          max.dim = 10,
                          k.nn = 5,
                          de.param = de.param,
                          rm.eigen = rm.eigen,
                          rm.th = 0.6,
                          vg.padj.th = 0.5,
                          method = "louvain",
                          prefix = "iter_clust",
                          verbose = F)
## [1] "iter_clust"
##   Finding nearest neighbors...DONE ~ 0.004 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.008 s
##   Build undirected graph from the weighted links...DONE ~ 0.023 s
##   Run louvain clustering on the graph ...DONE ~ 0.011 s
##   Return a community class
##   -Modularity value: 0.9385356 
##   -Number of clusters: 36[1] "iter_clust.1"
##   Finding nearest neighbors...DONE ~ 0 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.001 s
##   Build undirected graph from the weighted links...DONE ~ 0.001 s
##   Run louvain clustering on the graph ...DONE ~ 0.001 s
##   Return a community class
##   -Modularity value: 0.6538551 
##   -Number of clusters: 4[1] "iter_clust.2"
##   Finding nearest neighbors...DONE ~ 0.001 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.003 s
##   Build undirected graph from the weighted links...DONE ~ 0.006 s
##   Run louvain clustering on the graph ...DONE ~ 0.003 s
##   Return a community class
##   -Modularity value: 0.8933776 
##   -Number of clusters: 18[1] "iter_clust.3"
##   Finding nearest neighbors...DONE ~ 0.001 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.004 s
##   Build undirected graph from the weighted links...DONE ~ 0.008 s
##   Run louvain clustering on the graph ...DONE ~ 0.004 s
##   Return a community class
##   -Modularity value: 0.9202576 
##   -Number of clusters: 26[1] "iter_clust.4"
##   Finding nearest neighbors...DONE ~ 0.001 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.002 s
##   Build undirected graph from the weighted links...DONE ~ 0.005 s
##   Run louvain clustering on the graph ...DONE ~ 0.002 s
##   Return a community class
##   -Modularity value: 0.8736993 
##   -Number of clusters: 14
# Merge clusters which are not seperable 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")
## 4  Clusters
LN.data$iter.clust <- merge.result$cl

Idents(LN.data) <- "iter.clust"

colors <-  c("#ebcb2e", "#9ec22f", "#cc3a1b")

DimPlot(LN.data,
        reduction = "spring",
        #cols = colors,
        pt.size = 1.5) & NoAxes()

Raw.data$Cell.ident <- sapply(Raw.data$Barcodes,
                              FUN = function(x) {
                                if (x %in% LN.data$Barcodes) {
                                  x = paste0("LN.", LN.data@meta.data[x, "iter.clust"])
                                } else {
                                  x = Raw.data@meta.data[x, "Cell.ident"]
                                  }
                              })
Raw.data$Cell.ident <- ifelse(Raw.data$Cell.ident %in% c(3,5), "Pal.neuron.traj", Raw.data$Cell.ident)
Raw.data$Cell.ident <- ifelse(Raw.data$Cell.ident == 6, "CR.traj", Raw.data$Cell.ident)
Raw.data$Cell.ident <- ifelse(Raw.data$Cell.ident == "Thalamic_eminence", "Septum_ANR", Raw.data$Cell.ident)
Raw.data$Cell.ident <- ifelse(Raw.data$Cell.ident == "Pal.neuron.traj",
                              "Differentiating_neurons", Raw.data$Cell.ident)

Raw.data$Cell.ident <- ifelse(Raw.data$Cell.ident == "Septum_ANR",
                              "Progenitors_Septum_ANR", Raw.data$Cell.ident)

Raw.data$Cell.ident <- ifelse(Raw.data$Cell.ident == "Medial_pallium",
                              "Progenitors_Medial-pallium", Raw.data$Cell.ident)

Raw.data$Cell.ident <- ifelse(Raw.data$Cell.ident == "Hem",
                              "Progenitors_Hem", Raw.data$Cell.ident)

Raw.data$Cell.ident <- ifelse(Raw.data$Cell.ident == "Dorso-Medial_pallium",
                              "Progenitors_Dorso-Medial-pallium", Raw.data$Cell.ident)

Raw.data$Cell.ident <- ifelse(Raw.data$Cell.ident == "ChP_progenitors",
                              "Progenitors_ChP", Raw.data$Cell.ident)

Raw.data$Cell.ident <- ifelse(Raw.data$Cell.ident == "ChP_Early",
                              "Choroid_Plexus", Raw.data$Cell.ident)

Raw.data$Cell.ident <- ifelse(Raw.data$Cell.ident == "CR.traj",
                              "Differentiating_CRs", Raw.data$Cell.ident)

Raw.data$Cell.ident <- ifelse(Raw.data$Cell.ident == "LN.5",
                              "Neurons_Cajal-Retzius", Raw.data$Cell.ident)

Raw.data$Cell.ident <- ifelse(Raw.data$Cell.ident %in% c("LN.6", "LN.NA", "LN.1"),
                              "Neurons_Dorsal-Pallium", Raw.data$Cell.ident)

Raw.data$Cell.ident <- ifelse(Raw.data$Cell.ident %in% c("LN.7"),
                              "Neurons_Medial-Pallium", Raw.data$Cell.ident)
DimPlot(object = Raw.data,
        group.by = "Cell.ident",
        reduction = "spring",
        cols = c("grey40","#4cabdc","#046c9a", "#7293c8", "#31b6bd", "#ebcb2e", "#9ec22f", "#a9961b", "#cc3a1b", wes_palette("FantasticFox1")),
        pt.size = 0.5)  & NoAxes()

rm(list = ls()[!ls() %in% c("Raw.data")])
gc()
##             used   (Mb) gc trigger   (Mb)  max used   (Mb)
## Ncells   3088623  165.0    5731741  306.2   5731741  306.2
## Vcells 306611956 2339.3  805706592 6147.1 908772642 6933.4

Generate SRING dimentionality reduction

Export counts matrix

dir.create("./SpringCoordinates/SpringCoordinates_cleaned")
# Export raw expression matrix and gene list to regenerate a spring plot
exprData <- Matrix(as.matrix(Raw.data@assays[["RNA"]]@counts), sparse = TRUE)
writeMM(exprData, "./SpringCoordinates/SpringCoordinates_cleaned/ExprData.mtx")
## NULL
rm(exprData)
Genelist <- row.names(Raw.data@assays[["RNA"]]@counts)
write.table(Genelist, "./SpringCoordinates/SpringCoordinates_cleaned/Genelist.csv", sep="\t", col.names = F, row.names = F, quote = F)
#Export metadata
Identity <- c("Identity", Raw.data$Cell.ident)
Identity <- paste(Identity, sep=",", collapse=",")

Genotype <- c("Genotype", Raw.data$Genotype)
Genotype <- paste(Genotype, sep=",", collapse=",")

Cellgrouping <- rbind(Identity, Genotype)
write.table(Cellgrouping, "./SpringCoordinates/SpringCoordinates_cleaned/Cellgrouping.csv", quote =F, row.names = F, col.names = F)
#Cells scores
AP.score <- c("AP.score", Raw.data$AP_signature1)
AP.score <- paste(AP.score, sep=",", collapse=",")

BP.score <- c("BP.score", Raw.data$BP_signature1)
BP.score <- paste(BP.score, sep=",", collapse=",")

EN.score <- c("EN.score", Raw.data$EN_signature1)
EN.score <- paste(EN.score, sep=",", collapse=",")

LN.score <- c("LN.score", Raw.data$LN_signature1)
LN.score <- paste(LN.score, sep=",", collapse=",")

ColorTrack <- rbind(AP.score, BP.score, EN.score, LN.score)
write.table(ColorTrack, "./SpringCoordinates/SpringCoordinates_cleaned/ColorTrack.csv", quote =F, row.names = F, col.names = F)
#Coordinates

Coordinates <- cbind(c(1:nrow(Raw.data@meta.data))-1,
                     Raw.data$Spring_1,
                     Raw.data$Spring_2)

Spring.Sym <- function(x){
  x = abs(max(Coordinates[,3])-x)
 }

Coordinates[,3] <- sapply(Coordinates[,3], function(x) Spring.Sym(x))

write.table(Coordinates, "./SpringCoordinates/SpringCoordinates_cleaned/Custom_coor.csv", sep = ",", quote =F, row.names = F, col.names = F)

Save the object

saveRDS(Raw.data, "./Pidd1KO.cells.RDS")

Session Info

#date
format(Sys.time(), "%d %B, %Y, %H,%M")
## [1] "16 janvier, 2023, 11,58"
#Packages used
sessionInfo()
## R version 4.2.2 Patched (2022-11-10 r83330)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 20.04.5 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0
## 
## locale:
##  [1] LC_CTYPE=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] princurve_2.1.6      wesanderson_0.3.6    reticulate_1.22     
##  [4] cowplot_1.1.1        ggExtra_0.9          ggplot2_3.4.0       
##  [7] RColorBrewer_1.1-2   dplyr_1.0.7          Matrix_1.5-1        
## [10] FateID_0.2.1         scrattch.hicat_1.0.0 SeuratObject_4.0.4  
## [13] Seurat_4.0.5        
## 
## loaded via a namespace (and not attached):
##   [1] Rtsne_0.15            colorspace_2.0-2      deldir_1.0-6         
##   [4] ellipsis_0.3.2        ggridges_0.5.3        som_0.3-5.1          
##   [7] rstudioapi_0.13       spatstat.data_2.1-0   farver_2.1.0         
##  [10] leiden_0.3.9          listenv_0.8.0         ggrepel_0.9.1        
##  [13] lle_1.1               RSpectra_0.16-0       fansi_0.5.0          
##  [16] codetools_0.2-18      splines_4.2.2         knitr_1.36           
##  [19] polyclip_1.10-0       jsonlite_1.7.2        umap_0.2.8.0         
##  [22] ica_1.0-2             cluster_2.1.4         png_0.1-7            
##  [25] pheatmap_1.0.12       snowfall_1.84-6.1     uwot_0.1.10          
##  [28] shiny_1.7.1           sctransform_0.3.2     spatstat.sparse_2.0-0
##  [31] compiler_4.2.2        httr_1.4.2            assertthat_0.2.1     
##  [34] fastmap_1.1.0         lazyeval_0.2.2        limma_3.50.0         
##  [37] cli_3.4.1             later_1.3.0           htmltools_0.5.2      
##  [40] tools_4.2.2           igraph_1.2.11         gtable_0.3.0         
##  [43] glue_1.5.1            RANN_2.6.1            reshape2_1.4.4       
##  [46] Rcpp_1.0.8            scattermore_0.7       jquerylib_0.1.4      
##  [49] vctrs_0.5.1           nlme_3.1-153          lmtest_0.9-39        
##  [52] xfun_0.28             stringr_1.4.0         globals_0.14.0       
##  [55] mime_0.12             miniUI_0.1.1.1        lifecycle_1.0.3      
##  [58] irlba_2.3.3           goftest_1.2-3         future_1.23.0        
##  [61] MASS_7.3-58           zoo_1.8-9             scales_1.2.1         
##  [64] spatstat.core_2.3-1   promises_1.2.0.1      spatstat.utils_2.2-0 
##  [67] parallel_4.2.2        yaml_2.2.1            pbapply_1.5-0        
##  [70] gridExtra_2.3         sass_0.4.0            rpart_4.1.19         
##  [73] stringi_1.7.6         highr_0.9             randomForest_4.7-1   
##  [76] rlang_1.0.6           pkgconfig_2.0.3       matrixStats_0.61.0   
##  [79] evaluate_0.14         lattice_0.20-45       ROCR_1.0-11          
##  [82] purrr_0.3.4           tensor_1.5            labeling_0.4.2       
##  [85] patchwork_1.1.1       htmlwidgets_1.5.4     tidyselect_1.1.1     
##  [88] parallelly_1.29.0     RcppAnnoy_0.0.19      plyr_1.8.6           
##  [91] magrittr_2.0.2        R6_2.5.1              generics_0.1.1       
##  [94] DBI_1.1.1             withr_2.5.0           mgcv_1.8-41          
##  [97] pillar_1.6.4          fitdistrplus_1.1-6    scatterplot3d_0.3-41 
## [100] survival_3.4-0        abind_1.4-5           tibble_3.1.6         
## [103] future.apply_1.8.1    crayon_1.4.2          KernSmooth_2.23-20   
## [106] utf8_1.2.2            spatstat.geom_2.4-0   plotly_4.10.0        
## [109] rmarkdown_2.11        locfit_1.5-9.4        grid_4.2.2           
## [112] data.table_1.14.2     digest_0.6.29         xtable_1.8-4         
## [115] tidyr_1.1.4           httpuv_1.6.3          openssl_1.4.5        
## [118] munsell_0.5.0         viridisLite_0.4.0     bslib_0.3.1          
## [121] askpass_1.1

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

LS0tCnRpdGxlOiAiUGlkZDEgS08gYW5ub3RhdGlvbiIKYXV0aG9yOgogICAtIE1hdHRoaWV1IE1vcmVhdV5bSW5zdGl0dXRlIG9mIFBzeWNoaWF0cnkgYW5kIE5ldXJvc2NpZW5jZSBvZiBQYXJpcywgSU5TRVJNIFUxMjY2LCA3NTAxNCwgUGFyaXMsIEZyYW5jZSwgbWF0dGhpZXUubW9yZWF1QGluc2VybS5mcl0gWyFbXShodHRwczovL29yY2lkLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL2ltYWdlcy9vcmNpZF8xNngxNi5wbmcpXShodHRwczovL29yY2lkLm9yZy8wMDAwLTAwMDItMjU5Mi0yMzczKQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVknKWAiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDogCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIGRmX3ByaW50OiB0aWJibGUKICAgIGhpZ2hsaWdodDogaGFkZG9jawogICAgdGhlbWU6IGNvc21vCiAgICBjc3M6ICIuLi9zdHlsZS5jc3MiCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA1CiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogeWVzCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgZmlnLmFsaWduID0gJ2NlbnRlcicsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlLmxhenkgPSBGQUxTRSkKYGBgCgojIExvYWQgbGlicmFyaWVzCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShzY3JhdHRjaC5oaWNhdCkKbGlicmFyeShGYXRlSUQpCmxpYnJhcnkoTWF0cml4KQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdnRXh0cmEpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShyZXRpY3VsYXRlKQpsaWJyYXJ5KHdlc2FuZGVyc29uKQpsaWJyYXJ5KHByaW5jdXJ2ZSkKdXNlX3B5dGhvbigiL3Vzci9iaW4vcHl0aG9uMyIpCgojU2V0IGdncGxvdCB0aGVtZSBhcyBjbGFzc2ljCnRoZW1lX3NldCh0aGVtZV9jbGFzc2ljKCkpCmBgYAoKIyBQcm9qZWN0IHByb2dlbml0b3JzIGRvbWFpbiBpZGVudCBmcm9tIFdUCgpgYGB7cn0KIyBMb2FkIHRoZSByYXcgY291bnRzIG1hdHJpeApwYXRoLnJlZiA8LSAiL21udC9CODkyNkI4RTkyNkI1MDQ0LzIwMTctMjAyMV9QaWVyYW5pLWxhYi9Qcm9qZXRfQ1JfdHJhbnNjcmlwdG9tZV9zY1JOQXNlcS9EYXRhc2V0cy9FMTEtMTJfSGVtLVdudDNhQ3JlXzExLTE5L2hlbUNSL1FDLmZpbHRlcmVkLmNsdXN0ZXJlZC5jZWxscy5SRFMiCgoKV1QuS08gPC0gbGlzdChXVCA9IHJlYWRSRFMocGF0aC5yZWYpICU+JQogICAgICAgICAgICAgICAgc3Vic2V0KHN1YnNldCA9IG9yaWcuaWRlbnQgPT0gIkhlbTEiICYgQ2VsbF9pZGVudCAlaW4lIGMoIkNoUF9wcm9nZW5pdG9ycyIsICJDaFAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRvcnNvLU1lZGlhbF9wYWxsaXVtIiwgIk1lZGlhbF9wYWxsaXVtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJIZW0iLCAiVGhhbGFtaWNfZW1pbmVuY2UiKSApLAogICAgICAgICAgICAgIEtPID0gcmVhZFJEUygiUGlkZDFLTy5jZWxscy5SRFMiKSAlPiUgc3Vic2V0KGlkZW50cyA9IGMoMCwxLDMsNikpKQoKZ2MoKQpgYGAKCgpgYGB7cn0KcDEgPC0gRGltUGxvdChvYmplY3QgPSBXVC5LT1tbIldUIl1dLAogICAgICAgIGdyb3VwLmJ5ID0gIkNlbGwuc3RhdGUiLAogICAgICAgIHJlZHVjdGlvbiA9ICJzcHJpbmciLAogICAgICAgIGNvbHMgPSBjKCIjMzFiNmJkIiwgIiNlYmNiMmUiLCAiIzllYzIyZiIsICIjY2MzYTFiIiwgIiNkMTRjOGQiLCAiIzRjYWJkYyIsICIjNWFiNzkzIiwgIiNlNzgyM2EiLCAiIzA0NmM5YSIsICIjNDk5MGM5IiksCiAgICAgICAgcHQuc2l6ZSA9IDEuNQogICAgICAgICkgICYgTm9BeGVzKCkKCnAyIDwtIERpbVBsb3QoV1QuS09bWyJLTyJdXSwKICAgICAgICByZWR1Y3Rpb24gPSAic3ByaW5nIiwKICAgICAgICBncm91cC5ieSA9ICJCcm9hZGNsdXN0LmlkZW50IiwKICAgICAgICBjb2xzID0gYygiI2ViY2IyZSIsICIjOWVjMjJmIiwgIiNhOTk2MWIiLCAiI2NjM2ExYiIpLAogICAgICAgIHB0LnNpemUgPSAxLjUpICYgTm9BeGVzKCkKCnAxICsgcDIKYGBgCgpgYGB7cn0KV1QuS09bWyJXVCJdXSA8LSBOb3JtYWxpemVEYXRhKFdULktPW1siV1QiXV0sIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIkxvZ05vcm1hbGl6ZSIsIHNjYWxlLmZhY3RvciA9IDEwMDAwLCBhc3NheSA9ICJSTkEiKQpXVC5LT1tbIktPIl1dIDwtIE5vcm1hbGl6ZURhdGEoV1QuS09bWyJLTyJdXSwgbm9ybWFsaXphdGlvbi5tZXRob2QgPSAiTG9nTm9ybWFsaXplIiwgc2NhbGUuZmFjdG9yID0gMTAwMDAsIGFzc2F5ID0gIlJOQSIpCmBgYAoKYGBge3J9CldULktPW1siV1QiXV0gPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoV1QuS09bWyJXVCJdXSwgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAyMDAwKQpXVC5LT1tbIktPIl1dIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKFdULktPW1siS08iXV0sIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gMjAwMCkKYGBgCgpgYGB7cn0KZmVhdHVyZXMgPC0gU2VsZWN0SW50ZWdyYXRpb25GZWF0dXJlcyhvYmplY3QubGlzdCA9IFdULktPLCBuZmVhdHVyZXMgPSAxNTAwKQpgYGAKCiMjIFRyYW5zZmVydCBpZGVudGl0eSBsYWJlbHMgV1QgdG8gS08KCmBgYHtyIGNsYXNzLm91dHB1dD0ic2Nyb2xsLTEwMCIsIGNhY2hlPVRSVUV9CktPLmFuY2hvcnMgPC0gRmluZFRyYW5zZmVyQW5jaG9ycyhyZWZlcmVuY2UgPSBXVC5LT1tbIldUIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXVlcnkgPSBXVC5LT1tbIktPIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSBmZWF0dXJlcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJycGNhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsuYW5jaG9yID0gNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsuZmlsdGVyID0gMTAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgay5zY29yZSA9IDMwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnBjcyA9IDIwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IDE6MjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguZmVhdHVyZXMgPSAyMDApCgpwcmVkaWN0aW9ucyA8LSBUcmFuc2ZlckRhdGEoYW5jaG9yc2V0ID0gS08uYW5jaG9ycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZmRhdGEgPSBXVC5LT1tbIldUIl1dJENlbGwuc3RhdGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gMToyMCkKCldULktPW1siS08iXV0gPC0gQWRkTWV0YURhdGEoV1QuS09bWyJLTyJdXSwgbWV0YWRhdGEgPSBwcmVkaWN0aW9ucykKYGBgCgpgYGB7cn0KY29scyA8LSBicmV3ZXIucGFsKG4gPTExLCBuYW1lID0gIlNwZWN0cmFsIikKCmdncGxvdChXVC5LT1tbIktPIl1dQG1ldGEuZGF0YSwgYWVzKFNwcmluZ18xLCBTcHJpbmdfMikpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1wcmVkaWN0aW9uLnNjb3JlLm1heCksIHNpemU9MSwgc2hhcGU9MTYpICsgCiAgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG91cnM9cmV2KGNvbHMpLCBuYW1lPSdwcmVkaWN0aW9uLnNjb3JlLm1heCcpCmBgYAoKYGBge3J9CnAxIDwtIERpbVBsb3Qob2JqZWN0ID0gV1QuS09bWyJXVCJdXSwKICAgICAgICBncm91cC5ieSA9ICJDZWxsLnN0YXRlIiwKICAgICAgICByZWR1Y3Rpb24gPSAic3ByaW5nIiwKICAgICAgICBjb2xzID0gYygiIzcyOTNjOCIsICIjYjc5ZjBiIiwgIiMzY2E3M2YiLCIjMzFiNmJkIiwKICAgICAgICAgICAgICAgICAiI2ViY2IyZSIsICIjOWVjMjJmIiwgIiNhOTk2MWIiLCAiI2NjM2ExYiIpLAogICAgICAgIHB0LnNpemUgPSAxKSAgJiBOb0F4ZXMoKQoKcDIgPC0gRGltUGxvdChXVC5LT1tbIktPIl1dLAogICAgICAgICAgICAgIGdyb3VwLmJ5ID0gInByZWRpY3RlZC5pZCIsCiAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInNwcmluZyIsCiAgICAgICAgICAgICAgY29scyA9IGMoIiM3MjkzYzgiLCIjMzFiNmJkIiwKICAgICAgICAgICAgICAgICAiI2ViY2IyZSIsICIjOWVjMjJmIiwgIiNhOTk2MWIiLCAiI2NjM2ExYiIpLAogICAgICAgICAgICAgIHB0LnNpemUgPSAxKSAmIE5vQXhlcygpCgpwMSArIHAyCmBgYAoKIyMgVHJhbnNmZXJ0IHRvIHRoZSBmdWxsIGRhdGFzZXQKCmBgYHtyfQpQcm9qZWN0ZWQuaWRlbnRzIDwtIFdULktPW1siS08iXV1AbWV0YS5kYXRhCgpybShsaXN0ID0gbHMoKVshbHMoKSAlaW4lIGMoIlByb2plY3RlZC5pZGVudHMiKV0pCmdjKCkKYGBgCgoKYGBge3J9ClJhdy5kYXRhIDwtIHJlYWRSRFMoIlBpZGQxS08uY2VsbHMuUkRTIikKClJhdy5kYXRhJENlbGwuaWRlbnQgPC0gc2FwcGx5KFJhdy5kYXRhJEJhcmNvZGVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSBmdW5jdGlvbih4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHggJWluJSBQcm9qZWN0ZWQuaWRlbnRzICRCYXJjb2RlcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IFByb2plY3RlZC5pZGVudHNbeCwgInByZWRpY3RlZC5pZCJdCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSBSYXcuZGF0YUBtZXRhLmRhdGFbeCwgIkJyb2FkY2x1c3QuaWRlbnQiXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KQpgYGAKCmBgYHtyfQpEaW1QbG90KG9iamVjdCA9IFJhdy5kYXRhLAogICAgICAgIGdyb3VwLmJ5ID0gIkNlbGwuaWRlbnQiLAogICAgICAgIHJlZHVjdGlvbiA9ICJzcHJpbmciLAogICAgICAgIGNvbHMgPSBjKCIjNGNhYmRjIiwgIiM3MjkzYzgiLCAiZ3JleTQwIiwgIiM3MjkzYzgiLCIjMzFiNmJkIiwKICAgICAgICAgICAgICAgICAiI2ViY2IyZSIsICIjOWVjMjJmIiwgIiNhOTk2MWIiLCAiI2NjM2ExYiIpLAogICAgICAgIHB0LnNpemUgPSAwLjUpICAmIE5vQXhlcygpCmBgYAoKYGBge3J9CnJtKGxpc3QgPSBscygpWyFscygpICVpbiUgIlJhdy5kYXRhIl0pCmdjKCkKYGBgCgojIEFubm90YXRlIGRpZmZlcmVudGlhdGluZyBuZXVyb25zCgojIyBDZWxsIHN0YXRlIHNjb3JlCgpgYGB7cn0KIyBBUAoKQVBnZW5lcyA8LSBjKCJSZ2NjIiwgIlNwYXJjIiwgIkhlczUiLCJIZXMxIiwgIlNsYzFhMyIsCiAgICAgICAgICAgICAiRGRhaDEiLCAiTGRoYSIsICJIbWdhMiIsIlNmcnAxIiwgIklkNCIsCiAgICAgICAgICAgICAiQ3JlYjUiLCAiUHRuIiwgIkxwYXIxIiwgIlJjbjEiLCJaZnAzNmwxIiwKICAgICAgICAgICAgICJTb3g5IiwgIlNveDIiLCAiTnIyZTEiLCAiVHR5aDEiLCAiVHJpcDYiKQoKUmF3LmRhdGEgPC0gQWRkTW9kdWxlU2NvcmUoUmF3LmRhdGEsCiAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gbGlzdChBUGdlbmVzKSwKICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJBUF9zaWduYXR1cmUiKQpgYGAKCmBgYHtyfQojIEJQCgpCUGdlbmVzIDwtIGMoIkVvbWVzIiwgIklnc2Y4IiwgIkluc20xIiwgIkVsYXZsMiIsICJFbGF2bDQiLAogICAgICAgICAgICAgIkhlczYiLCJHYWRkNDVnIiwgIk5ldXJvZzIiLCAiQnRnMiIsICJOZXVyb2cxIikKClJhdy5kYXRhPC0gQWRkTW9kdWxlU2NvcmUoUmF3LmRhdGEsCiAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gbGlzdChCUGdlbmVzKSwKICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJCUF9zaWduYXR1cmUiKQpgYGAKCmBgYHtyfQojIEVOCgpFTmdlbmVzIDwtIGMoIk1mYXA0IiwgIk5obGgyIiwgIk5obGgxIiwgIlBwcDFyMTRhIiwgIk5hdjEiLAogICAgICAgICAgICAgIk5ldXJvZDEiLCAiU29ybDEiLCAiU3ZpcCIsICJDeGNsMTIiLCAiVGVubTQiLAogICAgICAgICAgICAgIkRsbDMiLCAiUmdtYiIsICJDbnRuMiIsICJWYXQxIikKClJhdy5kYXRhIDwtIEFkZE1vZHVsZVNjb3JlKFJhdy5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9IGxpc3QoRU5nZW5lcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiRU5fc2lnbmF0dXJlIikKYGBgCgpgYGB7cn0KIyBMTgoKTE5nZW5lcyA8LSBjKCJTbmhnMTEiLCAiUGNzazFuIiwgIk1hcHQiLCAiSW5hIiwgIlN0bW40IiwKICAgICAgICAgICAgICJHYXA0MyIsICJUdWJiMmEiLCAiTHk2aCIsIlB0cHJkIiwgIk1lZjJjIikKClJhdy5kYXRhIDwtIEFkZE1vZHVsZVNjb3JlKFJhdy5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9IGxpc3QoTE5nZW5lcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiTE5fc2lnbmF0dXJlIikKYGBgCgpgYGB7cn0KRmVhdHVyZVBsb3Qob2JqZWN0ID0gUmF3LmRhdGEsCiAgICAgICAgICAgIGZlYXR1cmVzID0gYygiQVBfc2lnbmF0dXJlMSIsICJCUF9zaWduYXR1cmUxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkVOX3NpZ25hdHVyZTEiLCAiTE5fc2lnbmF0dXJlMSIpLAogICAgICAgICAgICBwdC5zaXplID0gMC43NSwKICAgICAgICAgICAgY29scyA9IHJldihicmV3ZXIucGFsKDEwLCJTcGVjdHJhbCIpKSwKICAgICAgICAgICAgcmVkdWN0aW9uID0gInNwcmluZyIsCiAgICAgICAgICAgIG9yZGVyID0gVCkgJiBOb0F4ZXMoKSAmIE5vTGVnZW5kKCkKYGBgCgojIyBBbm5vdGF0ZSBtb3N0IG1hdHVyZSBuZXVyb25zCgpgYGB7cn0KTE4uZGF0YSA8LSBSYXcuZGF0YSAlPiUgc3Vic2V0KHN1YnNldCA9IENlbGwuaWRlbnQgJWluJSBjKDMsNikpCmBgYAoKCmBgYHtyfQojIEstbWVhbnMgY2x1c3RlcmluZyBiYXNlZCBvbiBBUCwgU1AgYW5kIFBhbCBzaWduYXR1cmUgc2NvcmVzCnNldC5zZWVkKDEwMCkKY2wgPC0ga21lYW5zKGNiaW5kKExOLmRhdGEkQlBfc2lnbmF0dXJlMSwKICAgICAgICAgICAgICAgICAgIExOLmRhdGEkRU5fc2lnbmF0dXJlMSwKICAgICAgICAgICAgICAgICAgIExOLmRhdGEkTE5fc2lnbmF0dXJlMSksIDIpCgpMTi5kYXRhJGttZWFuQ2x1c3QgPC0gcGFzdGUwKCJDbHVzdC4iLGNsJGNsdXN0ZXIpCmBgYAoKYGBge3J9CmNvbC5wYWwgPC0gd2VzX3BhbGV0dGUoIkdyYW5kQnVkYXBlc3QxIiwgNCwgdHlwZSA9ICJkaXNjcmV0ZSIpCgpwMSA8LSBnZ3Bsb3QoTE4uZGF0YUBtZXRhLmRhdGEsIGFlcyh4PUxOX3NpZ25hdHVyZTEsIHk9RU5fc2lnbmF0dXJlMSwgY29sb3VyID0ga21lYW5DbHVzdCkpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWNvbC5wYWwpICsKICBnZW9tX3BvaW50KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQpnZ01hcmdpbmFsKHAxLCB0eXBlID0gImhpc3RvZ3JhbSIsIGZpbGw9ImxpZ2h0Z3JleSIpCmBgYAoKYGBge3J9CkRpbVBsb3Qob2JqZWN0ID0gTE4uZGF0YSwKICAgICAgICBncm91cC5ieSA9ICJrbWVhbkNsdXN0IiwKICAgICAgICByZWR1Y3Rpb24gPSAic3ByaW5nIiwKICAgICAgICBjb2xzID0gY29sLnBhbCwKICAgICAgICBwdC5zaXplID0gMC41KSAgJiBOb0F4ZXMoKQpgYGAKCmBgYHtyfQpMTi5kYXRhIDwtIExOLmRhdGEgICU+JSBzdWJzZXQoc3Vic2V0ID0ga21lYW5DbHVzdCA9PSAiQ2x1c3QuMiIgJiBTcHJpbmdfMiA+IDI1MDApCgpEaW1QbG90KG9iamVjdCA9IExOLmRhdGEsCiAgICAgICAgZ3JvdXAuYnkgPSAia21lYW5DbHVzdCIsCiAgICAgICAgcmVkdWN0aW9uID0gInNwcmluZyIsCiAgICAgICAgY29scyA9IGMoIiM0Y2FiZGMiLCAiIzcyOTNjOCIsICJncmV5NDAiKSwKICAgICAgICBwdC5zaXplID0gMC41KSAgJiBOb0F4ZXMoKQpgYGAKCiMjIyBQcmVwYXJlIHRoZSBkYXRhc2V0IGZvciBjbHVzdGVyaW5nIHdpdGggc2NyYXR0Y2guaGljYXQKCmBgYHtyfQojIEV4Y2x1ZGUgZ2VuZXMgZGV0ZWN0ZWQgaW4gbGVzcyB0aGFuIDMgY2VsbHMKbnVtLmNlbGxzIDwtIE1hdHJpeDo6cm93U3VtcyhMTi5kYXRhQGFzc2F5c1tbIlJOQSJdXUBjb3VudHMgPiAwKQpnZW5lcy51c2UgPC0gbmFtZXMoeCA9IG51bS5jZWxsc1t3aGljaCh4ID0gbnVtLmNlbGxzID49IDMpXSkKCkdlbmVzVG9SZW1vdmUgPC0gYyhncmVwKHBhdHRlcm4gPSAiKF5ScGx8XlJwc3xeTXJwKSIsIHggPSBnZW5lcy51c2UsIHZhbHVlID0gVFJVRSksCiAgICAgICAgICAgICAgICAgICBncmVwKHBhdHRlcm4gPSAiXm10LSIsIHggPSBnZW5lcy51c2UsIHZhbHVlID0gVFJVRSksCiAgICAgICAgICAgICAgICAgICAiWGlzdCIpCgpnZW5lcy51c2UgPC0gZ2VuZXMudXNlWyFnZW5lcy51c2UgJWluJSBHZW5lc1RvUmVtb3ZlXQpgYGAKCmBgYHtyfQpkZ2VNYXRyaXhfY291bnQgPC0gYXMubWF0cml4KExOLmRhdGFAYXNzYXlzW1siUk5BIl1dQGNvdW50cylbcm93bmFtZXMoTE4uZGF0YUBhc3NheXNbWyJSTkEiXV1AY291bnRzKSAlaW4lIGdlbmVzLnVzZSxdCmRnZU1hdHJpeF9jcG0gPC0gY3BtKGRnZU1hdHJpeF9jb3VudCkKbm9ybS5kYXQgPC0gbG9nMihkZ2VNYXRyaXhfY3BtICsgMSkKCm5vcm0uZGF0IDwtIE1hdHJpeChub3JtLmRhdCwgc3BhcnNlID0gVFJVRSkKRGF0YS5tYXRyaXggPC0gbGlzdChyYXcuZGF0PWRnZU1hdHJpeF9jb3VudCwgbm9ybS5kYXQ9bm9ybS5kYXQpCmF0dGFjaChEYXRhLm1hdHJpeCkKYGBgCgpgYGB7cn0KZ2VuZS5jb3VudHMgPC0gbG9nMihjb2xTdW1zKGFzLm1hdHJpeChEYXRhLm1hdHJpeCRub3JtLmRhdCkgPiAwKSkKblVNSSA8LSBsb2cyKGNvbFN1bXMoRGF0YS5tYXRyaXgkcmF3LmRhdCkpCnBlcmN0TWl0byA8LSBMTi5kYXRhJHBlcmNlbnQubWl0bwpwZXJjdFJpYm8gPC0gTE4uZGF0YSRwZXJjZW50LnJpYm8KTE5zY29yZSA8LSBMTi5kYXRhJExOX3NpZ25hdHVyZTEKCnJtLmVpZ2VuIDwtIGFzLm1hdHJpeChjYmluZChnZW5lLmNvdW50cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5VTUksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJjdE1pdG8sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJjdFJpYm8sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMTnNjb3JlICkpCgpyb3cubmFtZXMocm0uZWlnZW4pIDwtIG5hbWVzKGdlbmUuY291bnRzKQoKY29sbmFtZXMocm0uZWlnZW4pIDwtIGMoImxvZzJuR2VuZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAibG9nMm5VTUkiLAogICAgICAgICAgICAgICAgICAgICAgICAicGVyY3RNaXRvIiwKICAgICAgICAgICAgICAgICAgICAgICAgInBlcmN0UmlibyIsCiAgICAgICAgICAgICAgICAgICAgICAgICJMTnNjb3JlIikKCnJtKGdlbmUuY291bnRzLCBuVU1JLCBwZXJjdE1pdG8sIHBlcmN0UmlibywgTE5zY29yZSkKYGBgCgojIyMgUnVuIHNjcmF0dGNoLmhpY2F0CgpgYGB7cn0KIyBQYXJhbWV0ZXJzIGZvciBpdGVyYXRpdmUgY2x1c3RlcmluZwpkZS5wYXJhbSA8LSBkZV9wYXJhbShwYWRqLnRoICAgICA9IDAuMDEsIAogICAgICAgICAgICAgICAgICAgICBsZmMudGggICAgICA9IDEsCiAgICAgICAgICAgICAgICAgICAgIGxvdy50aCAgICAgID0gMSwgCiAgICAgICAgICAgICAgICAgICAgIHExLnRoICAgICAgID0gMC4yNSwgCiAgICAgICAgICAgICAgICAgICAgIHEyLnRoICAgICAgID0gTlVMTCwKICAgICAgICAgICAgICAgICAgICAgcS5kaWZmLnRoICAgPSAwLjcsCiAgICAgICAgICAgICAgICAgICAgIGRlLnNjb3JlLnRoID0gMjAwLAogICAgICAgICAgICAgICAgICAgICBtaW4uY2VsbHMgICA9IDEwKQpgYGAKCmBgYHtyIGNsYXNzLm91dHB1dD0ic2Nyb2xsLTEwMCIsIGNhY2hlPVRSVUV9Cml0ZXIucmVzdWx0IDwtIGl0ZXJfY2x1c3Qobm9ybS5kYXQsIAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50cyA9IHJhdy5kYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGltLm1ldGhvZCA9ICJwY2EiLAogICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5kaW0gPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgICBrLm5uID0gNSwKICAgICAgICAgICAgICAgICAgICAgICAgICBkZS5wYXJhbSA9IGRlLnBhcmFtLAogICAgICAgICAgICAgICAgICAgICAgICAgIHJtLmVpZ2VuID0gcm0uZWlnZW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgcm0udGggPSAwLjYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgdmcucGFkai50aCA9IDAuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAibG91dmFpbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZml4ID0gIml0ZXJfY2x1c3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBGKQpgYGAKCmBgYHtyfQojIE1lcmdlIGNsdXN0ZXJzIHdoaWNoIGFyZSBub3Qgc2VwZXJhYmxlIGJ5IERFR3MKcmQuZGF0IDwtIHQobm9ybS5kYXRbaXRlci5yZXN1bHQkbWFya2VycyxdKQptZXJnZS5yZXN1bHQgPC0gbWVyZ2VfY2wobm9ybS5kYXQsIAogICAgICAgICAgICAgICAgICAgICAgICAgY2wgPSBpdGVyLnJlc3VsdCRjbCwgCiAgICAgICAgICAgICAgICAgICAgICAgICByZC5kYXQgPSByZC5kYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICBkZS5wYXJhbSA9IGRlLnBhcmFtKQoKY2F0KGxlbmd0aCh1bmlxdWUobWVyZ2UucmVzdWx0JGNsKSksIiBDbHVzdGVycyIpCmBgYAoKYGBge3J9CkxOLmRhdGEkaXRlci5jbHVzdCA8LSBtZXJnZS5yZXN1bHQkY2wKCklkZW50cyhMTi5kYXRhKSA8LSAiaXRlci5jbHVzdCIKCmNvbG9ycyA8LSAgYygiI2ViY2IyZSIsICIjOWVjMjJmIiwgIiNjYzNhMWIiKQoKRGltUGxvdChMTi5kYXRhLAogICAgICAgIHJlZHVjdGlvbiA9ICJzcHJpbmciLAogICAgICAgICNjb2xzID0gY29sb3JzLAogICAgICAgIHB0LnNpemUgPSAxLjUpICYgTm9BeGVzKCkKYGBgCgpgYGB7cn0KUmF3LmRhdGEkQ2VsbC5pZGVudCA8LSBzYXBwbHkoUmF3LmRhdGEkQmFyY29kZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9IGZ1bmN0aW9uKHgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoeCAlaW4lIExOLmRhdGEkQmFyY29kZXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSBwYXN0ZTAoIkxOLiIsIExOLmRhdGFAbWV0YS5kYXRhW3gsICJpdGVyLmNsdXN0Il0pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSBSYXcuZGF0YUBtZXRhLmRhdGFbeCwgIkNlbGwuaWRlbnQiXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KQpgYGAKCmBgYHtyfQpSYXcuZGF0YSRDZWxsLmlkZW50IDwtIGlmZWxzZShSYXcuZGF0YSRDZWxsLmlkZW50ICVpbiUgYygzLDUpLCAiUGFsLm5ldXJvbi50cmFqIiwgUmF3LmRhdGEkQ2VsbC5pZGVudCkKUmF3LmRhdGEkQ2VsbC5pZGVudCA8LSBpZmVsc2UoUmF3LmRhdGEkQ2VsbC5pZGVudCA9PSA2LCAiQ1IudHJhaiIsIFJhdy5kYXRhJENlbGwuaWRlbnQpClJhdy5kYXRhJENlbGwuaWRlbnQgPC0gaWZlbHNlKFJhdy5kYXRhJENlbGwuaWRlbnQgPT0gIlRoYWxhbWljX2VtaW5lbmNlIiwgIlNlcHR1bV9BTlIiLCBSYXcuZGF0YSRDZWxsLmlkZW50KQpgYGAKCmBgYHtyfQpSYXcuZGF0YSRDZWxsLmlkZW50IDwtIGlmZWxzZShSYXcuZGF0YSRDZWxsLmlkZW50ID09ICJQYWwubmV1cm9uLnRyYWoiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRGlmZmVyZW50aWF0aW5nX25ldXJvbnMiLCBSYXcuZGF0YSRDZWxsLmlkZW50KQoKUmF3LmRhdGEkQ2VsbC5pZGVudCA8LSBpZmVsc2UoUmF3LmRhdGEkQ2VsbC5pZGVudCA9PSAiU2VwdHVtX0FOUiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQcm9nZW5pdG9yc19TZXB0dW1fQU5SIiwgUmF3LmRhdGEkQ2VsbC5pZGVudCkKClJhdy5kYXRhJENlbGwuaWRlbnQgPC0gaWZlbHNlKFJhdy5kYXRhJENlbGwuaWRlbnQgPT0gIk1lZGlhbF9wYWxsaXVtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlByb2dlbml0b3JzX01lZGlhbC1wYWxsaXVtIiwgUmF3LmRhdGEkQ2VsbC5pZGVudCkKClJhdy5kYXRhJENlbGwuaWRlbnQgPC0gaWZlbHNlKFJhdy5kYXRhJENlbGwuaWRlbnQgPT0gIkhlbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQcm9nZW5pdG9yc19IZW0iLCBSYXcuZGF0YSRDZWxsLmlkZW50KQoKUmF3LmRhdGEkQ2VsbC5pZGVudCA8LSBpZmVsc2UoUmF3LmRhdGEkQ2VsbC5pZGVudCA9PSAiRG9yc28tTWVkaWFsX3BhbGxpdW0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUHJvZ2VuaXRvcnNfRG9yc28tTWVkaWFsLXBhbGxpdW0iLCBSYXcuZGF0YSRDZWxsLmlkZW50KQoKUmF3LmRhdGEkQ2VsbC5pZGVudCA8LSBpZmVsc2UoUmF3LmRhdGEkQ2VsbC5pZGVudCA9PSAiQ2hQX3Byb2dlbml0b3JzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlByb2dlbml0b3JzX0NoUCIsIFJhdy5kYXRhJENlbGwuaWRlbnQpCgpSYXcuZGF0YSRDZWxsLmlkZW50IDwtIGlmZWxzZShSYXcuZGF0YSRDZWxsLmlkZW50ID09ICJDaFBfRWFybHkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2hvcm9pZF9QbGV4dXMiLCBSYXcuZGF0YSRDZWxsLmlkZW50KQoKUmF3LmRhdGEkQ2VsbC5pZGVudCA8LSBpZmVsc2UoUmF3LmRhdGEkQ2VsbC5pZGVudCA9PSAiQ1IudHJhaiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJEaWZmZXJlbnRpYXRpbmdfQ1JzIiwgUmF3LmRhdGEkQ2VsbC5pZGVudCkKClJhdy5kYXRhJENlbGwuaWRlbnQgPC0gaWZlbHNlKFJhdy5kYXRhJENlbGwuaWRlbnQgPT0gIkxOLjUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTmV1cm9uc19DYWphbC1SZXR6aXVzIiwgUmF3LmRhdGEkQ2VsbC5pZGVudCkKClJhdy5kYXRhJENlbGwuaWRlbnQgPC0gaWZlbHNlKFJhdy5kYXRhJENlbGwuaWRlbnQgJWluJSBjKCJMTi42IiwgIkxOLk5BIiwgIkxOLjEiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5ldXJvbnNfRG9yc2FsLVBhbGxpdW0iLCBSYXcuZGF0YSRDZWxsLmlkZW50KQoKUmF3LmRhdGEkQ2VsbC5pZGVudCA8LSBpZmVsc2UoUmF3LmRhdGEkQ2VsbC5pZGVudCAlaW4lIGMoIkxOLjciKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5ldXJvbnNfTWVkaWFsLVBhbGxpdW0iLCBSYXcuZGF0YSRDZWxsLmlkZW50KQpgYGAKCmBgYHtyfQpEaW1QbG90KG9iamVjdCA9IFJhdy5kYXRhLAogICAgICAgIGdyb3VwLmJ5ID0gIkNlbGwuaWRlbnQiLAogICAgICAgIHJlZHVjdGlvbiA9ICJzcHJpbmciLAogICAgICAgIGNvbHMgPSBjKCJncmV5NDAiLCIjNGNhYmRjIiwiIzA0NmM5YSIsICIjNzI5M2M4IiwgIiMzMWI2YmQiLCAiI2ViY2IyZSIsICIjOWVjMjJmIiwgIiNhOTk2MWIiLCAiI2NjM2ExYiIsIHdlc19wYWxldHRlKCJGYW50YXN0aWNGb3gxIikpLAogICAgICAgIHB0LnNpemUgPSAwLjUpICAmIE5vQXhlcygpCmBgYAoKYGBge3J9CnJtKGxpc3QgPSBscygpWyFscygpICVpbiUgYygiUmF3LmRhdGEiKV0pCmdjKCkKYGBgCgoKIyBHZW5lcmF0ZSBTUklORyBkaW1lbnRpb25hbGl0eSByZWR1Y3Rpb24KCiMjIEV4cG9ydCBjb3VudHMgbWF0cml4CgpgYGB7cn0KZGlyLmNyZWF0ZSgiLi9TcHJpbmdDb29yZGluYXRlcy9TcHJpbmdDb29yZGluYXRlc19jbGVhbmVkIikKYGBgCgpgYGB7cn0KIyBFeHBvcnQgcmF3IGV4cHJlc3Npb24gbWF0cml4IGFuZCBnZW5lIGxpc3QgdG8gcmVnZW5lcmF0ZSBhIHNwcmluZyBwbG90CmV4cHJEYXRhIDwtIE1hdHJpeChhcy5tYXRyaXgoUmF3LmRhdGFAYXNzYXlzW1siUk5BIl1dQGNvdW50cyksIHNwYXJzZSA9IFRSVUUpCndyaXRlTU0oZXhwckRhdGEsICIuL1NwcmluZ0Nvb3JkaW5hdGVzL1NwcmluZ0Nvb3JkaW5hdGVzX2NsZWFuZWQvRXhwckRhdGEubXR4IikKcm0oZXhwckRhdGEpCmBgYAoKYGBge3J9CkdlbmVsaXN0IDwtIHJvdy5uYW1lcyhSYXcuZGF0YUBhc3NheXNbWyJSTkEiXV1AY291bnRzKQp3cml0ZS50YWJsZShHZW5lbGlzdCwgIi4vU3ByaW5nQ29vcmRpbmF0ZXMvU3ByaW5nQ29vcmRpbmF0ZXNfY2xlYW5lZC9HZW5lbGlzdC5jc3YiLCBzZXA9Ilx0IiwgY29sLm5hbWVzID0gRiwgcm93Lm5hbWVzID0gRiwgcXVvdGUgPSBGKQpgYGAKCmBgYHtyfQojRXhwb3J0IG1ldGFkYXRhCklkZW50aXR5IDwtIGMoIklkZW50aXR5IiwgUmF3LmRhdGEkQ2VsbC5pZGVudCkKSWRlbnRpdHkgPC0gcGFzdGUoSWRlbnRpdHksIHNlcD0iLCIsIGNvbGxhcHNlPSIsIikKCkdlbm90eXBlIDwtIGMoIkdlbm90eXBlIiwgUmF3LmRhdGEkR2Vub3R5cGUpCkdlbm90eXBlIDwtIHBhc3RlKEdlbm90eXBlLCBzZXA9IiwiLCBjb2xsYXBzZT0iLCIpCgpDZWxsZ3JvdXBpbmcgPC0gcmJpbmQoSWRlbnRpdHksIEdlbm90eXBlKQp3cml0ZS50YWJsZShDZWxsZ3JvdXBpbmcsICIuL1NwcmluZ0Nvb3JkaW5hdGVzL1NwcmluZ0Nvb3JkaW5hdGVzX2NsZWFuZWQvQ2VsbGdyb3VwaW5nLmNzdiIsIHF1b3RlID1GLCByb3cubmFtZXMgPSBGLCBjb2wubmFtZXMgPSBGKQpgYGAKCmBgYHtyfQojQ2VsbHMgc2NvcmVzCkFQLnNjb3JlIDwtIGMoIkFQLnNjb3JlIiwgUmF3LmRhdGEkQVBfc2lnbmF0dXJlMSkKQVAuc2NvcmUgPC0gcGFzdGUoQVAuc2NvcmUsIHNlcD0iLCIsIGNvbGxhcHNlPSIsIikKCkJQLnNjb3JlIDwtIGMoIkJQLnNjb3JlIiwgUmF3LmRhdGEkQlBfc2lnbmF0dXJlMSkKQlAuc2NvcmUgPC0gcGFzdGUoQlAuc2NvcmUsIHNlcD0iLCIsIGNvbGxhcHNlPSIsIikKCkVOLnNjb3JlIDwtIGMoIkVOLnNjb3JlIiwgUmF3LmRhdGEkRU5fc2lnbmF0dXJlMSkKRU4uc2NvcmUgPC0gcGFzdGUoRU4uc2NvcmUsIHNlcD0iLCIsIGNvbGxhcHNlPSIsIikKCkxOLnNjb3JlIDwtIGMoIkxOLnNjb3JlIiwgUmF3LmRhdGEkTE5fc2lnbmF0dXJlMSkKTE4uc2NvcmUgPC0gcGFzdGUoTE4uc2NvcmUsIHNlcD0iLCIsIGNvbGxhcHNlPSIsIikKCkNvbG9yVHJhY2sgPC0gcmJpbmQoQVAuc2NvcmUsIEJQLnNjb3JlLCBFTi5zY29yZSwgTE4uc2NvcmUpCndyaXRlLnRhYmxlKENvbG9yVHJhY2ssICIuL1NwcmluZ0Nvb3JkaW5hdGVzL1NwcmluZ0Nvb3JkaW5hdGVzX2NsZWFuZWQvQ29sb3JUcmFjay5jc3YiLCBxdW90ZSA9Riwgcm93Lm5hbWVzID0gRiwgY29sLm5hbWVzID0gRikKYGBgCgoKYGBge3J9CiNDb29yZGluYXRlcwoKQ29vcmRpbmF0ZXMgPC0gY2JpbmQoYygxOm5yb3coUmF3LmRhdGFAbWV0YS5kYXRhKSktMSwKICAgICAgICAgICAgICAgICAgICAgUmF3LmRhdGEkU3ByaW5nXzEsCiAgICAgICAgICAgICAgICAgICAgIFJhdy5kYXRhJFNwcmluZ18yKQoKU3ByaW5nLlN5bSA8LSBmdW5jdGlvbih4KXsKICB4ID0gYWJzKG1heChDb29yZGluYXRlc1ssM10pLXgpCiB9CgpDb29yZGluYXRlc1ssM10gPC0gc2FwcGx5KENvb3JkaW5hdGVzWywzXSwgZnVuY3Rpb24oeCkgU3ByaW5nLlN5bSh4KSkKCndyaXRlLnRhYmxlKENvb3JkaW5hdGVzLCAiLi9TcHJpbmdDb29yZGluYXRlcy9TcHJpbmdDb29yZGluYXRlc19jbGVhbmVkL0N1c3RvbV9jb29yLmNzdiIsIHNlcCA9ICIsIiwgcXVvdGUgPUYsIHJvdy5uYW1lcyA9IEYsIGNvbC5uYW1lcyA9IEYpCmBgYAoKIyBTYXZlIHRoZSBvYmplY3QKCmBgYHtyIFNhdmUgUkRTfQpzYXZlUkRTKFJhdy5kYXRhLCAiLi9QaWRkMUtPLmNlbGxzLlJEUyIpCmBgYAoKIyBTZXNzaW9uIEluZm8KCmBgYHtyfQojZGF0ZQpmb3JtYXQoU3lzLnRpbWUoKSwgIiVkICVCLCAlWSwgJUgsJU0iKQoKI1BhY2thZ2VzIHVzZWQKc2Vzc2lvbkluZm8oKQpgYGAK