Functions
Data
SCC4.data = Read10X(data.dir = "./Data/cervical_cancer_data/Qiu et al/SCC4//")
SCC4 <- CreateSeuratObject(counts = SCC4.data, project = "scc", min.cells = 3, min.features = 200)
SCC4[["percent.mt"]] <- PercentageFeatureSet(SCC4, pattern = "^MT-")
SCC4 <- subset(SCC4, subset = percent.mt < 10)
SCC4 <- NormalizeData(SCC4)
Performing log-normalization
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
SCC5.data = Read10X(data.dir = "./Data/cervical_cancer_data/Qiu et al/SCC5/")
SCC5 <- CreateSeuratObject(counts = SCC5.data, project = "scc", min.cells = 3, min.features = 200)
SCC5[["percent.mt"]] <- PercentageFeatureSet(SCC5, pattern = "^MT-")
SCC5 <- subset(SCC5, subset = percent.mt < 10)
SCC5 <- NormalizeData(SCC5)
Performing log-normalization
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
mtx <- "./Data/cervical_cancer_data/Qiu et al/GSE197461/GSM5917937_SCC_1_matrix.mtx.gz"
cells <- "./Data/cervical_cancer_data/Qiu et al/GSE197461/GSM5917937_SCC_1_barcodes.tsv.gz"
features <- "./Data/cervical_cancer_data/Qiu et al/GSE197461/GSM5917937_SCC_1_features.tsv.gz"
SCC1.data <- ReadMtx(mtx = mtx, cells = cells, features = features)
SCC1 <- CreateSeuratObject(counts = SCC1.data, project = "scc", min.cells = 3, min.features = 200)
SCC1[["percent.mt"]] <- PercentageFeatureSet(SCC1, pattern = "^MT-")
SCC1 <- subset(SCC1, subset = percent.mt < 10)
SCC1 <- NormalizeData(SCC1)
Performing log-normalization
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
mtx <- "./Data/cervical_cancer_data/Qiu et al/GSE197461/GSM5917938_SCC_2_matrix.mtx.gz"
cells <- "./Data/cervical_cancer_data/Qiu et al/GSE197461/GSM5917938_SCC_2_barcodes.tsv.gz"
features <- "./Data/cervical_cancer_data/Qiu et al/GSE197461/GSM5917938_SCC_2_features.tsv.gz"
SCC2.data <- ReadMtx(mtx = mtx, cells = cells, features = features)
SCC2 <- CreateSeuratObject(counts = SCC2.data, project = "scc", min.cells = 3, min.features = 200)
SCC2[["percent.mt"]] <- PercentageFeatureSet(SCC2, pattern = "^MT-")
SCC2 <- subset(SCC2, subset = percent.mt < 10)
SCC2 <- NormalizeData(SCC2)
Performing log-normalization
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
mtx <- "./Data/cervical_cancer_data/Qiu et al/GSE197461/GSM5917939_SCC_3_matrix.mtx.gz"
cells <- "./Data/cervical_cancer_data/Qiu et al/GSE197461/GSM5917939_SCC_3_barcodes.tsv.gz"
features <- "./Data/cervical_cancer_data/Qiu et al/GSE197461/GSM5917939_SCC_3_features.tsv.gz"
SCC3.data <- ReadMtx(mtx = mtx, cells = cells, features = features)
SCC3 <- CreateSeuratObject(counts = SCC3.data, project = "scc", min.cells = 3, min.features = 200)
SCC3[["percent.mt"]] <- PercentageFeatureSet(SCC3, pattern = "^MT-")
SCC3 <- subset(SCC3, subset = percent.mt < 10)
SCC3 <- NormalizeData(SCC3)
Performing log-normalization
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
VlnPlot(object = SCC1,features = "MYB")+ggtitle("SCC1")|VlnPlot(object = SCC2,features = "MYB")+ggtitle("SCC2")|VlnPlot(object = SCC3,features = "MYB")+ggtitle("SCC3")|VlnPlot(object = SCC4,features = "MYB")+ggtitle("SCC4")|VlnPlot(object = SCC5,features = "MYB",group.by = "orig.ident")+ggtitle("SCC5")

# read processed data:
SCC1_cancer = readRDS(file = "./Data/cervical_cancer_data/Qiu et al/SCC1/SCC1_cancer.RDS")
SCC2_cancer = readRDS(file = "./Data/cervical_cancer_data/Qiu et al/SCC2/SCC2_cancer_processed.RDS")
SCC3_cancer = readRDS(file = "./Data/cervical_cancer_data/Qiu et al/SCC3/SCC3_cancer_processed.RDS")
SCC4_cancer = readRDS(file = "./Data/cervical_cancer_data/Qiu et al/SCC4/SCC4_cancer_processed.RDS")
SCC5_cancer = readRDS(file = "./Data/cervical_cancer_data/Qiu et al/SCC5/SCC5_cancer_processed.RDS")
scc.big <- merge(SCC1_cancer, y = c(SCC2_cancer,SCC3_cancer, SCC4_cancer,SCC5_cancer), add.cell.ids = c("SCC1","SCC2", "SCC3", "SCC4","SCC5"), project = "SCC")
scc.big$orig.ident = sapply(X = strsplit(colnames(scc.big), split = "_"), FUN = "[", 1)
VlnPlot(object = scc.big,features = "MYB",group.by = "orig.ident",slot = "data", assay = "RNA")

NA
NA
b = FetchData(object = scc.big,vars = c("MYB","orig.ident"),slot = "data", assay = "RNA")
b %>% group_by(orig.ident) %>%
summarise(counts = sum(MYB > 0, na.rm = TRUE))
Violin plot all
patients without scc2
scc_myb_patients<- subset(scc.big, subset = orig.ident %in% c("SCC3","SCC4","SCC5"))
library(rstatix)
myb_vs_hpv = FetchData(object = scc_myb_patients, vars = c("hpv_positive", "MYB"))
df = reshape2::melt(myb_vs_hpv,value.name = "logTPM") %>% dplyr::rename(gene = variable)
Using hpv_positive as id variables
stat.test <- df %>%
wilcox_test(logTPM ~ hpv_positive)
stat.test
p = ggplot(myb_vs_hpv,aes( x = hpv_positive, y = MYB))+
geom_violin(trim=FALSE,aes(fill = hpv_positive)) +
theme_minimal()+
stat_summary(fun.data = function(x) data.frame(y=max(x)*1.15, label = paste("Mean=",round(mean(x),digits = 2))), geom="text") +ylab("average MYB")+ggtitle("all patients") +
stat_pvalue_manual(stat.test,y.position = 3, label = "Wilcox, p = {p}",remove.bracket = F)+
geom_boxplot(width=.1, outlier.shape=NA)
p

pdf(file = "./Figures/SCC_myb_hpv_violin_all_patients.pdf")
p
dev.off()
null device
1
Violin plot all
patients with scc2
scc_myb_patients<- subset(scc.big, subset = orig.ident %in% c("SCC2","SCC3","SCC4","SCC5"))
library(rstatix)
myb_vs_hpv = FetchData(object = scc_myb_patients, vars = c("hpv_positive", "MYB"))
df = reshape2::melt(myb_vs_hpv,value.name = "logTPM") %>% dplyr::rename(gene = variable)
Using hpv_positive as id variables
stat.test <- df %>%
wilcox_test(logTPM ~ hpv_positive)
stat.test
p = ggplot(myb_vs_hpv,aes( x = hpv_positive, y = MYB))+
geom_violin(trim=FALSE,aes(fill = hpv_positive)) +
theme_minimal()+
stat_summary(fun.data = function(x) data.frame(y=max(x)*1.15, label = paste("Mean=",round(mean(x),digits = 2))), geom="text") +ylab("average MYB")+ggtitle("all patients") +
stat_pvalue_manual(stat.test,y.position = 3, label = "Wilcox, p = {p}",remove.bracket = F)+
geom_boxplot(width=.1, outlier.shape=NA)
p

Boxplot by patient
scc_myb_patients<- subset(scc.big, subset = orig.ident %in% c("SCC2","SCC3","SCC4","SCC5"))
df = FetchData(object = scc_myb_patients,vars = c("orig.ident","MYB","hpv_positive")) %>% group_by(orig.ident,hpv_positive) %>% summarise(
myb = mean(MYB),.groups = "drop_last")
df = reshape2::dcast(df, orig.ident ~ hpv_positive)
Using myb as value column: use value.var to override.
p = ggpaired(df, cond1 = "positive",cond2 = "negative",palette = "jco",
add = "jitter", line.color = "gray", line.size = 0.4,id = "orig.ident", fill = "condition") + theme_minimal()+
stat_compare_means(method = "wilcox.test",comparisons = list(c("positive","negative")),paired = F)+
stat_summary(fun.data = function(x) data.frame(y=max(x)*1.2, label = paste("Mean=",round(mean(x),digits = 2))), geom="text")+ylab("MYB")
p

pdf(file = "./Figures/SCC_HPV_MYB_boxplot_bySample.pdf",width = 8)
p
dev.off()
null device
1
All genes boxplots
genes = c("AK4", "ANLN", "CAPG", "IFT122", "JAG1", "MYB", "PBRM1" )
myb_vs_hpv = FetchData(object = scc_myb_patients,vars = c("hpv_positive",genes))
df = reshape2::melt(myb_vs_hpv,value.name = "logTPM") %>% dplyr::rename(gene = variable)
Using hpv_positive as id variables
stat.test <- df %>%
group_by(gene) %>%
wilcox_test(logTPM ~ hpv_positive) %>%
mutate(y.position = 5)
stat.test
stat.test <- stat.test %>%
add_xy_position(x = "gene", dodge = 0.8)
p = ggboxplot(
df,
x = "gene",
y = "logTPM",
color = "hpv_positive",
palette = "jco",
add = "jitter"
)+ stat_pvalue_manual(stat.test,y.position = 4, label = "p = {p}",remove.bracket = T)
p

pdf(file = "./Figures/SCC_HPV_genes_all_patients.pdf",width = 8)
p
dev.off()
null device
1
LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMudGltZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvY19kZXB0aDogMQotLS0KCgoKIyBGdW5jdGlvbnMKCmBgYHtyIHdhcm5pbmc9RkFMU0V9CmBgYAoKYGBge3J9CmBgYAoKIyBEYXRhCgpgYGB7cn0KU0NDNC5kYXRhICA9IFJlYWQxMFgoZGF0YS5kaXIgPSAiLi9EYXRhL2NlcnZpY2FsX2NhbmNlcl9kYXRhL1FpdSBldCBhbC9TQ0M0Ly8iKQpTQ0M0IDwtIENyZWF0ZVNldXJhdE9iamVjdChjb3VudHMgPSBTQ0M0LmRhdGEsIHByb2plY3QgPSAic2NjIiwgbWluLmNlbGxzID0gMywgbWluLmZlYXR1cmVzID0gMjAwKQpTQ0M0W1sicGVyY2VudC5tdCJdXSA8LSBQZXJjZW50YWdlRmVhdHVyZVNldChTQ0M0LCBwYXR0ZXJuID0gIl5NVC0iKQpTQ0M0IDwtIHN1YnNldChTQ0M0LCBzdWJzZXQgPSBwZXJjZW50Lm10IDwgMTApClNDQzQgPC0gTm9ybWFsaXplRGF0YShTQ0M0KQoKClNDQzUuZGF0YSAgPSBSZWFkMTBYKGRhdGEuZGlyID0gIi4vRGF0YS9jZXJ2aWNhbF9jYW5jZXJfZGF0YS9RaXUgZXQgYWwvU0NDNS8iKQpTQ0M1IDwtIENyZWF0ZVNldXJhdE9iamVjdChjb3VudHMgPSBTQ0M1LmRhdGEsIHByb2plY3QgPSAic2NjIiwgbWluLmNlbGxzID0gMywgbWluLmZlYXR1cmVzID0gMjAwKQpTQ0M1W1sicGVyY2VudC5tdCJdXSA8LSBQZXJjZW50YWdlRmVhdHVyZVNldChTQ0M1LCBwYXR0ZXJuID0gIl5NVC0iKQpTQ0M1IDwtIHN1YnNldChTQ0M1LCBzdWJzZXQgPSBwZXJjZW50Lm10IDwgMTApClNDQzUgPC0gTm9ybWFsaXplRGF0YShTQ0M1KQoKbXR4IDwtICIuL0RhdGEvY2VydmljYWxfY2FuY2VyX2RhdGEvUWl1IGV0IGFsL0dTRTE5NzQ2MS9HU001OTE3OTM3X1NDQ18xX21hdHJpeC5tdHguZ3oiCmNlbGxzIDwtICIuL0RhdGEvY2VydmljYWxfY2FuY2VyX2RhdGEvUWl1IGV0IGFsL0dTRTE5NzQ2MS9HU001OTE3OTM3X1NDQ18xX2JhcmNvZGVzLnRzdi5neiIKZmVhdHVyZXMgPC0gICIuL0RhdGEvY2VydmljYWxfY2FuY2VyX2RhdGEvUWl1IGV0IGFsL0dTRTE5NzQ2MS9HU001OTE3OTM3X1NDQ18xX2ZlYXR1cmVzLnRzdi5neiIKU0NDMS5kYXRhIDwtIFJlYWRNdHgobXR4ID0gbXR4LCBjZWxscyA9IGNlbGxzLCBmZWF0dXJlcyA9IGZlYXR1cmVzKQpTQ0MxIDwtIENyZWF0ZVNldXJhdE9iamVjdChjb3VudHMgPSBTQ0MxLmRhdGEsIHByb2plY3QgPSAic2NjIiwgbWluLmNlbGxzID0gMywgbWluLmZlYXR1cmVzID0gMjAwKQpTQ0MxW1sicGVyY2VudC5tdCJdXSA8LSBQZXJjZW50YWdlRmVhdHVyZVNldChTQ0MxLCBwYXR0ZXJuID0gIl5NVC0iKQpTQ0MxIDwtIHN1YnNldChTQ0MxLCBzdWJzZXQgPSBwZXJjZW50Lm10IDwgMTApClNDQzEgPC0gTm9ybWFsaXplRGF0YShTQ0MxKQoKbXR4IDwtICIuL0RhdGEvY2VydmljYWxfY2FuY2VyX2RhdGEvUWl1IGV0IGFsL0dTRTE5NzQ2MS9HU001OTE3OTM4X1NDQ18yX21hdHJpeC5tdHguZ3oiCmNlbGxzIDwtICIuL0RhdGEvY2VydmljYWxfY2FuY2VyX2RhdGEvUWl1IGV0IGFsL0dTRTE5NzQ2MS9HU001OTE3OTM4X1NDQ18yX2JhcmNvZGVzLnRzdi5neiIKZmVhdHVyZXMgPC0gICIuL0RhdGEvY2VydmljYWxfY2FuY2VyX2RhdGEvUWl1IGV0IGFsL0dTRTE5NzQ2MS9HU001OTE3OTM4X1NDQ18yX2ZlYXR1cmVzLnRzdi5neiIKU0NDMi5kYXRhIDwtIFJlYWRNdHgobXR4ID0gbXR4LCBjZWxscyA9IGNlbGxzLCBmZWF0dXJlcyA9IGZlYXR1cmVzKQpTQ0MyIDwtIENyZWF0ZVNldXJhdE9iamVjdChjb3VudHMgPSBTQ0MyLmRhdGEsIHByb2plY3QgPSAic2NjIiwgbWluLmNlbGxzID0gMywgbWluLmZlYXR1cmVzID0gMjAwKQpTQ0MyW1sicGVyY2VudC5tdCJdXSA8LSBQZXJjZW50YWdlRmVhdHVyZVNldChTQ0MyLCBwYXR0ZXJuID0gIl5NVC0iKQpTQ0MyIDwtIHN1YnNldChTQ0MyLCBzdWJzZXQgPSBwZXJjZW50Lm10IDwgMTApClNDQzIgPC0gTm9ybWFsaXplRGF0YShTQ0MyKQoKCm10eCA8LSAiLi9EYXRhL2NlcnZpY2FsX2NhbmNlcl9kYXRhL1FpdSBldCBhbC9HU0UxOTc0NjEvR1NNNTkxNzkzOV9TQ0NfM19tYXRyaXgubXR4Lmd6IgpjZWxscyA8LSAiLi9EYXRhL2NlcnZpY2FsX2NhbmNlcl9kYXRhL1FpdSBldCBhbC9HU0UxOTc0NjEvR1NNNTkxNzkzOV9TQ0NfM19iYXJjb2Rlcy50c3YuZ3oiCmZlYXR1cmVzIDwtICAiLi9EYXRhL2NlcnZpY2FsX2NhbmNlcl9kYXRhL1FpdSBldCBhbC9HU0UxOTc0NjEvR1NNNTkxNzkzOV9TQ0NfM19mZWF0dXJlcy50c3YuZ3oiClNDQzMuZGF0YSA8LSBSZWFkTXR4KG10eCA9IG10eCwgY2VsbHMgPSBjZWxscywgZmVhdHVyZXMgPSBmZWF0dXJlcykKU0NDMyA8LSBDcmVhdGVTZXVyYXRPYmplY3QoY291bnRzID0gU0NDMy5kYXRhLCBwcm9qZWN0ID0gInNjYyIsIG1pbi5jZWxscyA9IDMsIG1pbi5mZWF0dXJlcyA9IDIwMCkKU0NDM1tbInBlcmNlbnQubXQiXV0gPC0gUGVyY2VudGFnZUZlYXR1cmVTZXQoU0NDMywgcGF0dGVybiA9ICJeTVQtIikKU0NDMyA8LSBzdWJzZXQoU0NDMywgc3Vic2V0ID0gcGVyY2VudC5tdCA8IDEwKQpTQ0MzIDwtIE5vcm1hbGl6ZURhdGEoU0NDMykKCgpgYGAKCgpgYGB7ciBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD0xMn0KVmxuUGxvdChvYmplY3QgPSBTQ0MxLGZlYXR1cmVzID0gIk1ZQiIpK2dndGl0bGUoIlNDQzEiKXxWbG5QbG90KG9iamVjdCA9IFNDQzIsZmVhdHVyZXMgPSAiTVlCIikrZ2d0aXRsZSgiU0NDMiIpfFZsblBsb3Qob2JqZWN0ID0gU0NDMyxmZWF0dXJlcyA9ICJNWUIiKStnZ3RpdGxlKCJTQ0MzIil8VmxuUGxvdChvYmplY3QgPSBTQ0M0LGZlYXR1cmVzID0gIk1ZQiIpK2dndGl0bGUoIlNDQzQiKXxWbG5QbG90KG9iamVjdCA9IFNDQzUsZmVhdHVyZXMgPSAiTVlCIixncm91cC5ieSA9ICJvcmlnLmlkZW50IikrZ2d0aXRsZSgiU0NDNSIpCmBgYAoKCmBgYHtyfQojIHJlYWQgcHJvY2Vzc2VkIGRhdGE6ClNDQzFfY2FuY2VyICA9IHJlYWRSRFMoZmlsZSA9ICIuL0RhdGEvY2VydmljYWxfY2FuY2VyX2RhdGEvUWl1IGV0IGFsL1NDQzEvU0NDMV9jYW5jZXIuUkRTIikKU0NDMl9jYW5jZXIgID0gcmVhZFJEUyhmaWxlID0gIi4vRGF0YS9jZXJ2aWNhbF9jYW5jZXJfZGF0YS9RaXUgZXQgYWwvU0NDMi9TQ0MyX2NhbmNlcl9wcm9jZXNzZWQuUkRTIikKU0NDM19jYW5jZXIgPSByZWFkUkRTKGZpbGUgPSAiLi9EYXRhL2NlcnZpY2FsX2NhbmNlcl9kYXRhL1FpdSBldCBhbC9TQ0MzL1NDQzNfY2FuY2VyX3Byb2Nlc3NlZC5SRFMiKQpTQ0M0X2NhbmNlciA9IHJlYWRSRFMoZmlsZSA9ICIuL0RhdGEvY2VydmljYWxfY2FuY2VyX2RhdGEvUWl1IGV0IGFsL1NDQzQvU0NDNF9jYW5jZXJfcHJvY2Vzc2VkLlJEUyIpClNDQzVfY2FuY2VyICA9IHJlYWRSRFMoZmlsZSA9ICIuL0RhdGEvY2VydmljYWxfY2FuY2VyX2RhdGEvUWl1IGV0IGFsL1NDQzUvU0NDNV9jYW5jZXJfcHJvY2Vzc2VkLlJEUyIpCgpzY2MuYmlnIDwtIG1lcmdlKFNDQzFfY2FuY2VyLCB5ID0gYyhTQ0MyX2NhbmNlcixTQ0MzX2NhbmNlciwgU0NDNF9jYW5jZXIsU0NDNV9jYW5jZXIpLCBhZGQuY2VsbC5pZHMgPSBjKCJTQ0MxIiwiU0NDMiIsICJTQ0MzIiwgIlNDQzQiLCJTQ0M1IiksIHByb2plY3QgPSAiU0NDIikKc2NjLmJpZyRvcmlnLmlkZW50ID0gIHNhcHBseShYID0gc3Ryc3BsaXQoY29sbmFtZXMoc2NjLmJpZyksIHNwbGl0ID0gIl8iKSwgRlVOID0gIlsiLCAxKQoKClZsblBsb3Qob2JqZWN0ID0gc2NjLmJpZyxmZWF0dXJlcyA9ICJNWUIiLGdyb3VwLmJ5ID0gIm9yaWcuaWRlbnQiLHNsb3QgPSAiZGF0YSIsIGFzc2F5ID0gIlJOQSIpCgoKYGBgCgoKYGBge3J9CmIgPSBGZXRjaERhdGEob2JqZWN0ID0gc2NjLmJpZyx2YXJzID0gYygiTVlCIiwib3JpZy5pZGVudCIpLHNsb3QgPSAiZGF0YSIsIGFzc2F5ID0gIlJOQSIpCmIgJT4lICAgZ3JvdXBfYnkob3JpZy5pZGVudCkgJT4lIAogIHN1bW1hcmlzZShjb3VudHMgPSBzdW0oTVlCID4gMCwgbmEucm0gPSBUUlVFKSkKYGBgCgoKIyBWaW9saW4gcGxvdCBhbGwgcGF0aWVudHMgd2l0aG91dCBzY2MyCmBgYHtyIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEyfQpzY2NfbXliX3BhdGllbnRzPC0gc3Vic2V0KHNjYy5iaWcsIHN1YnNldCA9IG9yaWcuaWRlbnQgJWluJSBjKCJTQ0MzIiwiU0NDNCIsIlNDQzUiKSkKYGBgCgoKYGBge3J9CmxpYnJhcnkocnN0YXRpeCkKbXliX3ZzX2hwdiA9IEZldGNoRGF0YShvYmplY3QgPSBzY2NfbXliX3BhdGllbnRzLCB2YXJzID0gYygiaHB2X3Bvc2l0aXZlIiwgIk1ZQiIpKQpkZiA9IHJlc2hhcGUyOjptZWx0KG15Yl92c19ocHYsdmFsdWUubmFtZSA9ICJsb2dUUE0iKSAlPiUgZHBseXI6OnJlbmFtZShnZW5lID0gdmFyaWFibGUpCgpzdGF0LnRlc3QgPC0gZGYgJT4lCiAgd2lsY294X3Rlc3QobG9nVFBNIH4gaHB2X3Bvc2l0aXZlKQoKc3RhdC50ZXN0CgoKCnAgPSBnZ3Bsb3QobXliX3ZzX2hwdixhZXMoIHggPSBocHZfcG9zaXRpdmUsIHkgPSBNWUIpKSsgCiAgICBnZW9tX3Zpb2xpbih0cmltPUZBTFNFLGFlcyhmaWxsID0gaHB2X3Bvc2l0aXZlKSkgKwogIHRoZW1lX21pbmltYWwoKSsKICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBmdW5jdGlvbih4KSBkYXRhLmZyYW1lKHk9bWF4KHgpKjEuMTUsIGxhYmVsID0gcGFzdGUoIk1lYW49Iixyb3VuZChtZWFuKHgpLGRpZ2l0cyA9IDIpKSksIGdlb209InRleHQiKSAreWxhYigiYXZlcmFnZSBNWUIiKStnZ3RpdGxlKCJhbGwgcGF0aWVudHMiKSArCiAgc3RhdF9wdmFsdWVfbWFudWFsKHN0YXQudGVzdCx5LnBvc2l0aW9uID0gMywgbGFiZWwgPSAiV2lsY294LCBwID0ge3B9IixyZW1vdmUuYnJhY2tldCA9IEYpKwogIGdlb21fYm94cGxvdCh3aWR0aD0uMSwgb3V0bGllci5zaGFwZT1OQSkgCgoKcApgYGAKYGBge3J9CnBkZihmaWxlID0gIi4vRmlndXJlcy9TQ0NfbXliX2hwdl92aW9saW5fYWxsX3BhdGllbnRzLnBkZiIpCnAKZGV2Lm9mZigpCmBgYAojIFZpb2xpbiBwbG90IGFsbCBwYXRpZW50cyB3aXRoIHNjYzIKCmBgYHtyIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEyfQpzY2NfbXliX3BhdGllbnRzPC0gc3Vic2V0KHNjYy5iaWcsIHN1YnNldCA9IG9yaWcuaWRlbnQgJWluJSBjKCJTQ0MyIiwiU0NDMyIsIlNDQzQiLCJTQ0M1IikpCmBgYAoKCmBgYHtyfQpsaWJyYXJ5KHJzdGF0aXgpCm15Yl92c19ocHYgPSBGZXRjaERhdGEob2JqZWN0ID0gc2NjX215Yl9wYXRpZW50cywgdmFycyA9IGMoImhwdl9wb3NpdGl2ZSIsICJNWUIiKSkKZGYgPSByZXNoYXBlMjo6bWVsdChteWJfdnNfaHB2LHZhbHVlLm5hbWUgPSAibG9nVFBNIikgJT4lIGRwbHlyOjpyZW5hbWUoZ2VuZSA9IHZhcmlhYmxlKQoKc3RhdC50ZXN0IDwtIGRmICU+JQogIHdpbGNveF90ZXN0KGxvZ1RQTSB+IGhwdl9wb3NpdGl2ZSkKCnN0YXQudGVzdAoKCgpwID0gZ2dwbG90KG15Yl92c19ocHYsYWVzKCB4ID0gaHB2X3Bvc2l0aXZlLCB5ID0gTVlCKSkrIAogICAgZ2VvbV92aW9saW4odHJpbT1GQUxTRSxhZXMoZmlsbCA9IGhwdl9wb3NpdGl2ZSkpICsKICB0aGVtZV9taW5pbWFsKCkrCiAgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gZnVuY3Rpb24oeCkgZGF0YS5mcmFtZSh5PW1heCh4KSoxLjE1LCBsYWJlbCA9IHBhc3RlKCJNZWFuPSIscm91bmQobWVhbih4KSxkaWdpdHMgPSAyKSkpLCBnZW9tPSJ0ZXh0IikgK3lsYWIoImF2ZXJhZ2UgTVlCIikrZ2d0aXRsZSgiYWxsIHBhdGllbnRzIikgKwogIHN0YXRfcHZhbHVlX21hbnVhbChzdGF0LnRlc3QseS5wb3NpdGlvbiA9IDMsIGxhYmVsID0gIldpbGNveCwgcCA9IHtwfSIscmVtb3ZlLmJyYWNrZXQgPSBGKSsKICBnZW9tX2JveHBsb3Qod2lkdGg9LjEsIG91dGxpZXIuc2hhcGU9TkEpIAoKCnAKYGBgCgoKIyBCb3hwbG90IGJ5IHBhdGllbnQKYGBge3J9CnNjY19teWJfcGF0aWVudHM8LSBzdWJzZXQoc2NjLmJpZywgc3Vic2V0ID0gb3JpZy5pZGVudCAlaW4lIGMoIlNDQzIiLCJTQ0MzIiwiU0NDNCIsIlNDQzUiKSkKCmRmID0gRmV0Y2hEYXRhKG9iamVjdCA9IHNjY19teWJfcGF0aWVudHMsdmFycyA9IGMoIm9yaWcuaWRlbnQiLCJNWUIiLCJocHZfcG9zaXRpdmUiKSkgJT4lIGdyb3VwX2J5KG9yaWcuaWRlbnQsaHB2X3Bvc2l0aXZlKSAlPiUgc3VtbWFyaXNlKAogIG15YiA9IG1lYW4oTVlCKSwuZ3JvdXBzID0gImRyb3BfbGFzdCIpCgpkZiA9IHJlc2hhcGUyOjpkY2FzdChkZiwgb3JpZy5pZGVudCB+IGhwdl9wb3NpdGl2ZSkKIApwID0gZ2dwYWlyZWQoZGYsIGNvbmQxICA9ICJwb3NpdGl2ZSIsY29uZDIgICA9ICJuZWdhdGl2ZSIscGFsZXR0ZSA9ICJqY28iLAogICAgICAgICAgICBhZGQgPSAiaml0dGVyIiwgbGluZS5jb2xvciA9ICJncmF5IiwgbGluZS5zaXplID0gMC40LGlkID0gIm9yaWcuaWRlbnQiLCBmaWxsID0gImNvbmRpdGlvbiIpICsgdGhlbWVfbWluaW1hbCgpKwogIHN0YXRfY29tcGFyZV9tZWFucyhtZXRob2QgPSAid2lsY294LnRlc3QiLGNvbXBhcmlzb25zID0gbGlzdChjKCJwb3NpdGl2ZSIsIm5lZ2F0aXZlIikpLHBhaXJlZCA9IEYpKwogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IGZ1bmN0aW9uKHgpIGRhdGEuZnJhbWUoeT1tYXgoeCkqMS4yLCBsYWJlbCA9IHBhc3RlKCJNZWFuPSIscm91bmQobWVhbih4KSxkaWdpdHMgPSAyKSkpLCBnZW9tPSJ0ZXh0IikreWxhYigiTVlCIikKcApgYGAKYGBge3J9CnBkZihmaWxlID0gIi4vRmlndXJlcy9TQ0NfSFBWX01ZQl9ib3hwbG90X2J5U2FtcGxlLnBkZiIsd2lkdGggPSA4KQpwCmRldi5vZmYoKQpgYGAKIyBBbGwgZ2VuZXMgYm94cGxvdHMKCmBgYHtyIGZpZy53aWR0aD04fQpnZW5lcyA9IGMoIkFLNCIsICJBTkxOIiwgIkNBUEciLCAiSUZUMTIyIiwgIkpBRzEiLCAiTVlCIiwgIlBCUk0xIiApCm15Yl92c19ocHYgPSBGZXRjaERhdGEob2JqZWN0ID0gc2NjX215Yl9wYXRpZW50cyx2YXJzID0gYygiaHB2X3Bvc2l0aXZlIixnZW5lcykpCmRmID0gcmVzaGFwZTI6Om1lbHQobXliX3ZzX2hwdix2YWx1ZS5uYW1lID0gImxvZ1RQTSIpICU+JSBkcGx5cjo6cmVuYW1lKGdlbmUgPSB2YXJpYWJsZSkKCgpzdGF0LnRlc3QgPC0gZGYgJT4lCiAgICBncm91cF9ieShnZW5lKSAlPiUKICB3aWxjb3hfdGVzdChsb2dUUE0gfiBocHZfcG9zaXRpdmUpICU+JQogIG11dGF0ZSh5LnBvc2l0aW9uID0gNSkKCnN0YXQudGVzdAoKc3RhdC50ZXN0IDwtIHN0YXQudGVzdCAlPiUgCiAgYWRkX3h5X3Bvc2l0aW9uKHggPSAiZ2VuZSIsIGRvZGdlID0gMC44KQoKcCA9IGdnYm94cGxvdCgKICBkZiwKICB4ID0gImdlbmUiLAogIHkgPSAibG9nVFBNIiwKICBjb2xvciA9ICJocHZfcG9zaXRpdmUiLAogIHBhbGV0dGUgPSAiamNvIiwKICBhZGQgPSAiaml0dGVyIgopKyBzdGF0X3B2YWx1ZV9tYW51YWwoc3RhdC50ZXN0LHkucG9zaXRpb24gPSA0LCBsYWJlbCA9ICJwID0ge3B9IixyZW1vdmUuYnJhY2tldCA9IFQpCgpwCmBgYAoKCmBgYHtyfQpwZGYoZmlsZSA9ICIuL0ZpZ3VyZXMvU0NDX0hQVl9nZW5lc19hbGxfcGF0aWVudHMucGRmIix3aWR0aCA9IDgpCnAKZGV2Lm9mZigpCmBgYAoKPHNjcmlwdCBzcmM9Imh0dHBzOi8vaHlwb3RoZXMuaXMvZW1iZWQuanMiIGFzeW5jPjwvc2NyaXB0PgoK