1. load libraries

2. Load Seurat Object


#Load Seurat Object merged from cell lines and a control(PBMC) after filtration
load("SS_merged_marie_obj-2-Variation.Robj")

All_samples_Merged
An object of class Seurat 
36629 features across 49193 samples within 2 assays 
Active assay: RNA (36601 features, 0 variable features)
 2 layers present: counts, data
 1 other assay present: ADT

3. Data PREPARATION


alldata <- All_samples_Merged

alldata.list <- SplitObject(alldata, split.by = "orig.ident")

for (i in 1:length(alldata.list)) {
    alldata.list[[i]] <- NormalizeData(alldata.list[[i]], verbose = FALSE)
    alldata.list[[i]] <- FindVariableFeatures(alldata.list[[i]], selection.method = "vst", nfeatures = 2000,verbose = FALSE)
}

# get the variable genes from all the datasets.
hvgs_per_dataset <- lapply(alldata.list, function(x) { x@assays$RNA@var.features })

# also add in the variable genes that was selected on the whole dataset
hvgs_per_dataset$all = VariableFeatures(alldata)

temp <- unique(unlist(hvgs_per_dataset))
overlap <- sapply( hvgs_per_dataset , function(x) { temp %in% x } )
pheatmap::pheatmap(t(overlap*1),cluster_rows = F ,
                   color = c("grey90","grey20"))


hvgs_all = SelectIntegrationFeatures(alldata.list)
hvgs_per_dataset$all_ranks = hvgs_all

temp <- unique(unlist(hvgs_per_dataset))
overlap <- sapply( hvgs_per_dataset , function(x) { temp %in% x } )
pheatmap::pheatmap(t(overlap*1),cluster_rows = F ,
                   color = c("grey90","grey20"))



alldata.list <- lapply(X = alldata.list, FUN = function(x) {
    x <- ScaleData(x, features = hvgs_all, verbose = FALSE)
    x <- RunPCA(x, features = hvgs_all, verbose = FALSE)
})

4. rpca-integration


alldata.anchors <- FindIntegrationAnchors(object.list = alldata.list, dims = 1:12, reduction = "rpca", anchor.features = hvgs_all)
Scaling features for provided objects

  |                                                  | 0 % ~calculating  
  |+++++++                                           | 12% ~05s          
  |+++++++++++++                                     | 25% ~04s          
  |+++++++++++++++++++                               | 38% ~04s          
  |+++++++++++++++++++++++++                         | 50% ~03s          
  |++++++++++++++++++++++++++++++++                  | 62% ~02s          
  |++++++++++++++++++++++++++++++++++++++            | 75% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=06s  
Computing within dataset neighborhoods

  |                                                  | 0 % ~calculating  
  |+++++++                                           | 12% ~17s          
  |+++++++++++++                                     | 25% ~13s          
  |+++++++++++++++++++                               | 38% ~11s          
  |+++++++++++++++++++++++++                         | 50% ~08s          
  |++++++++++++++++++++++++++++++++                  | 62% ~06s          
  |++++++++++++++++++++++++++++++++++++++            | 75% ~04s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~02s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=17s  
Finding all pairwise anchors

  |                                                  | 0 % ~calculating  
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 798 anchors

  |++                                                | 4 % ~03m 29s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 1024 anchors

  |++++                                              | 7 % ~03m 43s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 1251 anchors

  |++++++                                            | 11% ~03m 26s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 1784 anchors

  |++++++++                                          | 14% ~03m 17s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 628 anchors

  |+++++++++                                         | 18% ~03m 05s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 878 anchors

  |+++++++++++                                       | 21% ~02m 55s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 1614 anchors

  |+++++++++++++                                     | 25% ~02m 46s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 554 anchors

  |+++++++++++++++                                   | 29% ~02m 37s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 920 anchors

  |+++++++++++++++++                                 | 32% ~02m 29s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 2612 anchors

  |++++++++++++++++++                                | 36% ~02m 21s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 2016 anchors

  |++++++++++++++++++++                              | 39% ~02m 12s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 757 anchors

  |++++++++++++++++++++++                            | 43% ~02m 03s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 924 anchors

  |++++++++++++++++++++++++                          | 46% ~01m 55s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 1104 anchors

  |+++++++++++++++++++++++++                         | 50% ~01m 48s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 1352 anchors

  |+++++++++++++++++++++++++++                       | 54% ~01m 40s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 1053 anchors

  |+++++++++++++++++++++++++++++                     | 57% ~01m 32s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 644 anchors

  |+++++++++++++++++++++++++++++++                   | 61% ~01m 24s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 889 anchors

  |+++++++++++++++++++++++++++++++++                 | 64% ~01m 16s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 2061 anchors

  |++++++++++++++++++++++++++++++++++                | 68% ~01m 08s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 2628 anchors

  |++++++++++++++++++++++++++++++++++++              | 71% ~01m 00s      
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 1536 anchors

  |++++++++++++++++++++++++++++++++++++++            | 75% ~52s          
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 283 anchors

  |++++++++++++++++++++++++++++++++++++++++          | 79% ~45s          
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 294 anchors

  |++++++++++++++++++++++++++++++++++++++++++        | 82% ~38s          
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 281 anchors

  |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~30s          
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 262 anchors

  |+++++++++++++++++++++++++++++++++++++++++++++     | 89% ~23s          
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 255 anchors

  |+++++++++++++++++++++++++++++++++++++++++++++++   | 93% ~15s          
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 378 anchors

  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 96% ~08s          
Projecting new data onto SVD
Projecting new data onto SVD
Finding neighborhoods
Finding anchors
    Found 269 anchors

  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=03m 35s
alldata.int <- IntegrateData(anchorset = alldata.anchors, dims = 1:12, new.assay.name = "rpca")
Merging dataset 7 into 5
Extracting anchors for merged samples
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Merging dataset 6 into 1
Extracting anchors for merged samples
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Merging dataset 4 into 5 7
Extracting anchors for merged samples
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Merging dataset 2 into 3
Extracting anchors for merged samples
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Merging dataset 1 6 into 5 7 4
Extracting anchors for merged samples
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Merging dataset 3 2 into 5 7 4 1 6
Extracting anchors for merged samples
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Merging dataset 8 into 5 7 4 1 6 3 2
Extracting anchors for merged samples
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
names(alldata.int@assays)
[1] "RNA"  "ADT"  "rpca"
alldata.int@active.assay
[1] "rpca"
DefaultAssay(alldata.int) <- "rpca"

#Run Dimensionality reduction on integrated space
alldata.int <- ScaleData(alldata.int, verbose = FALSE)
alldata.int <- RunPCA(alldata.int, features = hvgs_all, reduction.name = "pca_rpca", do.print = TRUE, pcs.print = 1:5, genes.print = 15, verbose = FALSE)
alldata.int <- RunUMAP(alldata.int, reduction = "pca_rpca", reduction.name = "umap_rpca", dims = 1:12, verbose = FALSE)
Avis : The default method for RunUMAP has changed from calling Python UMAP via reticulate to the R-native UWOT using the cosine metric
To use Python UMAP via reticulate, set umap.method to 'umap-learn' and metric to 'correlation'
This message will be shown once per session
alldata.int <- RunTSNE(alldata.int, reduction = "pca_rpca", reduction.name = "tsne_rpca", dims = 1:12, verbose = FALSE)
alldata.int <- FindNeighbors(alldata.int, reduction = "pca_rpca", dims = 1:12, verbose = FALSE)
alldata.int <- FindClusters(alldata.int, resolution = 1.2, verbose = FALSE)



wrap_plots(

    DimPlot(alldata.int, reduction = "pca_rpca", group.by = "orig.ident")+NoAxes()+ggtitle("PCA integrated"),
    DimPlot(alldata.int, reduction = "tsne_rpca", group.by = "orig.ident")+NoAxes()+ggtitle("tSNE integrated"),
    DimPlot(alldata.int, reduction = "umap_rpca", group.by = "orig.ident")+NoAxes()+ggtitle("UMAP integrated"),

    DimPlot(alldata.int, reduction = "pca_rpca", group.by = "rpca_snn_res.1.2")+NoAxes()+ggtitle("PCA integrated"),
    DimPlot(alldata.int, reduction = "tsne_rpca", group.by = "rpca_snn_res.1.2")+NoAxes()+ggtitle("tSNE integrated"),
    DimPlot(alldata.int, reduction = "umap_rpca", group.by = "rpca_snn_res.1.2")+NoAxes()+ggtitle("UMAP integrated"),
    ncol = 3) + plot_layout(guides = "collect")

NA
NA
NA

clean memory

# remove all objects that will not be used
rm(alldata, alldata.anchors)

gc()
             used    (Mb) gc trigger    (Mb)   max used    (Mb)
Ncells   13372812   714.2   22952785  1225.9   22952785  1225.9
Vcells 1958246802 14940.3 5018916606 38291.3 5018904699 38291.3

5. CCA-integration

clean memory

# remove all objects that will not be used
rm(alldata.anchors)

gc()

FeaturePlot



myfeatures <- c("CD3E", "CD4", "CD8A", "NKG7", "GNLY", "MS4A1", "CD14", "LYZ", "MS4A7", "FCGR3A", "CST3", "FCER1A")
FeaturePlot(alldata.int, reduction = "umap_CCA", dims = 1:2, features = myfeatures, ncol = 4, order = T) + NoLegend() + NoAxes() + NoGrid()

NA
NA

6. Harmony-integration

FeaturePlot



myfeatures <- c("CD3E", "CD4", "CD8A", "NKG7", "GNLY", "MS4A1", "CD14", "LYZ", "MS4A7", "FCGR3A", "CST3", "FCER1A")
FeaturePlot(alldata.int, reduction = "umap_harmony", dims = 1:2, features = myfeatures, ncol = 4, order = T) + NoLegend() + NoAxes() + NoGrid()

NA
NA

7. Save the Seurat object as an Robj file


#save(alldata.int, file = "Integration-by-different-Methods-1.Robj")
LS0tCnRpdGxlOiAiSW50ZWdyYXRpb24gYnkgRGlmZmVyZW50IE1ldGhvZHMtcnBjYS1DQ0EtSGFybW9ueSIKYXV0aG9yOiBOYXNpciBNYWhtb29kIEFiYmFzaQpkYXRlOiAiMjAyNC0wNC0yNiIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IAogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRvY19jb2xsYXBzZWQ6IHRydWUKICAgIHRoZW1lOiBkYXJrbHkKLS0tCiMgMS4gbG9hZCBsaWJyYXJpZXMKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KFNldXJhdE9iamVjdCkKbGlicmFyeShTZXVyYXREYXRhKQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShoYXJtb255KQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocmV0aWN1bGF0ZSkKbGlicmFyeShBemltdXRoKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KFJ0c25lKQpsaWJyYXJ5KGhhcm1vbnkpCgpgYGAKCgoKCiMgMi4gTG9hZCBTZXVyYXQgT2JqZWN0IApgYGB7ciBsb2FkX3NldXJhdH0KCiNMb2FkIFNldXJhdCBPYmplY3QgbWVyZ2VkIGZyb20gY2VsbCBsaW5lcyBhbmQgYSBjb250cm9sKFBCTUMpIGFmdGVyIGZpbHRyYXRpb24KbG9hZCgiU1NfbWVyZ2VkX21hcmllX29iai0yLVZhcmlhdGlvbi5Sb2JqIikKCkFsbF9zYW1wbGVzX01lcmdlZAoKYGBgCiMgMy4gRGF0YSBQUkVQQVJBVElPTgpgYGB7ciBkYXRhLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KCmFsbGRhdGEgPC0gQWxsX3NhbXBsZXNfTWVyZ2VkCgphbGxkYXRhLmxpc3QgPC0gU3BsaXRPYmplY3QoYWxsZGF0YSwgc3BsaXQuYnkgPSAib3JpZy5pZGVudCIpCgpmb3IgKGkgaW4gMTpsZW5ndGgoYWxsZGF0YS5saXN0KSkgewogICAgYWxsZGF0YS5saXN0W1tpXV0gPC0gTm9ybWFsaXplRGF0YShhbGxkYXRhLmxpc3RbW2ldXSwgdmVyYm9zZSA9IEZBTFNFKQogICAgYWxsZGF0YS5saXN0W1tpXV0gPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoYWxsZGF0YS5saXN0W1tpXV0sIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gMjAwMCx2ZXJib3NlID0gRkFMU0UpCn0KCiMgZ2V0IHRoZSB2YXJpYWJsZSBnZW5lcyBmcm9tIGFsbCB0aGUgZGF0YXNldHMuCmh2Z3NfcGVyX2RhdGFzZXQgPC0gbGFwcGx5KGFsbGRhdGEubGlzdCwgZnVuY3Rpb24oeCkgeyB4QGFzc2F5cyRSTkFAdmFyLmZlYXR1cmVzIH0pCgojIGFsc28gYWRkIGluIHRoZSB2YXJpYWJsZSBnZW5lcyB0aGF0IHdhcyBzZWxlY3RlZCBvbiB0aGUgd2hvbGUgZGF0YXNldApodmdzX3Blcl9kYXRhc2V0JGFsbCA9IFZhcmlhYmxlRmVhdHVyZXMoYWxsZGF0YSkKCnRlbXAgPC0gdW5pcXVlKHVubGlzdChodmdzX3Blcl9kYXRhc2V0KSkKb3ZlcmxhcCA8LSBzYXBwbHkoIGh2Z3NfcGVyX2RhdGFzZXQgLCBmdW5jdGlvbih4KSB7IHRlbXAgJWluJSB4IH0gKQpwaGVhdG1hcDo6cGhlYXRtYXAodChvdmVybGFwKjEpLGNsdXN0ZXJfcm93cyA9IEYgLAogICAgICAgICAgICAgICAgICAgY29sb3IgPSBjKCJncmV5OTAiLCJncmV5MjAiKSkKCmh2Z3NfYWxsID0gU2VsZWN0SW50ZWdyYXRpb25GZWF0dXJlcyhhbGxkYXRhLmxpc3QpCmh2Z3NfcGVyX2RhdGFzZXQkYWxsX3JhbmtzID0gaHZnc19hbGwKCnRlbXAgPC0gdW5pcXVlKHVubGlzdChodmdzX3Blcl9kYXRhc2V0KSkKb3ZlcmxhcCA8LSBzYXBwbHkoIGh2Z3NfcGVyX2RhdGFzZXQgLCBmdW5jdGlvbih4KSB7IHRlbXAgJWluJSB4IH0gKQpwaGVhdG1hcDo6cGhlYXRtYXAodChvdmVybGFwKjEpLGNsdXN0ZXJfcm93cyA9IEYgLAogICAgICAgICAgICAgICAgICAgY29sb3IgPSBjKCJncmV5OTAiLCJncmV5MjAiKSkKCgphbGxkYXRhLmxpc3QgPC0gbGFwcGx5KFggPSBhbGxkYXRhLmxpc3QsIEZVTiA9IGZ1bmN0aW9uKHgpIHsKICAgIHggPC0gU2NhbGVEYXRhKHgsIGZlYXR1cmVzID0gaHZnc19hbGwsIHZlcmJvc2UgPSBGQUxTRSkKICAgIHggPC0gUnVuUENBKHgsIGZlYXR1cmVzID0gaHZnc19hbGwsIHZlcmJvc2UgPSBGQUxTRSkKfSkKYGBgCgoKIyA0LiBycGNhLWludGVncmF0aW9uCmBgYHtyIGludGVncmF0aW9uLXJwY2EsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQoKYWxsZGF0YS5hbmNob3JzIDwtIEZpbmRJbnRlZ3JhdGlvbkFuY2hvcnMob2JqZWN0Lmxpc3QgPSBhbGxkYXRhLmxpc3QsIGRpbXMgPSAxOjEyLCByZWR1Y3Rpb24gPSAicnBjYSIsIGFuY2hvci5mZWF0dXJlcyA9IGh2Z3NfYWxsKQoKYWxsZGF0YS5pbnQgPC0gSW50ZWdyYXRlRGF0YShhbmNob3JzZXQgPSBhbGxkYXRhLmFuY2hvcnMsIGRpbXMgPSAxOjEyLCBuZXcuYXNzYXkubmFtZSA9ICJycGNhIikKCm5hbWVzKGFsbGRhdGEuaW50QGFzc2F5cykKCmFsbGRhdGEuaW50QGFjdGl2ZS5hc3NheQoKRGVmYXVsdEFzc2F5KGFsbGRhdGEuaW50KSA8LSAicnBjYSIKCiNSdW4gRGltZW5zaW9uYWxpdHkgcmVkdWN0aW9uIG9uIGludGVncmF0ZWQgc3BhY2UKYWxsZGF0YS5pbnQgPC0gU2NhbGVEYXRhKGFsbGRhdGEuaW50LCB2ZXJib3NlID0gRkFMU0UpCmFsbGRhdGEuaW50IDwtIFJ1blBDQShhbGxkYXRhLmludCwgZmVhdHVyZXMgPSBodmdzX2FsbCwgcmVkdWN0aW9uLm5hbWUgPSAicGNhX3JwY2EiLCBkby5wcmludCA9IFRSVUUsIHBjcy5wcmludCA9IDE6NSwgZ2VuZXMucHJpbnQgPSAxNSwgdmVyYm9zZSA9IEZBTFNFKQphbGxkYXRhLmludCA8LSBSdW5VTUFQKGFsbGRhdGEuaW50LCByZWR1Y3Rpb24gPSAicGNhX3JwY2EiLCByZWR1Y3Rpb24ubmFtZSA9ICJ1bWFwX3JwY2EiLCBkaW1zID0gMToxMiwgdmVyYm9zZSA9IEZBTFNFKQphbGxkYXRhLmludCA8LSBSdW5UU05FKGFsbGRhdGEuaW50LCByZWR1Y3Rpb24gPSAicGNhX3JwY2EiLCByZWR1Y3Rpb24ubmFtZSA9ICJ0c25lX3JwY2EiLCBkaW1zID0gMToxMiwgdmVyYm9zZSA9IEZBTFNFKQphbGxkYXRhLmludCA8LSBGaW5kTmVpZ2hib3JzKGFsbGRhdGEuaW50LCByZWR1Y3Rpb24gPSAicGNhX3JwY2EiLCBkaW1zID0gMToxMiwgdmVyYm9zZSA9IEZBTFNFKQphbGxkYXRhLmludCA8LSBGaW5kQ2x1c3RlcnMoYWxsZGF0YS5pbnQsIHJlc29sdXRpb24gPSAxLjIsIHZlcmJvc2UgPSBGQUxTRSkKCgoKd3JhcF9wbG90cygKCiAgICBEaW1QbG90KGFsbGRhdGEuaW50LCByZWR1Y3Rpb24gPSAicGNhX3JwY2EiLCBncm91cC5ieSA9ICJvcmlnLmlkZW50IikrTm9BeGVzKCkrZ2d0aXRsZSgiUENBIGludGVncmF0ZWQiKSwKICAgIERpbVBsb3QoYWxsZGF0YS5pbnQsIHJlZHVjdGlvbiA9ICJ0c25lX3JwY2EiLCBncm91cC5ieSA9ICJvcmlnLmlkZW50IikrTm9BeGVzKCkrZ2d0aXRsZSgidFNORSBpbnRlZ3JhdGVkIiksCiAgICBEaW1QbG90KGFsbGRhdGEuaW50LCByZWR1Y3Rpb24gPSAidW1hcF9ycGNhIiwgZ3JvdXAuYnkgPSAib3JpZy5pZGVudCIpK05vQXhlcygpK2dndGl0bGUoIlVNQVAgaW50ZWdyYXRlZCIpLAoKICAgIERpbVBsb3QoYWxsZGF0YS5pbnQsIHJlZHVjdGlvbiA9ICJwY2FfcnBjYSIsIGdyb3VwLmJ5ID0gInJwY2Ffc25uX3Jlcy4xLjIiKStOb0F4ZXMoKStnZ3RpdGxlKCJQQ0EgaW50ZWdyYXRlZCIpLAogICAgRGltUGxvdChhbGxkYXRhLmludCwgcmVkdWN0aW9uID0gInRzbmVfcnBjYSIsIGdyb3VwLmJ5ID0gInJwY2Ffc25uX3Jlcy4xLjIiKStOb0F4ZXMoKStnZ3RpdGxlKCJ0U05FIGludGVncmF0ZWQiKSwKICAgIERpbVBsb3QoYWxsZGF0YS5pbnQsIHJlZHVjdGlvbiA9ICJ1bWFwX3JwY2EiLCBncm91cC5ieSA9ICJycGNhX3Nubl9yZXMuMS4yIikrTm9BeGVzKCkrZ2d0aXRsZSgiVU1BUCBpbnRlZ3JhdGVkIiksCiAgICBuY29sID0gMykgKyBwbG90X2xheW91dChndWlkZXMgPSAiY29sbGVjdCIpCgoKCmBgYAoKIyBjbGVhbiBtZW1vcnkKYGBge3IgY2xlYW5NZW1vcnkxfQojIHJlbW92ZSBhbGwgb2JqZWN0cyB0aGF0IHdpbGwgbm90IGJlIHVzZWQKcm0oYWxsZGF0YSwgYWxsZGF0YS5hbmNob3JzKQoKZ2MoKQpgYGAKCiMgNS4gQ0NBLWludGVncmF0aW9uCmBgYHtyIGludGVncmF0aW9uLUNDQSwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CgphbGxkYXRhLmFuY2hvcnMgPC0gRmluZEludGVncmF0aW9uQW5jaG9ycyhvYmplY3QubGlzdCA9IGFsbGRhdGEubGlzdCwgZGltcyA9IDE6MTIsIHJlZHVjdGlvbiA9ICJjY2EiLCBhbmNob3IuZmVhdHVyZXMgPSBodmdzX2FsbCkKCmFsbGRhdGEuaW50IDwtIEludGVncmF0ZURhdGEoYW5jaG9yc2V0ID0gYWxsZGF0YS5hbmNob3JzLCBkaW1zID0gMToxMiwgbmV3LmFzc2F5Lm5hbWUgPSAiQ0NBIikKCm5hbWVzKGFsbGRhdGEuaW50QGFzc2F5cykKCmFsbGRhdGEuaW50QGFjdGl2ZS5hc3NheQoKRGVmYXVsdEFzc2F5KGFsbGRhdGEuaW50KSA8LSAiQ0NBIgoKI1J1biBEaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24gb24gaW50ZWdyYXRlZCBzcGFjZQphbGxkYXRhLmludCA8LSBTY2FsZURhdGEoYWxsZGF0YS5pbnQsIHZlcmJvc2UgPSBUUlVFKQphbGxkYXRhLmludCA8LSBSdW5QQ0EoYWxsZGF0YS5pbnQsIGZlYXR1cmVzID0gaHZnc19hbGwsIHJlZHVjdGlvbi5uYW1lID0gInBjYV9DQ0EiLCBkby5wcmludCA9IFRSVUUsIHBjcy5wcmludCA9IDE6NSwgZ2VuZXMucHJpbnQgPSAxNSwgdmVyYm9zZSA9IEZBTFNFKQphbGxkYXRhLmludCA8LSBSdW5VTUFQKGFsbGRhdGEuaW50LCByZWR1Y3Rpb24gPSAicGNhX0NDQSIsIHJlZHVjdGlvbi5uYW1lID0gInVtYXBfQ0NBIiwgZGltcyA9IDE6MTIsIHZlcmJvc2UgPSBGQUxTRSkKYWxsZGF0YS5pbnQgPC0gUnVuVFNORShhbGxkYXRhLmludCwgcmVkdWN0aW9uID0gInBjYV9DQ0EiLHJlZHVjdGlvbi5uYW1lID0gInRzbmVfQ0NBIixkaW1zID0gMToxMiwgdmVyYm9zZSA9IEZBTFNFKQphbGxkYXRhLmludCA8LSBGaW5kTmVpZ2hib3JzKGFsbGRhdGEuaW50LCByZWR1Y3Rpb24gPSAicGNhX0NDQSIsIGRpbXMgPSAxOjEyLCB2ZXJib3NlID0gRkFMU0UpCmFsbGRhdGEuaW50IDwtIEZpbmRDbHVzdGVycyhhbGxkYXRhLmludCwgcmVzb2x1dGlvbiA9IDEuMiwgdmVyYm9zZSA9IEZBTFNFKQoKCgp3cmFwX3Bsb3RzKAoKICAgIERpbVBsb3QoYWxsZGF0YS5pbnQsIHJlZHVjdGlvbiA9ICJwY2FfQ0NBIiwgZ3JvdXAuYnkgPSAib3JpZy5pZGVudCIpK05vQXhlcygpK2dndGl0bGUoIlBDQSBpbnRlZ3JhdGVkIiksCiAgICBEaW1QbG90KGFsbGRhdGEuaW50LCByZWR1Y3Rpb24gPSAidHNuZV9DQ0EiLCBncm91cC5ieSA9ICJvcmlnLmlkZW50IikrTm9BeGVzKCkrZ2d0aXRsZSgidFNORSBpbnRlZ3JhdGVkIiksCiAgICBEaW1QbG90KGFsbGRhdGEuaW50LCByZWR1Y3Rpb24gPSAidW1hcF9DQ0EiLCBncm91cC5ieSA9ICJvcmlnLmlkZW50IikrTm9BeGVzKCkrZ2d0aXRsZSgiVU1BUCBpbnRlZ3JhdGVkIiksCgogICAgRGltUGxvdChhbGxkYXRhLmludCwgcmVkdWN0aW9uID0gInBjYV9DQ0EiLCBncm91cC5ieSA9ICJDQ0Ffc25uX3Jlcy4xLjIiKStOb0F4ZXMoKStnZ3RpdGxlKCJQQ0EgaW50ZWdyYXRlZCIpLAogICAgRGltUGxvdChhbGxkYXRhLmludCwgcmVkdWN0aW9uID0gInRzbmVfQ0NBIiwgZ3JvdXAuYnkgPSAiQ0NBX3Nubl9yZXMuMS4yIikrTm9BeGVzKCkrZ2d0aXRsZSgidFNORSBpbnRlZ3JhdGVkIiksCiAgICBEaW1QbG90KGFsbGRhdGEuaW50LCByZWR1Y3Rpb24gPSAidW1hcF9DQ0EiLCBncm91cC5ieSA9ICJDQ0Ffc25uX3Jlcy4xLjIiKStOb0F4ZXMoKStnZ3RpdGxlKCJVTUFQIGludGVncmF0ZWQiKSwKICAgIG5jb2wgPSAzKSArIHBsb3RfbGF5b3V0KGd1aWRlcyA9ICJjb2xsZWN0IikKYGBgCgoKIyBjbGVhbiBtZW1vcnkKYGBge3IgY2xlYW5NZW1vcnkyfQojIHJlbW92ZSBhbGwgb2JqZWN0cyB0aGF0IHdpbGwgbm90IGJlIHVzZWQKcm0oYWxsZGF0YS5hbmNob3JzKQoKZ2MoKQoKCgpgYGAKCgoKIyBGZWF0dXJlUGxvdApgYGB7ciBmZWF0dXJlcGxvdCwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CgoKbXlmZWF0dXJlcyA8LSBjKCJDRDNFIiwgIkNENCIsICJDRDhBIiwgIk5LRzciLCAiR05MWSIsICJNUzRBMSIsICJDRDE0IiwgIkxZWiIsICJNUzRBNyIsICJGQ0dSM0EiLCAiQ1NUMyIsICJGQ0VSMUEiKQpGZWF0dXJlUGxvdChhbGxkYXRhLmludCwgcmVkdWN0aW9uID0gInVtYXBfQ0NBIiwgZGltcyA9IDE6MiwgZmVhdHVyZXMgPSBteWZlYXR1cmVzLCBuY29sID0gNCwgb3JkZXIgPSBUKSArIE5vTGVnZW5kKCkgKyBOb0F4ZXMoKSArIE5vR3JpZCgpCgoKYGBgCiMgNi4gSGFybW9ueS1pbnRlZ3JhdGlvbgpgYGB7ciBpbnRlZ3JhdGlvbi1oYXJtb255LCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KCmFsbGRhdGEuaW50QGFjdGl2ZS5hc3NheSA9ICJSTkEiClZhcmlhYmxlRmVhdHVyZXMoYWxsZGF0YS5pbnQpID0gaHZnc19hbGwKYWxsZGF0YS5pbnQgPSBTY2FsZURhdGEoYWxsZGF0YS5pbnQsIHZhcnMudG8ucmVncmVzcyA9IGMoInBlcmNlbnQubWl0byIsICJuRmVhdHVyZV9STkEiKSkKYWxsZGF0YS5pbnQgPSBSdW5QQ0EoYWxsZGF0YS5pbnQsIHJlZHVjdGlvbi5uYW1lID0gInBjYV9oYXJtb255IikKCgoKYWxsZGF0YS5pbnQgPC0gUnVuSGFybW9ueSgKICBhbGxkYXRhLmludCwKICBncm91cC5ieS52YXJzID0gIm9yaWcuaWRlbnQiLAogIHJlZHVjdGlvbi51c2UgPSAicGNhX2hhcm1vbnkiLAogIGRpbXMudXNlID0gMToxMiwKICBhc3NheS51c2UgPSAiUk5BIikKCgphbGxkYXRhLmludCA8LSBSdW5VTUFQKGFsbGRhdGEuaW50LCBkaW1zID0gMToxMiwgcmVkdWN0aW9uID0gImhhcm1vbnkiLCByZWR1Y3Rpb24ubmFtZSA9ICJ1bWFwX2hhcm1vbnkiKQphbGxkYXRhLmludCA8LSBSdW5UU05FKGFsbGRhdGEuaW50LCBkaW1zID0gMToxMiwgcmVkdWN0aW9uID0gImhhcm1vbnkiLCByZWR1Y3Rpb24ubmFtZSA9ICJ0c25lX2hhcm1vbnkiKQphbGxkYXRhLmludCA8LSBGaW5kTmVpZ2hib3JzKGFsbGRhdGEuaW50LCByZWR1Y3Rpb24gPSAicGNhX2hhcm1vbnkiLCBkaW1zID0gMToxMiwgdmVyYm9zZSA9IEZBTFNFKQphbGxkYXRhLmludCA8LSBGaW5kQ2x1c3RlcnMoYWxsZGF0YS5pbnQsIHJlc29sdXRpb24gPSAxLjIsIHZlcmJvc2UgPSBGQUxTRSkKCgogCiAKIHdyYXBfcGxvdHMoCgogICAgRGltUGxvdChhbGxkYXRhLmludCwgcmVkdWN0aW9uID0gInBjYV9oYXJtb255IiwgZ3JvdXAuYnkgPSAib3JpZy5pZGVudCIpK05vQXhlcygpK2dndGl0bGUoIlBDQSBpbnRlZ3JhdGVkIiksCiAgICBEaW1QbG90KGFsbGRhdGEuaW50LCByZWR1Y3Rpb24gPSAidHNuZV9oYXJtb255IiwgZ3JvdXAuYnkgPSAib3JpZy5pZGVudCIpK05vQXhlcygpK2dndGl0bGUoInRTTkUgaW50ZWdyYXRlZCIpLAogICAgRGltUGxvdChhbGxkYXRhLmludCwgcmVkdWN0aW9uID0gInVtYXBfaGFybW9ueSIsIGdyb3VwLmJ5ID0gIm9yaWcuaWRlbnQiKStOb0F4ZXMoKStnZ3RpdGxlKCJVTUFQIGludGVncmF0ZWQiKSwKCiAgICBEaW1QbG90KGFsbGRhdGEuaW50LCByZWR1Y3Rpb24gPSAicGNhX2hhcm1vbnkiLCBncm91cC5ieSA9ICJSTkFfc25uX3Jlcy4xLjIiKStOb0F4ZXMoKStnZ3RpdGxlKCJQQ0EgaW50ZWdyYXRlZCIpLAogICAgRGltUGxvdChhbGxkYXRhLmludCwgcmVkdWN0aW9uID0gInRzbmVfaGFybW9ueSIsIGdyb3VwLmJ5ID0gIlJOQV9zbm5fcmVzLjEuMiIpK05vQXhlcygpK2dndGl0bGUoInRTTkUgaW50ZWdyYXRlZCIpLAogICAgRGltUGxvdChhbGxkYXRhLmludCwgcmVkdWN0aW9uID0gInVtYXBfaGFybW9ueSIsIGdyb3VwLmJ5ID0gIlJOQV9zbm5fcmVzLjEuMiIpK05vQXhlcygpK2dndGl0bGUoIlVNQVAgaW50ZWdyYXRlZCIpLAogICAgbmNvbCA9IDMpICsgcGxvdF9sYXlvdXQoZ3VpZGVzID0gImNvbGxlY3QiKQogICAgCmBgYAoKIyBGZWF0dXJlUGxvdApgYGB7ciBmZWF0dXJlcGxvdC1oYXJtb255LCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KCgpteWZlYXR1cmVzIDwtIGMoIkNEM0UiLCAiQ0Q0IiwgIkNEOEEiLCAiTktHNyIsICJHTkxZIiwgIk1TNEExIiwgIkNEMTQiLCAiTFlaIiwgIk1TNEE3IiwgIkZDR1IzQSIsICJDU1QzIiwgIkZDRVIxQSIpCkZlYXR1cmVQbG90KGFsbGRhdGEuaW50LCByZWR1Y3Rpb24gPSAidW1hcF9oYXJtb255IiwgZGltcyA9IDE6MiwgZmVhdHVyZXMgPSBteWZlYXR1cmVzLCBuY29sID0gNCwgb3JkZXIgPSBUKSArIE5vTGVnZW5kKCkgKyBOb0F4ZXMoKSArIE5vR3JpZCgpCgoKYGBgCgoKIyA3LiBTYXZlIHRoZSBTZXVyYXQgb2JqZWN0IGFzIGFuIFJvYmogZmlsZQpgYGB7ciBzYXZlUk9CSn0KCiNzYXZlKGFsbGRhdGEuaW50LCBmaWxlID0gIkludGVncmF0aW9uLWJ5LWRpZmZlcmVudC1NZXRob2RzLTEuUm9iaiIpCgoKYGBgCgoKCgo=