Combining Multiple Single cell RNA-seq Datasets: Part II

In this post, I will try to combine Nowakowski et al., 2017 , BrainSpan and Zhong et al., 2017 datasets.

All of these datasets are publicly available. For more information, please visit the Resources page

First let's combine the Nowakowski and Brainsan datasets.

df0.all <- MergeSeurat(df0.BS, df0.nowa,
                       min.cells = 10,
                       do.normalize = T,
                       scale.factor = 100000)

Normalize both datasets:

Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
p1 <- plotGeneDistr("PAX6",object1 = df0.all)
p2 <- plotGeneDistr("BCL11B",object1 = df0.all)
p3 <- plotGeneDistr("GAD1",object1 = df0.all)
p4 <- plotGeneDistr("OLIG1",object1 = df0.all)
plot_grid(p1, p2, p3, p4, nrow = 2)

Find highly variable genes to conduct PCA analysis:

Calculating gene means
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating gene variance to mean ratios
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|

Run PCA:

df0.all <- RunPCA(object = df0.all,
                  pc.genes=df0.all@var.genes,
                  pcs.compute = 30,
                  pcs.print = 1:10,
                  do.print = F,
                  genes.print = 10)

Pick significant PCs for tSNE and clustering analysis based on elbow plot:

I chose 20 PCs for down stream analysis.

Run tSNE analysis:

df0.all <- RunTSNE(df0.all,
               dims.use = 1:20,
               perplexity = 30,
               seed.use = 1)
df0.all <- FindClusters(object = df0.all,
                    reduction.type = "pca",
                    dims.use = 1:20,
                    resolution = 0.8,
                    print.output = 0,
                    save.SNN = F,
                    force.recalc = T) 
p1 <- TSNEPlot(object = df0.all,
               pt.size = 3,
               do.label = T,
               label.size = 10,
               do.return = T)
p2 <- TSNEPlot(object = df0.all,
               group.by = "orig.ident",
               do.return = T,
               pt.size = 3)
plot_grid(p1, p2, ncol = 2)

source("~/zhen/scripts/R/functions/markers.R")
markers <- unlist(sapply(markers,function(x){grep(x, rownames(df0.all@data), value = T)}))
## Plot marker genes
temp <- df0.all@data[markers,]
ord <- order(df0.all@meta.data$res.0.8)
ColSideColors <- c(gg_color_hue(length(unique(df0.all@meta.data$res.0.8)))[as.numeric(as.factor(df0.all@meta.data$res.0.8))],
rainbow(2)[as.numeric(as.factor(df0.all@meta.data$orig.ident))])
ColSideColors <- matrix(data = ColSideColors, nrow = ncol(temp));
ColSideColors <- ColSideColors[ord, ];
colsep <- lapply(unique(df0.all@meta.data$res.0.8[ord]),
function(xx){length(which(df0.all@meta.data$res.0.8 == xx))});
colsep <- cumsum(unlist(colsep));
pairs.breaks <- seq(-2, 2, length.out=101);
heatmap.3(temp[, ord],
          breaks = pairs.breaks,
          #symbreaks = T,
          keysize = 0.8,
          main="Marker gene expression",
          col = gplots::bluered(100),
          symkey = F,
          cexRow=1, cexCol = 0.6,
          Rowv = F,
          Colv = F,#as.dendrogram(hca),
          ColSideColors = as.matrix(ColSideColors),
          ColSideColorsSize = 1,
          #RowSideColors = RowSideColors,
          dendrogram = "none",
          scale = "row",
          colsep = colsep,
          sepcolor = "black",
          labRow = rownames(temp),
          labCol = "",
          na.rm = F)
Using scale="row" or scale="column" when breaks arespecified can produce unpredictable results.Please consider using only one or the other.

Add another dataset: Zhong et al. 2017

Merge Zhong et al dataset to the other two:

df0.all <- MergeSeurat(df0.all, df0.zhong,
                       min.cells = 10,
                       do.normalize = T,
                       scale.factor = 100000)
df0.all@meta.data$Time_point2[df0.all@meta.data$Time_point %in%
                                    c("5 pcw", "6 pcw", "8 pcw", "GW08", "GW09","GW10")] <- "W1"
df0.all@meta.data$Time_point2[df0.all@meta.data$Time_point %in%
                                    c("11", "13", "13.3","14","14.2","14.5","14.7","GW12","GW13", "GW16")] <- "W2"
df0.all@meta.data$Time_point2[df0.all@meta.data$Time_point %in%
                                    c("15", "16 pcw", "16.3","17.3","17.5","18.5","GW19")] <- "W3"
df0.all@meta.data$Time_point2[df0.all@meta.data$Time_point %in%
                                    c("19", "19 pcw", "20 pcw","20","21.5","22","GW23","GW26")] <- "W4"
df0.all@meta.data$Time_point2[df0.all@meta.data$Time_point %in% c("32")] <- "W5"

Regress out nUMI and different studies.

Look at expression level distribution in normalized data:

Take a look at expression level distribution in scaled data:

Find highly variable genes to conduct PCA analysis:

Calculating gene means
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating gene variance to mean ratios
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|

Run PCA:

df0.all <- RunPCA(object = df0.all,
                  pc.genes=df0.all@var.genes,
                  pcs.compute = 30,
                  pcs.print = 1:10,
                  do.print = F,
                  genes.print = 10)
Error in irlba(A = t(x = data.use), nv = pcs.compute, ...) :
  max(nu, nv) must be positive

Pick significant PCs for tSNE and clustering analysis based on elbow plot:

I chose 20 PCs for down stream analysis.

Run tSNE analysis:

df0.all <- RunTSNE(df0.all,
               dims.use = 1:20,
               perplexity = 30,
               seed.use = 1)
df0.all <- FindClusters(object = df0.all,
                    reduction.type = "pca",
                    dims.use = 1:20,
                    resolution = 0.8,
                    print.output = 0,
                    save.SNN = F,
                    force.recalc = T) 

source("~/zhen/scripts/R/functions/markers.R")
markers <- unlist(sapply(markers,function(x){grep(x, rownames(df0.all@data), value = T)}))
## Plot marker genes
temp <- df0.all@data[markers,]
ord <- order(df0.all@meta.data$res.0.8)
ColSideColors <- c(gg_color_hue(length(unique(df0.all@meta.data$res.0.8)))[as.numeric(as.factor(df0.all@meta.data$res.0.8))],
rainbow(3)[as.numeric(as.factor(df0.all@meta.data$orig.ident))])
ColSideColors <- matrix(data = ColSideColors, nrow = ncol(temp));
ColSideColors <- ColSideColors[ord, ];
colsep <- lapply(unique(df0.all@meta.data$res.0.8[ord]),
function(xx){length(which(df0.all@meta.data$res.0.8 == xx))});
colsep <- cumsum(unlist(colsep));
pairs.breaks <- seq(-2, 2, length.out=101);
heatmap.3(temp[, ord],
          breaks = pairs.breaks,
          key = F,
          #symbreaks = T,
          keysize = 0.8,
          main="Marker gene expression",
          col = gplots::bluered(100),
          symkey = F,
          cexRow=1, cexCol = 0.6,
          Rowv = F,
          Colv = F,#as.dendrogram(hca),
          ColSideColors = as.matrix(ColSideColors),
          ColSideColorsSize = 1,
          #RowSideColors = RowSideColors,
          dendrogram = "none",
          scale = "row",
          colsep = colsep,
          sepcolor = "black",
          labRow = rownames(temp),
          labCol = "",
          na.rm = F)
Using scale="row" or scale="column" when breaks arespecified can produce unpredictable results.Please consider using only one or the other.

LS0tCnRpdGxlOiAiMjAxOC0xMC0yNCIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQo+IENvbWJpbmUgTm93YWtvd3NraSBhbmQgQnJhaW5TcGFuIGRhdGFzZXQgZm9yIGdyZWF0ZXIgY2VsbCBudW1iZXIgdG8gZG8gY2xhc3NpZmljYXRpb24KCmBgYHtyIGluY2x1ZGU9Rn0Kc2V0d2QoIn4vemhlbi9kYXRhL2hPcmcvIikKbG9hZCgifi96aGVuL2RhdGEvaE9yZy9ub3dhX0JTLlJEYXRhIikKbGlicmFyeShTZXVyYXQpCnNvdXJjZSgifi96aGVuL3NjcmlwdHMvUi9mdW5jdGlvbnMvcGxvdEdlbmVEaXN0ci5SIikKIyBkZjAubWljMTcwNy5uIDwtIHJlYWRSRFMoIn4vemhlbi9kYXRhL2hPcmcvZGYwLm1pYzE3MDcubi5yZHMiKQojIGRmMC5taWMxNzA3LmQgPC0gcmVhZFJEUygifi96aGVuL2RhdGEvaE9yZy9kZjAubWljMTcwNy5kLnJkcyIpCmBgYAoKTm9ybWFsaXplIGJvdGggZGF0YXNldHM6CgpgYGB7cn0KZGYwLmFsbCA8LSBNZXJnZVNldXJhdChkZjAuQlMsIGRmMC5ub3dhLAogICAgICAgICAgICAgICAgICAgICAgIG1pbi5jZWxscyA9IDEwLAogICAgICAgICAgICAgICAgICAgICAgIGRvLm5vcm1hbGl6ZSA9IFQsCiAgICAgICAgICAgICAgICAgICAgICAgc2NhbGUuZmFjdG9yID0gMTAwMDAwKQoKZGYwLmFsbCA8LSBTY2FsZURhdGEoZGYwLmFsbCwgdmFycy50by5yZWdyZXNzID0gIm5VTUkiKQpgYGAKCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGZpZy53aWR0aD0xNiwgZmlnLmhlaWdodD0xNn0KcDEgPC0gcGxvdEdlbmVEaXN0cigiUEFYNiIsb2JqZWN0MSA9IGRmMC5hbGwpCnAyIDwtIHBsb3RHZW5lRGlzdHIoIkJDTDExQiIsb2JqZWN0MSA9IGRmMC5hbGwpCnAzIDwtIHBsb3RHZW5lRGlzdHIoIkdBRDEiLG9iamVjdDEgPSBkZjAuYWxsKQpwNCA8LSBwbG90R2VuZURpc3RyKCJPTElHMSIsb2JqZWN0MSA9IGRmMC5hbGwpCnBsb3RfZ3JpZChwMSwgcDIsIHAzLCBwNCwgbnJvdyA9IDIpCmBgYApGaW5kIGhpZ2hseSB2YXJpYWJsZSBnZW5lcyB0byBjb25kdWN0IFBDQSBhbmFseXNpczoKYGBge3IgZWNobz1GLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD03fQpkZjAuYWxsIDwtIEZpbmRWYXJpYWJsZUdlbmVzKGRmMC5hbGwsIHgubG93LmN1dG9mZiA9IDAuNSkKYGBgCgpSdW4gUENBOgpgYGB7cn0KZGYwLmFsbCA8LSBSdW5QQ0Eob2JqZWN0ID0gZGYwLmFsbCwKICAgICAgICAgICAgICAgICAgcGMuZ2VuZXM9ZGYwLmFsbEB2YXIuZ2VuZXMsIAogICAgICAgICAgICAgICAgICBwY3MuY29tcHV0ZSA9IDMwLCAKICAgICAgICAgICAgICAgICAgcGNzLnByaW50ID0gMToxMCwKICAgICAgICAgICAgICAgICAgZG8ucHJpbnQgPSBGLCAKICAgICAgICAgICAgICAgICAgZ2VuZXMucHJpbnQgPSAxMCkKYGBgCgpgYGB7ciBlY2hvPUYsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTd9CnAxIDwtIFBDQVBsb3QoZGYwLmFsbCwgZ3JvdXAuYnkgPSAib3JpZy5pZGVudCIsIGRvLnJldHVybiA9IFQpCnAxIDwtIHAxICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gYygwLjEsIDAuOSkpCnAxCmBgYAoKUGljayBzaWduaWZpY2FudCBQQ3MgZm9yIHRTTkUgYW5kIGNsdXN0ZXJpbmcgYW5hbHlzaXMgYmFzZWQgb24gZWxib3cgcGxvdDoKCmBgYHtyIGVjaG89Rn0KUENFbGJvd1Bsb3QoZGYwLmFsbCxudW0ucGMgPSAzMCkKYGBgCgpJIGNob3NlIDIwIFBDcyBmb3IgZG93biBzdHJlYW0gYW5hbHlzaXMuCgpSdW4gdFNORSBhbmFseXNpczoKYGBge3IgcmVzdWx0cz0naGlkZScsIG1lc3NhZ2U9Rn0KZGYwLmFsbCA8LSBSdW5UU05FKGRmMC5hbGwsIAogICAgICAgICAgICAgICBkaW1zLnVzZSA9IDE6MjAsIAogICAgICAgICAgICAgICBwZXJwbGV4aXR5ID0gMzAsIAogICAgICAgICAgICAgICBzZWVkLnVzZSA9IDEpCgpkZjAuYWxsIDwtIEZpbmRDbHVzdGVycyhvYmplY3QgPSBkZjAuYWxsLCAKICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24udHlwZSA9ICJwY2EiLCAKICAgICAgICAgICAgICAgICAgICBkaW1zLnVzZSA9IDE6MjAsIAogICAgICAgICAgICAgICAgICAgIHJlc29sdXRpb24gPSAwLjgsIAogICAgICAgICAgICAgICAgICAgIHByaW50Lm91dHB1dCA9IDAsIAogICAgICAgICAgICAgICAgICAgIHNhdmUuU05OID0gRiwgCiAgICAgICAgICAgICAgICAgICAgZm9yY2UucmVjYWxjID0gVCkgCmBgYAoKYGBge3IgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9MTR9CnAxIDwtIFRTTkVQbG90KG9iamVjdCA9IGRmMC5hbGwsIAogICAgICAgICAgICAgICBwdC5zaXplID0gMywKICAgICAgICAgICAgICAgZG8ubGFiZWwgPSBULAogICAgICAgICAgICAgICBsYWJlbC5zaXplID0gMTAsIAogICAgICAgICAgICAgICBkby5yZXR1cm4gPSBUKQpwMiA8LSBUU05FUGxvdChvYmplY3QgPSBkZjAuYWxsLCAKICAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAib3JpZy5pZGVudCIsIAogICAgICAgICAgICAgICBkby5yZXR1cm4gPSBULCAKICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDMpCgpwbG90X2dyaWQocDEsIHAyLCBuY29sID0gMikKCmBgYAoKYGBge3J9CnNvdXJjZSgifi96aGVuL3NjcmlwdHMvUi9mdW5jdGlvbnMvbWFya2Vycy5SIikKbWFya2VycyA8LSB1bmxpc3Qoc2FwcGx5KG1hcmtlcnMsZnVuY3Rpb24oeCl7Z3JlcCh4LCByb3duYW1lcyhkZjAuYWxsQGRhdGEpLCB2YWx1ZSA9IFQpfSkpCmBgYAoKYGBge3J9CiMjIFBsb3QgbWFya2VyIGdlbmVzCnRlbXAgPC0gZGYwLmFsbEBkYXRhW21hcmtlcnMsXQoKb3JkIDwtIG9yZGVyKGRmMC5hbGxAbWV0YS5kYXRhJHJlcy4wLjgpCkNvbFNpZGVDb2xvcnMgPC0gYyhnZ19jb2xvcl9odWUobGVuZ3RoKHVuaXF1ZShkZjAuYWxsQG1ldGEuZGF0YSRyZXMuMC44KSkpW2FzLm51bWVyaWMoYXMuZmFjdG9yKGRmMC5hbGxAbWV0YS5kYXRhJHJlcy4wLjgpKV0sCnJhaW5ib3coMilbYXMubnVtZXJpYyhhcy5mYWN0b3IoZGYwLmFsbEBtZXRhLmRhdGEkb3JpZy5pZGVudCkpXSkKCkNvbFNpZGVDb2xvcnMgPC0gbWF0cml4KGRhdGEgPSBDb2xTaWRlQ29sb3JzLCBucm93ID0gbmNvbCh0ZW1wKSk7CkNvbFNpZGVDb2xvcnMgPC0gQ29sU2lkZUNvbG9yc1tvcmQsIF07Cgpjb2xzZXAgPC0gbGFwcGx5KHVuaXF1ZShkZjAuYWxsQG1ldGEuZGF0YSRyZXMuMC44W29yZF0pLCAKZnVuY3Rpb24oeHgpe2xlbmd0aCh3aGljaChkZjAuYWxsQG1ldGEuZGF0YSRyZXMuMC44ID09IHh4KSl9KTsKY29sc2VwIDwtIGN1bXN1bSh1bmxpc3QoY29sc2VwKSk7ICAKCnBhaXJzLmJyZWFrcyA8LSBzZXEoLTIsIDIsIGxlbmd0aC5vdXQ9MTAxKTsKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTE1LCBmaWcud2lkdGg9N30KaGVhdG1hcC4zKHRlbXBbLCBvcmRdLAogICAgICAgICAgYnJlYWtzID0gcGFpcnMuYnJlYWtzLAogICAgICAgICAgI3N5bWJyZWFrcyA9IFQsCiAgICAgICAgICBrZXlzaXplID0gMC44LCAKICAgICAgICAgIG1haW49Ik1hcmtlciBnZW5lIGV4cHJlc3Npb24iLAogICAgICAgICAgY29sID0gZ3Bsb3RzOjpibHVlcmVkKDEwMCksCiAgICAgICAgICBzeW1rZXkgPSBGLAogICAgICAgICAgY2V4Um93PTEsIGNleENvbCA9IDAuNiwgCiAgICAgICAgICBSb3d2ID0gRiwgCiAgICAgICAgICBDb2x2ID0gRiwjYXMuZGVuZHJvZ3JhbShoY2EpLCAKICAgICAgICAgIENvbFNpZGVDb2xvcnMgPSBhcy5tYXRyaXgoQ29sU2lkZUNvbG9ycyksCiAgICAgICAgICBDb2xTaWRlQ29sb3JzU2l6ZSA9IDEsCiAgICAgICAgICAjUm93U2lkZUNvbG9ycyA9IFJvd1NpZGVDb2xvcnMsCiAgICAgICAgICBkZW5kcm9ncmFtID0gIm5vbmUiLAogICAgICAgICAgc2NhbGUgPSAicm93IiwKICAgICAgICAgIGNvbHNlcCA9IGNvbHNlcCwKICAgICAgICAgIHNlcGNvbG9yID0gImJsYWNrIiwKICAgICAgICAgIGxhYlJvdyA9IHJvd25hbWVzKHRlbXApLCAKICAgICAgICAgIGxhYkNvbCA9ICIiLAogICAgICAgICAgbmEucm0gPSBGKQpgYGAKCkFkZCBhbm90aGVyIGRhdGFzZXQ/IFpob25nIGV0IGFsLiAyMDE3CmBgYHtyfQpkZi56aG9uZyA8LSByZWFkLnRhYmxlKCJ+L3poZW4vZGF0YS9oT3JnL3Jhd19kYXRhL0dTRTEwNDI3Nl9hbGxfcGZjXzIzOTRfVU1JX2NvdW50X05PRVJDQy54bHMiKQoKCk1UIDwtIGdyZXAoIl5NVC0iLCByb3duYW1lcyhkZi56aG9uZykpClJQIDwtIGdyZXAoIl5SUCIsIHJvd25hbWVzKGRmLnpob25nKSkKCnJvd25hbWVzKGRmLnpob25nKSA8LSBnc3ViKCJcXC0iLCAiXFwuIixyb3duYW1lcyhkZi56aG9uZykpCgpkZjAuemhvbmcgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGFzLm1hdHJpeChkZi56aG9uZ1sgLWMoTVQsUlApLCBdKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvamVjdCA9ICJaaG9uZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheS5wcm9ncmVzcyA9IEYpCnRlbXAgPC0gc3Ryc3BsaXQoZGYwLnpob25nQGNlbGwubmFtZXMsIHNwbGl0ID0gIl8iKQpkZjAuemhvbmdAbWV0YS5kYXRhJFRpbWVfcG9pbnQgPC0gc2FwcGx5KHRlbXAsICBmdW5jdGlvbih4eCkgeHhbMV0pCmRmMC56aG9uZ0BtZXRhLmRhdGEkQXJlYV8gPC0gc2FwcGx5KHRlbXAsICBmdW5jdGlvbih4eCkgeHhbMl0pCmRmMC56aG9uZ0BtZXRhLmRhdGEkb3JpZy5pZGVudCA8LSAiemhvbmciCmBgYAoKTWVyZ2UgWmhvbmcgZXQgYWwgZGF0YXNldCB0byB0aGUgb3RoZXIgdHdvOgpgYGB7cn0KZGYwLmFsbCA8LSBNZXJnZVNldXJhdChkZjAuYWxsLCBkZjAuemhvbmcsCiAgICAgICAgICAgICAgICAgICAgICAgbWluLmNlbGxzID0gMTAsCiAgICAgICAgICAgICAgICAgICAgICAgZG8ubm9ybWFsaXplID0gVCwKICAgICAgICAgICAgICAgICAgICAgICBzY2FsZS5mYWN0b3IgPSAxMDAwMDApCmBgYAoKYGBge3J9CmRmMC5hbGxAbWV0YS5kYXRhJFRpbWVfcG9pbnQyW2RmMC5hbGxAbWV0YS5kYXRhJFRpbWVfcG9pbnQgJWluJSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiNSBwY3ciLCAiNiBwY3ciLCAiOCBwY3ciLCAiR1cwOCIsICJHVzA5IiwiR1cxMCIpXSA8LSAiVzEiCmRmMC5hbGxAbWV0YS5kYXRhJFRpbWVfcG9pbnQyW2RmMC5hbGxAbWV0YS5kYXRhJFRpbWVfcG9pbnQgJWluJSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiMTEiLCAiMTMiLCAiMTMuMyIsIjE0IiwiMTQuMiIsIjE0LjUiLCIxNC43IiwiR1cxMiIsIkdXMTMiLCAiR1cxNiIpXSA8LSAiVzIiCmRmMC5hbGxAbWV0YS5kYXRhJFRpbWVfcG9pbnQyW2RmMC5hbGxAbWV0YS5kYXRhJFRpbWVfcG9pbnQgJWluJSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiMTUiLCAiMTYgcGN3IiwgIjE2LjMiLCIxNy4zIiwiMTcuNSIsIjE4LjUiLCJHVzE5IildIDwtICJXMyIKZGYwLmFsbEBtZXRhLmRhdGEkVGltZV9wb2ludDJbZGYwLmFsbEBtZXRhLmRhdGEkVGltZV9wb2ludCAlaW4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKCIxOSIsICIxOSBwY3ciLCAiMjAgcGN3IiwiMjAiLCIyMS41IiwiMjIiLCJHVzIzIiwiR1cyNiIpXSA8LSAiVzQiCmRmMC5hbGxAbWV0YS5kYXRhJFRpbWVfcG9pbnQyW2RmMC5hbGxAbWV0YS5kYXRhJFRpbWVfcG9pbnQgJWluJSBjKCIzMiIpXSA8LSAiVzUiCgpgYGAKCgpSZWdyZXNzIG91dCBuVU1JIGFuZCBkaWZmZXJlbnQgc3R1ZGllcy4KYGBge3J9CmRmMC5hbGwgPC0gU2NhbGVEYXRhKGRmMC5hbGwsIAogICAgICAgICAgICAgICAgICAgICB2YXJzLnRvLnJlZ3Jlc3MgPSBjKCJuVU1JIiwgIm9yaWcuaWRlbnQiKSwKICAgICAgICAgICAgICAgICAgICAgZGlzcGxheS5wcm9ncmVzcyA9IEYpCmBgYAoKTG9vayBhdCBleHByZXNzaW9uIGxldmVsIGRpc3RyaWJ1dGlvbiBpbiBub3JtYWxpemVkIGRhdGE6CmBgYHtyIGVjaG89RiwgZmlnLndpZHRoPTE2LCBmaWcuaGVpZ2h0PTE2fQpwMSA8LSBwbG90R2VuZURpc3RyKCJQQVg2IixvYmplY3QxID0gZGYwLmFsbCkKcDIgPC0gcGxvdEdlbmVEaXN0cigiQkNMMTFCIixvYmplY3QxID0gZGYwLmFsbCkKcDMgPC0gcGxvdEdlbmVEaXN0cigiR0FEMSIsb2JqZWN0MSA9IGRmMC5hbGwpCnA0IDwtIHBsb3RHZW5lRGlzdHIoIk9MSUcxIixvYmplY3QxID0gZGYwLmFsbCkKcGxvdF9ncmlkKHAxLCBwMiwgcDMsIHA0LCBucm93ID0gMikKYGBgCgpUYWtlIGEgbG9vayBhdCBleHByZXNzaW9uIGxldmVsIGRpc3RyaWJ1dGlvbiBpbiBzY2FsZWQgZGF0YToKYGBge3IgZWNobz1GLCBmaWcud2lkdGg9MTYsIGZpZy5oZWlnaHQ9MTZ9CnAxIDwtIHBsb3RHZW5lRGlzdHIoIlBBWDYiLG9iamVjdDEgPSBkZjAuYWxsLCBkYXRhLnR5cGUgPSAic2NhbGVkIikKcDIgPC0gcGxvdEdlbmVEaXN0cigiQkNMMTFCIixvYmplY3QxID0gZGYwLmFsbCwgZGF0YS50eXBlID0gInNjYWxlZCIpCnAzIDwtIHBsb3RHZW5lRGlzdHIoIkdBRDEiLG9iamVjdDEgPSBkZjAuYWxsLCBkYXRhLnR5cGUgPSAic2NhbGVkIikKcDQgPC0gcGxvdEdlbmVEaXN0cigiT0xJRzEiLG9iamVjdDEgPSBkZjAuYWxsLCBkYXRhLnR5cGUgPSAic2NhbGVkIikKcGxvdF9ncmlkKHAxLCBwMiwgcDMsIHA0LCBucm93ID0gMikKYGBgCgpGaW5kIGhpZ2hseSB2YXJpYWJsZSBnZW5lcyB0byBjb25kdWN0IFBDQSBhbmFseXNpczoKYGBge3IgZWNobz1GLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD03fQpkZjAuYWxsIDwtIEZpbmRWYXJpYWJsZUdlbmVzKGRmMC5hbGwsIHgubG93LmN1dG9mZiA9IDAuNSwgeS5jdXRvZmYgPSAwKQpgYGAKClJ1biBQQ0E6CmBgYHtyfQpkZjAuYWxsIDwtIFJ1blBDQShvYmplY3QgPSBkZjAuYWxsLAogICAgICAgICAgICAgICAgICBwYy5nZW5lcz1kZjAuYWxsQHZhci5nZW5lcywgCiAgICAgICAgICAgICAgICAgIHBjcy5jb21wdXRlID0gMzAsIAogICAgICAgICAgICAgICAgICBwY3MucHJpbnQgPSAxOjEwLAogICAgICAgICAgICAgICAgICBkby5wcmludCA9IEYsIAogICAgICAgICAgICAgICAgICBnZW5lcy5wcmludCA9IDEwKQpgYGAKCmBgYHtyIGVjaG89RiwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9N30KcDEgPC0gUENBUGxvdChkZjAuYWxsLCBncm91cC5ieSA9ICJvcmlnLmlkZW50IiwgZG8ucmV0dXJuID0gVCkKcDEgPC0gcDEgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAuMSwgMC45KSkKcDEKYGBgCgpQaWNrIHNpZ25pZmljYW50IFBDcyBmb3IgdFNORSBhbmQgY2x1c3RlcmluZyBhbmFseXNpcyBiYXNlZCBvbiBlbGJvdyBwbG90OgoKYGBge3IgZWNobz1GfQpQQ0VsYm93UGxvdChkZjAuYWxsLG51bS5wYyA9IDMwKQpgYGAKCkkgY2hvc2UgMjAgUENzIGZvciBkb3duIHN0cmVhbSBhbmFseXNpcy4KClJ1biB0U05FIGFuYWx5c2lzOgpgYGB7ciByZXN1bHRzPSdoaWRlJywgbWVzc2FnZT1GfQpkZjAuYWxsIDwtIFJ1blRTTkUoZGYwLmFsbCwgCiAgICAgICAgICAgICAgIGRpbXMudXNlID0gMToyMCwgCiAgICAgICAgICAgICAgIHBlcnBsZXhpdHkgPSAzMCwgCiAgICAgICAgICAgICAgIHNlZWQudXNlID0gMSkKCmRmMC5hbGwgPC0gRmluZENsdXN0ZXJzKG9iamVjdCA9IGRmMC5hbGwsIAogICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbi50eXBlID0gInBjYSIsIAogICAgICAgICAgICAgICAgICAgIGRpbXMudXNlID0gMToyMCwgCiAgICAgICAgICAgICAgICAgICAgcmVzb2x1dGlvbiA9IDAuOCwgCiAgICAgICAgICAgICAgICAgICAgcHJpbnQub3V0cHV0ID0gMCwgCiAgICAgICAgICAgICAgICAgICAgc2F2ZS5TTk4gPSBGLCAKICAgICAgICAgICAgICAgICAgICBmb3JjZS5yZWNhbGMgPSBUKSAKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD0yMX0KcDEgPC0gVFNORVBsb3Qob2JqZWN0ID0gZGYwLmFsbCwgCiAgICAgICAgICAgICAgIHB0LnNpemUgPSAzLAogICAgICAgICAgICAgICBkby5sYWJlbCA9IFQsCiAgICAgICAgICAgICAgIGxhYmVsLnNpemUgPSAxMCwgCiAgICAgICAgICAgICAgIGRvLnJldHVybiA9IFQpCnAyIDwtIFRTTkVQbG90KG9iamVjdCA9IGRmMC5hbGwsIAogICAgICAgICAgICAgICBncm91cC5ieSA9ICJvcmlnLmlkZW50IiwgCiAgICAgICAgICAgICAgIGRvLnJldHVybiA9IFQsIAogICAgICAgICAgICAgICBwdC5zaXplID0gMykKcDMgPC0gVFNORVBsb3Qob2JqZWN0ID0gZGYwLmFsbCwgCiAgICAgICAgICAgICAgIGdyb3VwLmJ5ID0gIlRpbWVfcG9pbnQyIiwgCiAgICAgICAgICAgICAgIGRvLnJldHVybiA9IFQsIAogICAgICAgICAgICAgICBwdC5zaXplID0gMykKCnBsb3RfZ3JpZChwMSwgcDIsIHAzLCBuY29sID0gMykKYGBgCgpgYGB7cn0Kc291cmNlKCJ+L3poZW4vc2NyaXB0cy9SL2Z1bmN0aW9ucy9tYXJrZXJzLlIiKQptYXJrZXJzIDwtIHVubGlzdChzYXBwbHkobWFya2VycyxmdW5jdGlvbih4KXtncmVwKHgsIHJvd25hbWVzKGRmMC5hbGxAZGF0YSksIHZhbHVlID0gVCl9KSkKYGBgCgpgYGB7cn0KIyMgUGxvdCBtYXJrZXIgZ2VuZXMKdGVtcCA8LSBkZjAuYWxsQGRhdGFbbWFya2VycyxdCgpvcmQgPC0gb3JkZXIoZGYwLmFsbEBtZXRhLmRhdGEkcmVzLjAuOCkKQ29sU2lkZUNvbG9ycyA8LSBjKGdnX2NvbG9yX2h1ZShsZW5ndGgodW5pcXVlKGRmMC5hbGxAbWV0YS5kYXRhJHJlcy4wLjgpKSlbYXMubnVtZXJpYyhhcy5mYWN0b3IoZGYwLmFsbEBtZXRhLmRhdGEkcmVzLjAuOCkpXSwKcmFpbmJvdygzKVthcy5udW1lcmljKGFzLmZhY3RvcihkZjAuYWxsQG1ldGEuZGF0YSRvcmlnLmlkZW50KSldKQoKQ29sU2lkZUNvbG9ycyA8LSBtYXRyaXgoZGF0YSA9IENvbFNpZGVDb2xvcnMsIG5yb3cgPSBuY29sKHRlbXApKTsKQ29sU2lkZUNvbG9ycyA8LSBDb2xTaWRlQ29sb3JzW29yZCwgXTsKCmNvbHNlcCA8LSBsYXBwbHkodW5pcXVlKGRmMC5hbGxAbWV0YS5kYXRhJHJlcy4wLjhbb3JkXSksIApmdW5jdGlvbih4eCl7bGVuZ3RoKHdoaWNoKGRmMC5hbGxAbWV0YS5kYXRhJHJlcy4wLjggPT0geHgpKX0pOwpjb2xzZXAgPC0gY3Vtc3VtKHVubGlzdChjb2xzZXApKTsgIAoKcGFpcnMuYnJlYWtzIDwtIHNlcSgtMiwgMiwgbGVuZ3RoLm91dD0xMDEpOwpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9MTUsIGZpZy53aWR0aD0xNH0KaGVhdG1hcC4zKHRlbXBbLCBvcmRdLAogICAgICAgICAgYnJlYWtzID0gcGFpcnMuYnJlYWtzLAogICAgICAgICAga2V5ID0gRiwKICAgICAgICAgICNzeW1icmVha3MgPSBULAogICAgICAgICAga2V5c2l6ZSA9IDAuOCwgCiAgICAgICAgICBtYWluPSJNYXJrZXIgZ2VuZSBleHByZXNzaW9uIiwKICAgICAgICAgIGNvbCA9IGdwbG90czo6Ymx1ZXJlZCgxMDApLAogICAgICAgICAgc3lta2V5ID0gRiwKICAgICAgICAgIGNleFJvdz0xLCBjZXhDb2wgPSAwLjYsIAogICAgICAgICAgUm93diA9IEYsIAogICAgICAgICAgQ29sdiA9IEYsI2FzLmRlbmRyb2dyYW0oaGNhKSwgCiAgICAgICAgICBDb2xTaWRlQ29sb3JzID0gYXMubWF0cml4KENvbFNpZGVDb2xvcnMpLAogICAgICAgICAgQ29sU2lkZUNvbG9yc1NpemUgPSAxLAogICAgICAgICAgI1Jvd1NpZGVDb2xvcnMgPSBSb3dTaWRlQ29sb3JzLAogICAgICAgICAgZGVuZHJvZ3JhbSA9ICJub25lIiwKICAgICAgICAgIHNjYWxlID0gInJvdyIsCiAgICAgICAgICBjb2xzZXAgPSBjb2xzZXAsCiAgICAgICAgICBzZXBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICBsYWJSb3cgPSByb3duYW1lcyh0ZW1wKSwgCiAgICAgICAgICBsYWJDb2wgPSAiIiwKICAgICAgICAgIG5hLnJtID0gRikKYGBgCgo+IFRoaXMgbG9va3MgcHJldHR5IGdvb2QuIENhbiBJIGFkZCBtb3JlIGRhdGFzZXRzPyAK
comments powered by Disqus