I. Preliminaries

Loading libraries

library("tidyverse")
library("tibble")
library("msigdbr")
library("ggplot2")
library("TCGAbiolinks")
library("RNAseqQC")
library("DESeq2")
library("ensembldb")
library("purrr")
library("magrittr")
library("vsn")
library("matrixStats")
library("dplyr")
library("grex")

II. Downloading the TCGA gene expression data

Create a function for downloading TCGA gene expression data.

For more detailed documentation, refer to 2. Differential Gene Expression Analysis - TCGA.Rmd.

query_and_filter_samples <- function(project) {
  query_tumor <- GDCquery(
    project = project,
    data.category = "Transcriptome Profiling",
    data.type = "Gene Expression Quantification",
    experimental.strategy = "RNA-Seq",
    workflow.type = "STAR - Counts",
    access = "open",
    sample.type = "Primary Tumor"
  )
  tumor <- getResults(query_tumor)
  
  query_normal <- GDCquery(
    project = project,
    data.category = "Transcriptome Profiling",
    data.type = "Gene Expression Quantification",
    experimental.strategy = "RNA-Seq",
    workflow.type = "STAR - Counts",
    access = "open",
    sample.type = "Solid Tissue Normal"
  )
  normal <- getResults(query_normal)
  
  submitter_ids <- inner_join(tumor, normal, by = "cases.submitter_id") %>%
    dplyr::select(cases.submitter_id)
  tumor <- tumor %>%
    dplyr::filter(cases.submitter_id %in% submitter_ids$cases.submitter_id)
  normal <- normal %>%
    dplyr::filter(cases.submitter_id %in% submitter_ids$cases.submitter_id)
  
  samples <- rbind(tumor, normal)
  unique(samples$sample_type)
  
  query_project <- GDCquery(
    project = project,
    data.category = "Transcriptome Profiling",
    data.type = "Gene Expression Quantification",
    experimental.strategy = "RNA-Seq",
    workflow.type = "STAR - Counts",
    access = "open",
    sample.type = c("Solid Tissue Normal", "Primary Tumor"),
    barcode = as.list(samples$sample.submitter_id)
  )
  
  # If this is your first time running this notebook (i.e., you have not yet downloaded the results of the query in the previous block), 
  # uncomment the line below
  
  # GDCdownload(query_project)
  
  return (list(samples = samples, query_project = query_project))
}

Download the TCGA gene expression data for different cancer types.

Refer to this link for the list of TCGA cancer type abbreviations: https://gdc.cancer.gov/resources-tcga-users/tcga-code-tables/tcga-study-abbreviations

projects <- c("TCGA-LUSC", "TCGA-COAD", "TCGA-KICH", "TCGA-KIRC", "TCGA-PRAD",
              "TCGA-BRCA", "TCGA-HNSC", "TCGA-KIRP", "TCGA-LIHC", "TCGA-STAD",
              "TCGA-THCA", "TCGA-BLCA", "TCGA-LUAD", "TCGA-ESCA")

samples <- list()
project_data <- list()

for (project in projects) {
  result <- query_and_filter_samples(project)
  
  samples[[project]] <- result$samples
  project_data[[project]] <- result$query_project
}

Running the code block above should generate and populate a directory named GDCdata.

III. Data preprocessing

Construct the RNA-seq count matrix for each cancer type.

tcga_data <- list()
tcga_matrix <- list()

for (project in projects) {
  tcga_data[[project]] <- GDCprepare(project_data[[project]], summarizedExperiment = TRUE)
}
for (project in projects) {
  count_matrix <- assay(tcga_data[[project]], "unstranded")
  
  # Remove duplicate entries
  count_matrix_df <- data.frame(count_matrix)
  count_matrix_df <- count_matrix_df[!duplicated(count_matrix_df), ]
  count_matrix <- data.matrix(count_matrix_df)
  rownames(count_matrix) <- cleanid(rownames(count_matrix))
  count_matrix <- count_matrix[!(duplicated(rownames(count_matrix)) | duplicated(rownames(count_matrix), fromLast = TRUE)), ]
  
  tcga_matrix[[project]] <- count_matrix
}

Format the samples table so that it can be fed as input to DESeq2.

for (project in projects) {
  rownames(samples[[project]]) <- samples[[project]]$cases
  samples[[project]] <- samples[[project]] %>%
    dplyr::select(case = "cases.submitter_id", type = "sample_type")
  samples[[project]]$type <- str_replace(samples[[project]]$type, "Solid Tissue Normal", "normal")
  samples[[project]]$type <- str_replace(samples[[project]]$type, "Primary Tumor", "tumor")
}

DESeq2 requires the row names of samples should be identical to the column names of count_matrix.

for (project in projects) {
  colnames(tcga_matrix[[project]]) <- gsub(x = colnames(tcga_matrix[[project]]), pattern = "\\.", replacement = "-")
  tcga_matrix[[project]] <- tcga_matrix[[project]][, rownames(samples[[project]])]
  
  # Sanity check
  print(all(colnames(tcga_matrix[[project]]) == rownames(samples[[project]])))
}

IV. Differential gene expression analysis

References:

Construct the DESeqDataSet object for each cancer type.

dds_results <- list()

for (project in projects) {
  dds_results[[project]] <- DESeqDataSetFromMatrix(
    countData = tcga_matrix[[project]],
    colData = samples[[project]],
    design = ~type
  )
}
Warning: some variables in design formula are characters, converting to factorsWarning: some variables in design formula are characters, converting to factorsWarning: some variables in design formula are characters, converting to factorsWarning: some variables in design formula are characters, converting to factorsWarning: some variables in design formula are characters, converting to factorsWarning: some variables in design formula are characters, converting to factorsWarning: some variables in design formula are characters, converting to factorsWarning: some variables in design formula are characters, converting to factorsWarning: some variables in design formula are characters, converting to factorsWarning: some variables in design formula are characters, converting to factorsWarning: some variables in design formula are characters, converting to factorsWarning: some variables in design formula are characters, converting to factorsWarning: some variables in design formula are characters, converting to factorsWarning: some variables in design formula are characters, converting to factors

Regulated Cell Death

Refer to 1. Exploratory Data Analysis - MSigDB Gene Sets + GTEx TPM.Rmd for more detailed documentation on obtaining the gene sets.

Necroptosis

Fetch the necroptosis gene set.

necroptosis.genes <- msigdbr(species = "human", category = "C5", subcategory = "GO:BP") %>%
  dplyr::filter(gs_name == "GOBP_NECROPTOTIC_SIGNALING_PATHWAY")
necroptosis.genes

Filter the genes to include only those in the necroptosis gene set.

tcga_necroptosis <- list()

for (project in projects) {
  rownames(necroptosis.genes) <- necroptosis.genes$ensembl_gene
  tcga_necroptosis[[project]] <- tcga_matrix[[project]][rownames(tcga_matrix[[project]]) %in% necroptosis.genes$ensembl_gene, ]
  tcga_necroptosis[[project]] <- tcga_necroptosis[[project]][, rownames(samples[[project]])]
  
  # Check if all samples in the counts dataframe are in the samples dataframe
  print(all(colnames(tcga_necroptosis[[project]]) == rownames((samples[[project]]))))
}

Perform differential gene expression analysis.

dds_necroptosis <- list()
res_necroptosis <- list()

for (project in projects) {
  print(project)
  print("=============")
    
  dds <- DESeqDataSetFromMatrix(
    countData = tcga_necroptosis[[project]],
    colData = samples[[project]],
    design = ~type
  )
  dds <- filter_genes(dds, min_count = 10)
  dds$type <- relevel(dds$type, ref = "normal")
  dds_necroptosis[[project]] <- DESeq(dds)
  res_necroptosis[[project]] <- results(dds_necroptosis[[project]])
}
[1] "TCGA-LUSC"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 1 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-COAD"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
[1] "TCGA-KICH"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
[1] "TCGA-KIRC"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
[1] "TCGA-PRAD"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 1 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-BRCA"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
[1] "TCGA-HNSC"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
[1] "TCGA-KIRP"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
[1] "TCGA-LIHC"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
[1] "TCGA-STAD"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
[1] "TCGA-THCA"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
[1] "TCGA-BLCA"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
[1] "TCGA-LUAD"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 1 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-ESCA"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 1 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing

Prettify the display of results.

deseq.bbl.data <- list()

for (project in projects) {
  deseq.results <- res_necroptosis[[project]]
  deseq.bbl.data[[project]] <- data.frame(
    row.names = rownames(deseq.results),
    baseMean = deseq.results$baseMean,
    log2FoldChange = deseq.results$log2FoldChange,
    lfcSE = deseq.results$lfcSE,
    stat = deseq.results$stat,
    pvalue = deseq.results$pvalue,
    padj = deseq.results$padj,
    cancer_type = project,
    gene_symbol = necroptosis.genes[rownames(deseq.results), "gene_symbol"]
  )
}

deseq.bbl.data.combined <- bind_rows(deseq.bbl.data)
deseq.bbl.data.combined <- dplyr::filter(deseq.bbl.data.combined, abs(log2FoldChange) >= 1.5 & padj < 0.05)
deseq.bbl.data.combined

Plot the results.

sizes <- c("<10^-15" = 4, "10^-10" = 3, "10^-5" = 2, "0.05" = 1)

deseq.bbl.data.combined <- deseq.bbl.data.combined %>%
  mutate(fdr_category = cut(padj,
                            breaks = c(-Inf, 1e-15, 1e-10, 1e-5, 0.05),
                            labels = c("<10^-15", "10^-10", "10^-5", "0.05"),
                            right = FALSE))

top_genes <- deseq.bbl.data.combined %>%
  group_by(cancer_type) %>%
  mutate(rank = rank(-abs(log2FoldChange))) %>%
  dplyr::filter(rank <= 10) %>%
  ungroup()

ggplot(top_genes, aes(y=cancer_type, x=gene_symbol, size=fdr_category, fill=log2FoldChange)) +
    geom_point(alpha=0.5, shape=21, color="black") +
    scale_size_manual(values = sizes) +
    scale_fill_gradient2(low = "blue", mid = "white", high = "red", limits = c(min(deseq.bbl.data.combined$log2FoldChange),max(deseq.bbl.data.combined$log2FoldChange))) +
    theme_minimal() +
    theme(
      axis.text.x = element_text(size = 9, angle = 90, hjust = 1)
    ) +
    theme(legend.position="bottom") +
    theme(legend.position = "bottom")+
    labs(size = "FDR", fill = "log2 FC", y = "Cancer type", x = "Gene")

Ferroptosis

Fetch the ferroptosis gene set.

ferroptosis.genes <- msigdbr(species = "human", category = "C2", subcategory = "CP:WIKIPATHWAYS") %>%
  dplyr::filter(gs_name == "WP_FERROPTOSIS")
ferroptosis.genes

Filter the genes to include only those in the ferroptosis gene set.

tcga_ferroptosis <- list()

for (project in projects) {
  rownames(ferroptosis.genes) <- ferroptosis.genes$ensembl_gene
  tcga_ferroptosis[[project]] <- tcga_matrix[[project]][rownames(tcga_matrix[[project]]) %in% ferroptosis.genes$ensembl_gene, ]
  tcga_ferroptosis[[project]] <- tcga_ferroptosis[[project]][, rownames(samples[[project]])]
  
  # Check if all samples in the counts dataframe are in the samples dataframe
  print(all(colnames(tcga_ferroptosis[[project]]) == rownames((samples[[project]]))))
}

Perform differential gene expression analysis.

dds_ferroptosis <- list()
res_ferroptosis <- list()

for (project in projects) {
  print(project)
  print("=============")
  
  dds <- DESeqDataSetFromMatrix(
    countData = tcga_ferroptosis[[project]],
    colData = samples[[project]],
    design = ~type
  )
  dds <- filter_genes(dds, min_count = 10)
  dds$type <- relevel(dds$type, ref = "normal")
  dds_ferroptosis[[project]] <- DESeq(dds)
  res_ferroptosis[[project]] <- results(dds_ferroptosis[[project]])
}
[1] "TCGA-LUSC"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 2 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-COAD"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 2 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-KICH"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 2 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-KIRC"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 2 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-PRAD"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
[1] "TCGA-BRCA"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 2 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-HNSC"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 2 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-KIRP"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 2 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-LIHC"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 4 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-STAD"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 4 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-THCA"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 1 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-BLCA"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 8 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-LUAD"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 2 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-ESCA"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 1 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing

Prettify the display of results.

deseq.bbl.data <- list()

for (project in projects) {
  deseq.results <- res_ferroptosis[[project]]
  deseq.bbl.data[[project]] <- data.frame(
    row.names = rownames(deseq.results),
    baseMean = deseq.results$baseMean,
    log2FoldChange = deseq.results$log2FoldChange,
    lfcSE = deseq.results$lfcSE,
    stat = deseq.results$stat,
    pvalue = deseq.results$pvalue,
    padj = deseq.results$padj,
    cancer_type = project,
    gene_symbol = ferroptosis.genes[rownames(deseq.results), "gene_symbol"]
  )
}

deseq.bbl.data.combined <- bind_rows(deseq.bbl.data)
deseq.bbl.data.combined <- dplyr::filter(deseq.bbl.data.combined, abs(log2FoldChange) >= 1.5 & padj < 0.05)
deseq.bbl.data.combined

Plot the results.

deseq.bbl.data.combined <- deseq.bbl.data.combined %>%
  mutate(fdr_category = cut(padj,
                            breaks = c(-Inf, 1e-15, 1e-10, 1e-5, 0.05),
                            labels = c("<10^-15", "10^-10", "10^-5", "0.05"),
                            right = FALSE))

top_genes <- deseq.bbl.data.combined %>%
  group_by(cancer_type) %>%
  mutate(rank = rank(-abs(log2FoldChange))) %>%
  dplyr::filter(rank <= 10) %>%
  ungroup()

ggplot(top_genes, aes(y=cancer_type, x=gene_symbol, size=fdr_category, fill=log2FoldChange)) +
    geom_point(alpha=0.5, shape=21, color="black") +
    scale_size_manual(values = sizes) +
    scale_fill_gradient2(low = "blue", mid = "white", high = "red", limits = c(min(deseq.bbl.data.combined$log2FoldChange),max(deseq.bbl.data.combined$log2FoldChange))) +
    theme_minimal() +
    theme(
      axis.text.x = element_text(size = 9, angle = 90, hjust = 1)
    ) +
    theme(legend.position="bottom") +
    theme(legend.position = "bottom")+
    labs(size = "FDR", fill = "log2 FC", y = "Cancer type", x = "Gene")

Pyroptosis

Fetch the pyroptosis gene set.

pyroptosis.genes <- msigdbr(species = "human", category = "C2", subcategory = "CP:REACTOME") %>%
  dplyr::filter(gs_name == "REACTOME_PYROPTOSIS")
pyroptosis.genes

Filter the genes to include only those in the pyroptosis gene set.

tcga_pyroptosis <- list()

for (project in projects) {
  rownames(pyroptosis.genes) <- pyroptosis.genes$ensembl_gene
  tcga_pyroptosis[[project]] <- tcga_matrix[[project]][rownames(tcga_matrix[[project]]) %in% pyroptosis.genes$ensembl_gene, ]
  tcga_pyroptosis[[project]] <- tcga_pyroptosis[[project]][, rownames(samples[[project]])]
  
  # Check if all samples in the counts dataframe are in the samples dataframe
  print(all(colnames(tcga_pyroptosis[[project]]) == rownames((samples[[project]]))))
}

Perform differential gene expression analysis.

dds_pyroptosis <- list()
res_pyroptosis <- list()

for (project in projects) {
  print(project)
  print("=============")
  
  dds <- DESeqDataSetFromMatrix(
    countData = tcga_pyroptosis[[project]],
    colData = samples[[project]],
    design = ~type
  )
  dds <- filter_genes(dds, min_count = 10)
  dds$type <- relevel(dds$type, ref = "normal")
  dds_pyroptosis[[project]] <- DESeq(dds)
  res_pyroptosis[[project]] <- results(dds_pyroptosis[[project]])
}
[1] "TCGA-LUSC"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 1 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-COAD"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 1 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-KICH"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 2 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-KIRC"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 3 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-PRAD"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
[1] "TCGA-BRCA"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
[1] "TCGA-HNSC"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
[1] "TCGA-KIRP"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
[1] "TCGA-LIHC"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 2 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-STAD"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 1 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-THCA"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 2 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-BLCA"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 1 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-LUAD"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 1 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
[1] "TCGA-ESCA"
[1] "============="
Warning: some variables in design formula are characters, converting to factorsestimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 1 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing

Prettify the display of results.

deseq.bbl.data <- list()

for (project in projects) {
  deseq.results <- res_pyroptosis[[project]]
  deseq.bbl.data[[project]] <- data.frame(
    row.names = rownames(deseq.results),
    baseMean = deseq.results$baseMean,
    log2FoldChange = deseq.results$log2FoldChange,
    lfcSE = deseq.results$lfcSE,
    stat = deseq.results$stat,
    pvalue = deseq.results$pvalue,
    padj = deseq.results$padj,
    cancer_type = project,
    gene_symbol = pyroptosis.genes[rownames(deseq.results), "gene_symbol"]
  )
}

deseq.bbl.data.combined <- bind_rows(deseq.bbl.data)
deseq.bbl.data.combined <- dplyr::filter(deseq.bbl.data.combined, abs(log2FoldChange) >= 1.5 & padj < 0.05)
deseq.bbl.data.combined

Plot the results.

deseq.bbl.data.combined <- deseq.bbl.data.combined %>%
  mutate(fdr_category = cut(padj,
                            breaks = c(-Inf, 1e-15, 1e-10, 1e-5, 0.05),
                            labels = c("<10^-15", "10^-10", "10^-5", "0.05"),
                            right = FALSE))

top_genes <- deseq.bbl.data.combined %>%
  group_by(cancer_type) %>%
  mutate(rank = rank(-abs(log2FoldChange))) %>%
  dplyr::filter(rank <= 10) %>%
  ungroup()

ggplot(top_genes, aes(y=cancer_type, x=gene_symbol, size=fdr_category, fill=log2FoldChange)) +
    geom_point(alpha=0.5, shape=21, color="black") +
    scale_size_manual(values = sizes) +
    scale_fill_gradient2(low = "blue", mid = "white", high = "red", limits = c(min(deseq.bbl.data.combined$log2FoldChange),max(deseq.bbl.data.combined$log2FoldChange))) +
    theme_minimal() +
    theme(
      axis.text.x = element_text(size = 9, angle = 90, hjust = 1)
    ) +
    theme(legend.position="bottom") +
    theme(legend.position = "bottom")+
    labs(size = "FDR", fill = "log2 FC", y = "Cancer type", x = "Gene")


  1. De La Salle University, Manila, Philippines, ↩︎

  2. De La Salle University, Manila, Philippines, ↩︎

  3. De La Salle University, Manila, Philippines, ↩︎

LS0tDQp0aXRsZTogIkRpZmZlcmVudGlhbCBHZW5lIEV4cHJlc3Npb24gQW5hbHlzaXMiDQpzdWJ0aXRsZTogIlBhbi1jYW5jZXIgfCBOZWNyb3B0b3NpcywgRmVycm9wdG9zaXMgJiBQeXJvcHRvc2lzIg0KYXV0aG9yOiANCiAgLSBLaW0gV2lsbGlhbWUgTGVlXltEZSBMYSBTYWxsZSBVbml2ZXJzaXR5LCBNYW5pbGEsIFBoaWxpcHBpbmVzLCBraW1fbGVlanJhQGRsc3UuZWR1LnBoXQ0KICAtIE1hcmsgRWR3YXJkIE0uIEdvbnphbGVzXltEZSBMYSBTYWxsZSBVbml2ZXJzaXR5LCBNYW5pbGEsIFBoaWxpcHBpbmVzLCBnb256YWxlcy5tYXJrZWR3YXJkQGdtYWlsLmNvbV0NCiAgLSBEci4gQW5pc2ggTS5TLiBTaHJlc3RoYV5bRGUgTGEgU2FsbGUgVW5pdmVyc2l0eSwgTWFuaWxhLCBQaGlsaXBwaW5lcywgYW5pc2guc2hyZXN0aGFAZGxzdS5lZHUucGhdDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyBJLiBQcmVsaW1pbmFyaWVzDQoNCiMjIyBMb2FkaW5nIGxpYnJhcmllcw0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCmxpYnJhcnkoInRpZHl2ZXJzZSIpDQpsaWJyYXJ5KCJ0aWJibGUiKQ0KbGlicmFyeSgibXNpZ2RiciIpDQpsaWJyYXJ5KCJnZ3Bsb3QyIikNCmxpYnJhcnkoIlRDR0FiaW9saW5rcyIpDQpsaWJyYXJ5KCJSTkFzZXFRQyIpDQpsaWJyYXJ5KCJERVNlcTIiKQ0KbGlicmFyeSgiZW5zZW1ibGRiIikNCmxpYnJhcnkoInB1cnJyIikNCmxpYnJhcnkoIm1hZ3JpdHRyIikNCmxpYnJhcnkoInZzbiIpDQpsaWJyYXJ5KCJtYXRyaXhTdGF0cyIpDQpsaWJyYXJ5KCJkcGx5ciIpDQpsaWJyYXJ5KCJncmV4IikNCmBgYA0KDQojIyBJSS4gRG93bmxvYWRpbmcgdGhlIFRDR0EgZ2VuZSBleHByZXNzaW9uIGRhdGEgDQoNCkNyZWF0ZSBhIGZ1bmN0aW9uIGZvciBkb3dubG9hZGluZyBUQ0dBIGdlbmUgZXhwcmVzc2lvbiBkYXRhLiANCg0KRm9yIG1vcmUgZGV0YWlsZWQgZG9jdW1lbnRhdGlvbiwgcmVmZXIgdG8gYDIuIERpZmZlcmVudGlhbCBHZW5lIEV4cHJlc3Npb24gQW5hbHlzaXMgLSBUQ0dBLnJtZGAuDQoNCmBgYHtyfQ0KcXVlcnlfYW5kX2ZpbHRlcl9zYW1wbGVzIDwtIGZ1bmN0aW9uKHByb2plY3QpIHsNCiAgcXVlcnlfdHVtb3IgPC0gR0RDcXVlcnkoDQogICAgcHJvamVjdCA9IHByb2plY3QsDQogICAgZGF0YS5jYXRlZ29yeSA9ICJUcmFuc2NyaXB0b21lIFByb2ZpbGluZyIsDQogICAgZGF0YS50eXBlID0gIkdlbmUgRXhwcmVzc2lvbiBRdWFudGlmaWNhdGlvbiIsDQogICAgZXhwZXJpbWVudGFsLnN0cmF0ZWd5ID0gIlJOQS1TZXEiLA0KICAgIHdvcmtmbG93LnR5cGUgPSAiU1RBUiAtIENvdW50cyIsDQogICAgYWNjZXNzID0gIm9wZW4iLA0KICAgIHNhbXBsZS50eXBlID0gIlByaW1hcnkgVHVtb3IiDQogICkNCiAgdHVtb3IgPC0gZ2V0UmVzdWx0cyhxdWVyeV90dW1vcikNCiAgDQogIHF1ZXJ5X25vcm1hbCA8LSBHRENxdWVyeSgNCiAgICBwcm9qZWN0ID0gcHJvamVjdCwNCiAgICBkYXRhLmNhdGVnb3J5ID0gIlRyYW5zY3JpcHRvbWUgUHJvZmlsaW5nIiwNCiAgICBkYXRhLnR5cGUgPSAiR2VuZSBFeHByZXNzaW9uIFF1YW50aWZpY2F0aW9uIiwNCiAgICBleHBlcmltZW50YWwuc3RyYXRlZ3kgPSAiUk5BLVNlcSIsDQogICAgd29ya2Zsb3cudHlwZSA9ICJTVEFSIC0gQ291bnRzIiwNCiAgICBhY2Nlc3MgPSAib3BlbiIsDQogICAgc2FtcGxlLnR5cGUgPSAiU29saWQgVGlzc3VlIE5vcm1hbCINCiAgKQ0KICBub3JtYWwgPC0gZ2V0UmVzdWx0cyhxdWVyeV9ub3JtYWwpDQogIA0KICBzdWJtaXR0ZXJfaWRzIDwtIGlubmVyX2pvaW4odHVtb3IsIG5vcm1hbCwgYnkgPSAiY2FzZXMuc3VibWl0dGVyX2lkIikgJT4lDQogICAgZHBseXI6OnNlbGVjdChjYXNlcy5zdWJtaXR0ZXJfaWQpDQogIHR1bW9yIDwtIHR1bW9yICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXIoY2FzZXMuc3VibWl0dGVyX2lkICVpbiUgc3VibWl0dGVyX2lkcyRjYXNlcy5zdWJtaXR0ZXJfaWQpDQogIG5vcm1hbCA8LSBub3JtYWwgJT4lDQogICAgZHBseXI6OmZpbHRlcihjYXNlcy5zdWJtaXR0ZXJfaWQgJWluJSBzdWJtaXR0ZXJfaWRzJGNhc2VzLnN1Ym1pdHRlcl9pZCkNCiAgDQogIHNhbXBsZXMgPC0gcmJpbmQodHVtb3IsIG5vcm1hbCkNCiAgdW5pcXVlKHNhbXBsZXMkc2FtcGxlX3R5cGUpDQogIA0KICBxdWVyeV9wcm9qZWN0IDwtIEdEQ3F1ZXJ5KA0KICAgIHByb2plY3QgPSBwcm9qZWN0LA0KICAgIGRhdGEuY2F0ZWdvcnkgPSAiVHJhbnNjcmlwdG9tZSBQcm9maWxpbmciLA0KICAgIGRhdGEudHlwZSA9ICJHZW5lIEV4cHJlc3Npb24gUXVhbnRpZmljYXRpb24iLA0KICAgIGV4cGVyaW1lbnRhbC5zdHJhdGVneSA9ICJSTkEtU2VxIiwNCiAgICB3b3JrZmxvdy50eXBlID0gIlNUQVIgLSBDb3VudHMiLA0KICAgIGFjY2VzcyA9ICJvcGVuIiwNCiAgICBzYW1wbGUudHlwZSA9IGMoIlNvbGlkIFRpc3N1ZSBOb3JtYWwiLCAiUHJpbWFyeSBUdW1vciIpLA0KICAgIGJhcmNvZGUgPSBhcy5saXN0KHNhbXBsZXMkc2FtcGxlLnN1Ym1pdHRlcl9pZCkNCiAgKQ0KICANCiAgIyBJZiB0aGlzIGlzIHlvdXIgZmlyc3QgdGltZSBydW5uaW5nIHRoaXMgbm90ZWJvb2sgKGkuZS4sIHlvdSBoYXZlIG5vdCB5ZXQgZG93bmxvYWRlZCB0aGUgcmVzdWx0cyBvZiB0aGUgcXVlcnkgaW4gdGhlIHByZXZpb3VzIGJsb2NrKSwgDQogICMgdW5jb21tZW50IHRoZSBsaW5lIGJlbG93DQogIA0KICAjIEdEQ2Rvd25sb2FkKHF1ZXJ5X3Byb2plY3QpDQogIA0KICByZXR1cm4gKGxpc3Qoc2FtcGxlcyA9IHNhbXBsZXMsIHF1ZXJ5X3Byb2plY3QgPSBxdWVyeV9wcm9qZWN0KSkNCn0NCmBgYA0KDQpEb3dubG9hZCB0aGUgVENHQSBnZW5lIGV4cHJlc3Npb24gZGF0YSBmb3IgZGlmZmVyZW50IGNhbmNlciB0eXBlcy4NCg0KUmVmZXIgdG8gdGhpcyBsaW5rIGZvciB0aGUgbGlzdCBvZiBUQ0dBIGNhbmNlciB0eXBlIGFiYnJldmlhdGlvbnM6IGh0dHBzOi8vZ2RjLmNhbmNlci5nb3YvcmVzb3VyY2VzLXRjZ2EtdXNlcnMvdGNnYS1jb2RlLXRhYmxlcy90Y2dhLXN0dWR5LWFiYnJldmlhdGlvbnMNCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0V9DQpwcm9qZWN0cyA8LSBjKCJUQ0dBLUxVU0MiLCAiVENHQS1DT0FEIiwgIlRDR0EtS0lDSCIsICJUQ0dBLUtJUkMiLCAiVENHQS1QUkFEIiwNCiAgICAgICAgICAgICAgIlRDR0EtQlJDQSIsICJUQ0dBLUhOU0MiLCAiVENHQS1LSVJQIiwgIlRDR0EtTElIQyIsICJUQ0dBLVNUQUQiLA0KICAgICAgICAgICAgICAiVENHQS1USENBIiwgIlRDR0EtQkxDQSIsICJUQ0dBLUxVQUQiLCAiVENHQS1FU0NBIikNCg0Kc2FtcGxlcyA8LSBsaXN0KCkNCnByb2plY3RfZGF0YSA8LSBsaXN0KCkNCg0KZm9yIChwcm9qZWN0IGluIHByb2plY3RzKSB7DQogIHJlc3VsdCA8LSBxdWVyeV9hbmRfZmlsdGVyX3NhbXBsZXMocHJvamVjdCkNCiAgDQogIHNhbXBsZXNbW3Byb2plY3RdXSA8LSByZXN1bHQkc2FtcGxlcw0KICBwcm9qZWN0X2RhdGFbW3Byb2plY3RdXSA8LSByZXN1bHQkcXVlcnlfcHJvamVjdA0KfQ0KYGBgDQoNCg0KUnVubmluZyB0aGUgY29kZSBibG9jayBhYm92ZSBzaG91bGQgZ2VuZXJhdGUgYW5kIHBvcHVsYXRlIGEgZGlyZWN0b3J5IG5hbWVkIGBHRENkYXRhYC4NCg0KIyMgSUlJLiBEYXRhIHByZXByb2Nlc3NpbmcNCg0KQ29uc3RydWN0IHRoZSBSTkEtc2VxIGNvdW50IG1hdHJpeCBmb3IgZWFjaCBjYW5jZXIgdHlwZS4NCg0KYGBge3IsIGVjaG8gPSBUUlVFLCBtZXNzYWdlID0gRkFMU0UsIHJlc3VsdHM9ImhpZGUifQ0KdGNnYV9kYXRhIDwtIGxpc3QoKQ0KdGNnYV9tYXRyaXggPC0gbGlzdCgpDQoNCmZvciAocHJvamVjdCBpbiBwcm9qZWN0cykgew0KICB0Y2dhX2RhdGFbW3Byb2plY3RdXSA8LSBHRENwcmVwYXJlKHByb2plY3RfZGF0YVtbcHJvamVjdF1dLCBzdW1tYXJpemVkRXhwZXJpbWVudCA9IFRSVUUpDQp9DQpgYGANCg0KYGBge3J9DQpmb3IgKHByb2plY3QgaW4gcHJvamVjdHMpIHsNCiAgY291bnRfbWF0cml4IDwtIGFzc2F5KHRjZ2FfZGF0YVtbcHJvamVjdF1dLCAidW5zdHJhbmRlZCIpDQogIA0KICAjIFJlbW92ZSBkdXBsaWNhdGUgZW50cmllcw0KICBjb3VudF9tYXRyaXhfZGYgPC0gZGF0YS5mcmFtZShjb3VudF9tYXRyaXgpDQogIGNvdW50X21hdHJpeF9kZiA8LSBjb3VudF9tYXRyaXhfZGZbIWR1cGxpY2F0ZWQoY291bnRfbWF0cml4X2RmKSwgXQ0KICBjb3VudF9tYXRyaXggPC0gZGF0YS5tYXRyaXgoY291bnRfbWF0cml4X2RmKQ0KICByb3duYW1lcyhjb3VudF9tYXRyaXgpIDwtIGNsZWFuaWQocm93bmFtZXMoY291bnRfbWF0cml4KSkNCiAgY291bnRfbWF0cml4IDwtIGNvdW50X21hdHJpeFshKGR1cGxpY2F0ZWQocm93bmFtZXMoY291bnRfbWF0cml4KSkgfCBkdXBsaWNhdGVkKHJvd25hbWVzKGNvdW50X21hdHJpeCksIGZyb21MYXN0ID0gVFJVRSkpLCBdDQogIA0KICB0Y2dhX21hdHJpeFtbcHJvamVjdF1dIDwtIGNvdW50X21hdHJpeA0KfQ0KYGBgDQpGb3JtYXQgdGhlIGBzYW1wbGVzYCB0YWJsZSBzbyB0aGF0IGl0IGNhbiBiZSBmZWQgYXMgaW5wdXQgdG8gREVTZXEyLg0KDQpgYGB7cn0NCmZvciAocHJvamVjdCBpbiBwcm9qZWN0cykgew0KICByb3duYW1lcyhzYW1wbGVzW1twcm9qZWN0XV0pIDwtIHNhbXBsZXNbW3Byb2plY3RdXSRjYXNlcw0KICBzYW1wbGVzW1twcm9qZWN0XV0gPC0gc2FtcGxlc1tbcHJvamVjdF1dICU+JQ0KICAgIGRwbHlyOjpzZWxlY3QoY2FzZSA9ICJjYXNlcy5zdWJtaXR0ZXJfaWQiLCB0eXBlID0gInNhbXBsZV90eXBlIikNCiAgc2FtcGxlc1tbcHJvamVjdF1dJHR5cGUgPC0gc3RyX3JlcGxhY2Uoc2FtcGxlc1tbcHJvamVjdF1dJHR5cGUsICJTb2xpZCBUaXNzdWUgTm9ybWFsIiwgIm5vcm1hbCIpDQogIHNhbXBsZXNbW3Byb2plY3RdXSR0eXBlIDwtIHN0cl9yZXBsYWNlKHNhbXBsZXNbW3Byb2plY3RdXSR0eXBlLCAiUHJpbWFyeSBUdW1vciIsICJ0dW1vciIpDQp9DQpgYGANCg0KREVTZXEyIHJlcXVpcmVzIHRoZSByb3cgbmFtZXMgb2YgYHNhbXBsZXNgIHNob3VsZCBiZSBpZGVudGljYWwgdG8gdGhlIGNvbHVtbiBuYW1lcyBvZiBgY291bnRfbWF0cml4YC4NCg0KYGBge3IsIGVjaG8gPSBUUlVFLCByZXN1bHRzPSJoaWRlIn0NCmZvciAocHJvamVjdCBpbiBwcm9qZWN0cykgew0KICBjb2xuYW1lcyh0Y2dhX21hdHJpeFtbcHJvamVjdF1dKSA8LSBnc3ViKHggPSBjb2xuYW1lcyh0Y2dhX21hdHJpeFtbcHJvamVjdF1dKSwgcGF0dGVybiA9ICJcXC4iLCByZXBsYWNlbWVudCA9ICItIikNCiAgdGNnYV9tYXRyaXhbW3Byb2plY3RdXSA8LSB0Y2dhX21hdHJpeFtbcHJvamVjdF1dWywgcm93bmFtZXMoc2FtcGxlc1tbcHJvamVjdF1dKV0NCiAgDQogICMgU2FuaXR5IGNoZWNrDQogIHByaW50KGFsbChjb2xuYW1lcyh0Y2dhX21hdHJpeFtbcHJvamVjdF1dKSA9PSByb3duYW1lcyhzYW1wbGVzW1twcm9qZWN0XV0pKSkNCn0NCmBgYA0KDQojIyBJVi4gRGlmZmVyZW50aWFsIGdlbmUgZXhwcmVzc2lvbiBhbmFseXNpcw0KDQpSZWZlcmVuY2VzOiANCg0KLSBPZmZpY2lhbCBkb2N1bWVudGF0aW9uOiBodHRwczovL3d3dy5iaW9jb25kdWN0b3Iub3JnL3BhY2thZ2VzL3JlbGVhc2UvYmlvYy92aWduZXR0ZXMvREVTZXEyL2luc3QvZG9jL0RFU2VxMi5odG1sDQotIEdvb2QgYmFsYW5jZSBvZiB0aGVvcnkgYW5kIGhhbmRzLW9uOiBodHRwczovL2hiY3RyYWluaW5nLmdpdGh1Yi5pby9ER0Vfd29ya3Nob3AvbGVzc29ucy8wNF9ER0VfREVTZXEyX2FuYWx5c2lzLmh0bWwNCi0gUXVhbGl0eSBjb250cm9sOiBodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvUk5Bc2VxUUMvdmlnbmV0dGVzL2ludHJvZHVjdGlvbi5odG1sDQoNCkNvbnN0cnVjdCB0aGUgYERFU2VxRGF0YVNldGAgb2JqZWN0IGZvciBlYWNoIGNhbmNlciB0eXBlLg0KDQpgYGB7cn0NCmRkc19yZXN1bHRzIDwtIGxpc3QoKQ0KDQpmb3IgKHByb2plY3QgaW4gcHJvamVjdHMpIHsNCiAgZGRzX3Jlc3VsdHNbW3Byb2plY3RdXSA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KA0KICAgIGNvdW50RGF0YSA9IHRjZ2FfbWF0cml4W1twcm9qZWN0XV0sDQogICAgY29sRGF0YSA9IHNhbXBsZXNbW3Byb2plY3RdXSwNCiAgICBkZXNpZ24gPSB+dHlwZQ0KICApDQp9DQpgYGANCg0KDQojIyMgUmVndWxhdGVkIENlbGwgRGVhdGgNCg0KUmVmZXIgdG8gYDEuIEV4cGxvcmF0b3J5IERhdGEgQW5hbHlzaXMgLSBNU2lnREIgR2VuZSBTZXRzICsgR1RFeCBUUE0ucm1kYCBmb3IgbW9yZSBkZXRhaWxlZCBkb2N1bWVudGF0aW9uIG9uIG9idGFpbmluZyB0aGUgZ2VuZSBzZXRzLg0KDQojIyMjIE5lY3JvcHRvc2lzDQoNCkZldGNoIHRoZSBuZWNyb3B0b3NpcyBnZW5lIHNldC4NCg0KYGBge3J9DQpuZWNyb3B0b3Npcy5nZW5lcyA8LSBtc2lnZGJyKHNwZWNpZXMgPSAiaHVtYW4iLCBjYXRlZ29yeSA9ICJDNSIsIHN1YmNhdGVnb3J5ID0gIkdPOkJQIikgJT4lDQogIGRwbHlyOjpmaWx0ZXIoZ3NfbmFtZSA9PSAiR09CUF9ORUNST1BUT1RJQ19TSUdOQUxJTkdfUEFUSFdBWSIpDQpuZWNyb3B0b3Npcy5nZW5lcw0KYGBgDQpGaWx0ZXIgdGhlIGdlbmVzIHRvIGluY2x1ZGUgb25seSB0aG9zZSBpbiB0aGUgbmVjcm9wdG9zaXMgZ2VuZSBzZXQuDQoNCmBgYHtyLCBlY2hvID0gVFJVRSwgcmVzdWx0cz0iaGlkZSJ9DQp0Y2dhX25lY3JvcHRvc2lzIDwtIGxpc3QoKQ0KDQpmb3IgKHByb2plY3QgaW4gcHJvamVjdHMpIHsNCiAgcm93bmFtZXMobmVjcm9wdG9zaXMuZ2VuZXMpIDwtIG5lY3JvcHRvc2lzLmdlbmVzJGVuc2VtYmxfZ2VuZQ0KICB0Y2dhX25lY3JvcHRvc2lzW1twcm9qZWN0XV0gPC0gdGNnYV9tYXRyaXhbW3Byb2plY3RdXVtyb3duYW1lcyh0Y2dhX21hdHJpeFtbcHJvamVjdF1dKSAlaW4lIG5lY3JvcHRvc2lzLmdlbmVzJGVuc2VtYmxfZ2VuZSwgXQ0KICB0Y2dhX25lY3JvcHRvc2lzW1twcm9qZWN0XV0gPC0gdGNnYV9uZWNyb3B0b3Npc1tbcHJvamVjdF1dWywgcm93bmFtZXMoc2FtcGxlc1tbcHJvamVjdF1dKV0NCiAgDQogICMgQ2hlY2sgaWYgYWxsIHNhbXBsZXMgaW4gdGhlIGNvdW50cyBkYXRhZnJhbWUgYXJlIGluIHRoZSBzYW1wbGVzIGRhdGFmcmFtZQ0KICBwcmludChhbGwoY29sbmFtZXModGNnYV9uZWNyb3B0b3Npc1tbcHJvamVjdF1dKSA9PSByb3duYW1lcygoc2FtcGxlc1tbcHJvamVjdF1dKSkpKQ0KfQ0KYGBgDQoNClBlcmZvcm0gZGlmZmVyZW50aWFsIGdlbmUgZXhwcmVzc2lvbiBhbmFseXNpcy4NCg0KYGBge3J9DQpkZHNfbmVjcm9wdG9zaXMgPC0gbGlzdCgpDQpyZXNfbmVjcm9wdG9zaXMgPC0gbGlzdCgpDQoNCmZvciAocHJvamVjdCBpbiBwcm9qZWN0cykgew0KICBwcmludChwcm9qZWN0KQ0KICBwcmludCgiPT09PT09PT09PT09PSIpDQogICAgDQogIGRkcyA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KA0KICAgIGNvdW50RGF0YSA9IHRjZ2FfbmVjcm9wdG9zaXNbW3Byb2plY3RdXSwNCiAgICBjb2xEYXRhID0gc2FtcGxlc1tbcHJvamVjdF1dLA0KICAgIGRlc2lnbiA9IH50eXBlDQogICkNCiAgZGRzIDwtIGZpbHRlcl9nZW5lcyhkZHMsIG1pbl9jb3VudCA9IDEwKQ0KICBkZHMkdHlwZSA8LSByZWxldmVsKGRkcyR0eXBlLCByZWYgPSAibm9ybWFsIikNCiAgZGRzX25lY3JvcHRvc2lzW1twcm9qZWN0XV0gPC0gREVTZXEoZGRzKQ0KICByZXNfbmVjcm9wdG9zaXNbW3Byb2plY3RdXSA8LSByZXN1bHRzKGRkc19uZWNyb3B0b3Npc1tbcHJvamVjdF1dKQ0KfQ0KYGBgDQoNClByZXR0aWZ5IHRoZSBkaXNwbGF5IG9mIHJlc3VsdHMuDQoNCmBgYHtyfQ0KZGVzZXEuYmJsLmRhdGEgPC0gbGlzdCgpDQoNCmZvciAocHJvamVjdCBpbiBwcm9qZWN0cykgew0KICBkZXNlcS5yZXN1bHRzIDwtIHJlc19uZWNyb3B0b3Npc1tbcHJvamVjdF1dDQogIGRlc2VxLmJibC5kYXRhW1twcm9qZWN0XV0gPC0gZGF0YS5mcmFtZSgNCiAgICByb3cubmFtZXMgPSByb3duYW1lcyhkZXNlcS5yZXN1bHRzKSwNCiAgICBiYXNlTWVhbiA9IGRlc2VxLnJlc3VsdHMkYmFzZU1lYW4sDQogICAgbG9nMkZvbGRDaGFuZ2UgPSBkZXNlcS5yZXN1bHRzJGxvZzJGb2xkQ2hhbmdlLA0KICAgIGxmY1NFID0gZGVzZXEucmVzdWx0cyRsZmNTRSwNCiAgICBzdGF0ID0gZGVzZXEucmVzdWx0cyRzdGF0LA0KICAgIHB2YWx1ZSA9IGRlc2VxLnJlc3VsdHMkcHZhbHVlLA0KICAgIHBhZGogPSBkZXNlcS5yZXN1bHRzJHBhZGosDQogICAgY2FuY2VyX3R5cGUgPSBwcm9qZWN0LA0KICAgIGdlbmVfc3ltYm9sID0gbmVjcm9wdG9zaXMuZ2VuZXNbcm93bmFtZXMoZGVzZXEucmVzdWx0cyksICJnZW5lX3N5bWJvbCJdDQogICkNCn0NCg0KZGVzZXEuYmJsLmRhdGEuY29tYmluZWQgPC0gYmluZF9yb3dzKGRlc2VxLmJibC5kYXRhKQ0KZGVzZXEuYmJsLmRhdGEuY29tYmluZWQgPC0gZHBseXI6OmZpbHRlcihkZXNlcS5iYmwuZGF0YS5jb21iaW5lZCwgYWJzKGxvZzJGb2xkQ2hhbmdlKSA+PSAxLjUgJiBwYWRqIDwgMC4wNSkNCmRlc2VxLmJibC5kYXRhLmNvbWJpbmVkDQpgYGANCg0KUGxvdCB0aGUgcmVzdWx0cy4NCg0KYGBge3J9DQpzaXplcyA8LSBjKCI8MTBeLTE1IiA9IDQsICIxMF4tMTAiID0gMywgIjEwXi01IiA9IDIsICIwLjA1IiA9IDEpDQoNCmRlc2VxLmJibC5kYXRhLmNvbWJpbmVkIDwtIGRlc2VxLmJibC5kYXRhLmNvbWJpbmVkICU+JQ0KICBtdXRhdGUoZmRyX2NhdGVnb3J5ID0gY3V0KHBhZGosDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYygtSW5mLCAxZS0xNSwgMWUtMTAsIDFlLTUsIDAuMDUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIjwxMF4tMTUiLCAiMTBeLTEwIiwgIjEwXi01IiwgIjAuMDUiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByaWdodCA9IEZBTFNFKSkNCg0KdG9wX2dlbmVzIDwtIGRlc2VxLmJibC5kYXRhLmNvbWJpbmVkICU+JQ0KICBncm91cF9ieShjYW5jZXJfdHlwZSkgJT4lDQogIG11dGF0ZShyYW5rID0gcmFuaygtYWJzKGxvZzJGb2xkQ2hhbmdlKSkpICU+JQ0KICBkcGx5cjo6ZmlsdGVyKHJhbmsgPD0gMTApICU+JQ0KICB1bmdyb3VwKCkNCg0KZ2dwbG90KHRvcF9nZW5lcywgYWVzKHk9Y2FuY2VyX3R5cGUsIHg9Z2VuZV9zeW1ib2wsIHNpemU9ZmRyX2NhdGVnb3J5LCBmaWxsPWxvZzJGb2xkQ2hhbmdlKSkgKw0KICAgIGdlb21fcG9pbnQoYWxwaGE9MC41LCBzaGFwZT0yMSwgY29sb3I9ImJsYWNrIikgKw0KICAgIHNjYWxlX3NpemVfbWFudWFsKHZhbHVlcyA9IHNpemVzKSArDQogICAgc2NhbGVfZmlsbF9ncmFkaWVudDIobG93ID0gImJsdWUiLCBtaWQgPSAid2hpdGUiLCBoaWdoID0gInJlZCIsIGxpbWl0cyA9IGMobWluKGRlc2VxLmJibC5kYXRhLmNvbWJpbmVkJGxvZzJGb2xkQ2hhbmdlKSxtYXgoZGVzZXEuYmJsLmRhdGEuY29tYmluZWQkbG9nMkZvbGRDaGFuZ2UpKSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgdGhlbWUoDQogICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gOSwgYW5nbGUgPSA5MCwgaGp1c3QgPSAxKQ0KICAgICkgKw0KICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikgKw0KICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSsNCiAgICBsYWJzKHNpemUgPSAiRkRSIiwgZmlsbCA9ICJsb2cyIEZDIiwgeSA9ICJDYW5jZXIgdHlwZSIsIHggPSAiR2VuZSIpDQpgYGANCg0KIyMjIyBGZXJyb3B0b3Npcw0KDQpGZXRjaCB0aGUgZmVycm9wdG9zaXMgZ2VuZSBzZXQuDQoNCmBgYHtyfQ0KZmVycm9wdG9zaXMuZ2VuZXMgPC0gbXNpZ2RicihzcGVjaWVzID0gImh1bWFuIiwgY2F0ZWdvcnkgPSAiQzIiLCBzdWJjYXRlZ29yeSA9ICJDUDpXSUtJUEFUSFdBWVMiKSAlPiUNCiAgZHBseXI6OmZpbHRlcihnc19uYW1lID09ICJXUF9GRVJST1BUT1NJUyIpDQpmZXJyb3B0b3Npcy5nZW5lcw0KYGBgDQoNCkZpbHRlciB0aGUgZ2VuZXMgdG8gaW5jbHVkZSBvbmx5IHRob3NlIGluIHRoZSBmZXJyb3B0b3NpcyBnZW5lIHNldC4NCg0KYGBge3IsIGVjaG8gPSBUUlVFLCByZXN1bHRzPSJoaWRlIn0NCnRjZ2FfZmVycm9wdG9zaXMgPC0gbGlzdCgpDQoNCmZvciAocHJvamVjdCBpbiBwcm9qZWN0cykgew0KICByb3duYW1lcyhmZXJyb3B0b3Npcy5nZW5lcykgPC0gZmVycm9wdG9zaXMuZ2VuZXMkZW5zZW1ibF9nZW5lDQogIHRjZ2FfZmVycm9wdG9zaXNbW3Byb2plY3RdXSA8LSB0Y2dhX21hdHJpeFtbcHJvamVjdF1dW3Jvd25hbWVzKHRjZ2FfbWF0cml4W1twcm9qZWN0XV0pICVpbiUgZmVycm9wdG9zaXMuZ2VuZXMkZW5zZW1ibF9nZW5lLCBdDQogIHRjZ2FfZmVycm9wdG9zaXNbW3Byb2plY3RdXSA8LSB0Y2dhX2ZlcnJvcHRvc2lzW1twcm9qZWN0XV1bLCByb3duYW1lcyhzYW1wbGVzW1twcm9qZWN0XV0pXQ0KICANCiAgIyBDaGVjayBpZiBhbGwgc2FtcGxlcyBpbiB0aGUgY291bnRzIGRhdGFmcmFtZSBhcmUgaW4gdGhlIHNhbXBsZXMgZGF0YWZyYW1lDQogIHByaW50KGFsbChjb2xuYW1lcyh0Y2dhX2ZlcnJvcHRvc2lzW1twcm9qZWN0XV0pID09IHJvd25hbWVzKChzYW1wbGVzW1twcm9qZWN0XV0pKSkpDQp9DQpgYGANClBlcmZvcm0gZGlmZmVyZW50aWFsIGdlbmUgZXhwcmVzc2lvbiBhbmFseXNpcy4NCg0KYGBge3J9DQpkZHNfZmVycm9wdG9zaXMgPC0gbGlzdCgpDQpyZXNfZmVycm9wdG9zaXMgPC0gbGlzdCgpDQoNCmZvciAocHJvamVjdCBpbiBwcm9qZWN0cykgew0KICBwcmludChwcm9qZWN0KQ0KICBwcmludCgiPT09PT09PT09PT09PSIpDQogIA0KICBkZHMgPC0gREVTZXFEYXRhU2V0RnJvbU1hdHJpeCgNCiAgICBjb3VudERhdGEgPSB0Y2dhX2ZlcnJvcHRvc2lzW1twcm9qZWN0XV0sDQogICAgY29sRGF0YSA9IHNhbXBsZXNbW3Byb2plY3RdXSwNCiAgICBkZXNpZ24gPSB+dHlwZQ0KICApDQogIGRkcyA8LSBmaWx0ZXJfZ2VuZXMoZGRzLCBtaW5fY291bnQgPSAxMCkNCiAgZGRzJHR5cGUgPC0gcmVsZXZlbChkZHMkdHlwZSwgcmVmID0gIm5vcm1hbCIpDQogIGRkc19mZXJyb3B0b3Npc1tbcHJvamVjdF1dIDwtIERFU2VxKGRkcykNCiAgcmVzX2ZlcnJvcHRvc2lzW1twcm9qZWN0XV0gPC0gcmVzdWx0cyhkZHNfZmVycm9wdG9zaXNbW3Byb2plY3RdXSkNCn0NCmBgYA0KDQpQcmV0dGlmeSB0aGUgZGlzcGxheSBvZiByZXN1bHRzLg0KDQpgYGB7cn0NCmRlc2VxLmJibC5kYXRhIDwtIGxpc3QoKQ0KDQpmb3IgKHByb2plY3QgaW4gcHJvamVjdHMpIHsNCiAgZGVzZXEucmVzdWx0cyA8LSByZXNfZmVycm9wdG9zaXNbW3Byb2plY3RdXQ0KICBkZXNlcS5iYmwuZGF0YVtbcHJvamVjdF1dIDwtIGRhdGEuZnJhbWUoDQogICAgcm93Lm5hbWVzID0gcm93bmFtZXMoZGVzZXEucmVzdWx0cyksDQogICAgYmFzZU1lYW4gPSBkZXNlcS5yZXN1bHRzJGJhc2VNZWFuLA0KICAgIGxvZzJGb2xkQ2hhbmdlID0gZGVzZXEucmVzdWx0cyRsb2cyRm9sZENoYW5nZSwNCiAgICBsZmNTRSA9IGRlc2VxLnJlc3VsdHMkbGZjU0UsDQogICAgc3RhdCA9IGRlc2VxLnJlc3VsdHMkc3RhdCwNCiAgICBwdmFsdWUgPSBkZXNlcS5yZXN1bHRzJHB2YWx1ZSwNCiAgICBwYWRqID0gZGVzZXEucmVzdWx0cyRwYWRqLA0KICAgIGNhbmNlcl90eXBlID0gcHJvamVjdCwNCiAgICBnZW5lX3N5bWJvbCA9IGZlcnJvcHRvc2lzLmdlbmVzW3Jvd25hbWVzKGRlc2VxLnJlc3VsdHMpLCAiZ2VuZV9zeW1ib2wiXQ0KICApDQp9DQoNCmRlc2VxLmJibC5kYXRhLmNvbWJpbmVkIDwtIGJpbmRfcm93cyhkZXNlcS5iYmwuZGF0YSkNCmRlc2VxLmJibC5kYXRhLmNvbWJpbmVkIDwtIGRwbHlyOjpmaWx0ZXIoZGVzZXEuYmJsLmRhdGEuY29tYmluZWQsIGFicyhsb2cyRm9sZENoYW5nZSkgPj0gMS41ICYgcGFkaiA8IDAuMDUpDQpkZXNlcS5iYmwuZGF0YS5jb21iaW5lZA0KYGBgDQoNClBsb3QgdGhlIHJlc3VsdHMuDQoNCmBgYHtyfQ0KZGVzZXEuYmJsLmRhdGEuY29tYmluZWQgPC0gZGVzZXEuYmJsLmRhdGEuY29tYmluZWQgJT4lDQogIG11dGF0ZShmZHJfY2F0ZWdvcnkgPSBjdXQocGFkaiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBjKC1JbmYsIDFlLTE1LCAxZS0xMCwgMWUtNSwgMC4wNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiPDEwXi0xNSIsICIxMF4tMTAiLCAiMTBeLTUiLCAiMC4wNSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0ID0gRkFMU0UpKQ0KDQp0b3BfZ2VuZXMgPC0gZGVzZXEuYmJsLmRhdGEuY29tYmluZWQgJT4lDQogIGdyb3VwX2J5KGNhbmNlcl90eXBlKSAlPiUNCiAgbXV0YXRlKHJhbmsgPSByYW5rKC1hYnMobG9nMkZvbGRDaGFuZ2UpKSkgJT4lDQogIGRwbHlyOjpmaWx0ZXIocmFuayA8PSAxMCkgJT4lDQogIHVuZ3JvdXAoKQ0KDQpnZ3Bsb3QodG9wX2dlbmVzLCBhZXMoeT1jYW5jZXJfdHlwZSwgeD1nZW5lX3N5bWJvbCwgc2l6ZT1mZHJfY2F0ZWdvcnksIGZpbGw9bG9nMkZvbGRDaGFuZ2UpKSArDQogICAgZ2VvbV9wb2ludChhbHBoYT0wLjUsIHNoYXBlPTIxLCBjb2xvcj0iYmxhY2siKSArDQogICAgc2NhbGVfc2l6ZV9tYW51YWwodmFsdWVzID0gc2l6ZXMpICsNCiAgICBzY2FsZV9maWxsX2dyYWRpZW50Mihsb3cgPSAiYmx1ZSIsIG1pZCA9ICJ3aGl0ZSIsIGhpZ2ggPSAicmVkIiwgbGltaXRzID0gYyhtaW4oZGVzZXEuYmJsLmRhdGEuY29tYmluZWQkbG9nMkZvbGRDaGFuZ2UpLG1heChkZXNlcS5iYmwuZGF0YS5jb21iaW5lZCRsb2cyRm9sZENoYW5nZSkpKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICB0aGVtZSgNCiAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBhbmdsZSA9IDkwLCBoanVzdCA9IDEpDQogICAgKSArDQogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArDQogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpKw0KICAgIGxhYnMoc2l6ZSA9ICJGRFIiLCBmaWxsID0gImxvZzIgRkMiLCB5ID0gIkNhbmNlciB0eXBlIiwgeCA9ICJHZW5lIikNCmBgYA0KDQojIyMjIFB5cm9wdG9zaXMNCg0KRmV0Y2ggdGhlIHB5cm9wdG9zaXMgZ2VuZSBzZXQuDQoNCmBgYHtyfQ0KcHlyb3B0b3Npcy5nZW5lcyA8LSBtc2lnZGJyKHNwZWNpZXMgPSAiaHVtYW4iLCBjYXRlZ29yeSA9ICJDMiIsIHN1YmNhdGVnb3J5ID0gIkNQOlJFQUNUT01FIikgJT4lDQogIGRwbHlyOjpmaWx0ZXIoZ3NfbmFtZSA9PSAiUkVBQ1RPTUVfUFlST1BUT1NJUyIpDQpweXJvcHRvc2lzLmdlbmVzDQpgYGANCg0KRmlsdGVyIHRoZSBnZW5lcyB0byBpbmNsdWRlIG9ubHkgdGhvc2UgaW4gdGhlIHB5cm9wdG9zaXMgZ2VuZSBzZXQuDQoNCmBgYHtyLCBlY2hvID0gVFJVRSwgcmVzdWx0cz0iaGlkZSJ9DQp0Y2dhX3B5cm9wdG9zaXMgPC0gbGlzdCgpDQoNCmZvciAocHJvamVjdCBpbiBwcm9qZWN0cykgew0KICByb3duYW1lcyhweXJvcHRvc2lzLmdlbmVzKSA8LSBweXJvcHRvc2lzLmdlbmVzJGVuc2VtYmxfZ2VuZQ0KICB0Y2dhX3B5cm9wdG9zaXNbW3Byb2plY3RdXSA8LSB0Y2dhX21hdHJpeFtbcHJvamVjdF1dW3Jvd25hbWVzKHRjZ2FfbWF0cml4W1twcm9qZWN0XV0pICVpbiUgcHlyb3B0b3Npcy5nZW5lcyRlbnNlbWJsX2dlbmUsIF0NCiAgdGNnYV9weXJvcHRvc2lzW1twcm9qZWN0XV0gPC0gdGNnYV9weXJvcHRvc2lzW1twcm9qZWN0XV1bLCByb3duYW1lcyhzYW1wbGVzW1twcm9qZWN0XV0pXQ0KICANCiAgIyBDaGVjayBpZiBhbGwgc2FtcGxlcyBpbiB0aGUgY291bnRzIGRhdGFmcmFtZSBhcmUgaW4gdGhlIHNhbXBsZXMgZGF0YWZyYW1lDQogIHByaW50KGFsbChjb2xuYW1lcyh0Y2dhX3B5cm9wdG9zaXNbW3Byb2plY3RdXSkgPT0gcm93bmFtZXMoKHNhbXBsZXNbW3Byb2plY3RdXSkpKSkNCn0NCmBgYA0KUGVyZm9ybSBkaWZmZXJlbnRpYWwgZ2VuZSBleHByZXNzaW9uIGFuYWx5c2lzLg0KDQpgYGB7cn0NCmRkc19weXJvcHRvc2lzIDwtIGxpc3QoKQ0KcmVzX3B5cm9wdG9zaXMgPC0gbGlzdCgpDQoNCmZvciAocHJvamVjdCBpbiBwcm9qZWN0cykgew0KICBwcmludChwcm9qZWN0KQ0KICBwcmludCgiPT09PT09PT09PT09PSIpDQogIA0KICBkZHMgPC0gREVTZXFEYXRhU2V0RnJvbU1hdHJpeCgNCiAgICBjb3VudERhdGEgPSB0Y2dhX3B5cm9wdG9zaXNbW3Byb2plY3RdXSwNCiAgICBjb2xEYXRhID0gc2FtcGxlc1tbcHJvamVjdF1dLA0KICAgIGRlc2lnbiA9IH50eXBlDQogICkNCiAgZGRzIDwtIGZpbHRlcl9nZW5lcyhkZHMsIG1pbl9jb3VudCA9IDEwKQ0KICBkZHMkdHlwZSA8LSByZWxldmVsKGRkcyR0eXBlLCByZWYgPSAibm9ybWFsIikNCiAgZGRzX3B5cm9wdG9zaXNbW3Byb2plY3RdXSA8LSBERVNlcShkZHMpDQogIHJlc19weXJvcHRvc2lzW1twcm9qZWN0XV0gPC0gcmVzdWx0cyhkZHNfcHlyb3B0b3Npc1tbcHJvamVjdF1dKQ0KfQ0KYGBgDQoNClByZXR0aWZ5IHRoZSBkaXNwbGF5IG9mIHJlc3VsdHMuDQoNCmBgYHtyfQ0KZGVzZXEuYmJsLmRhdGEgPC0gbGlzdCgpDQoNCmZvciAocHJvamVjdCBpbiBwcm9qZWN0cykgew0KICBkZXNlcS5yZXN1bHRzIDwtIHJlc19weXJvcHRvc2lzW1twcm9qZWN0XV0NCiAgZGVzZXEuYmJsLmRhdGFbW3Byb2plY3RdXSA8LSBkYXRhLmZyYW1lKA0KICAgIHJvdy5uYW1lcyA9IHJvd25hbWVzKGRlc2VxLnJlc3VsdHMpLA0KICAgIGJhc2VNZWFuID0gZGVzZXEucmVzdWx0cyRiYXNlTWVhbiwNCiAgICBsb2cyRm9sZENoYW5nZSA9IGRlc2VxLnJlc3VsdHMkbG9nMkZvbGRDaGFuZ2UsDQogICAgbGZjU0UgPSBkZXNlcS5yZXN1bHRzJGxmY1NFLA0KICAgIHN0YXQgPSBkZXNlcS5yZXN1bHRzJHN0YXQsDQogICAgcHZhbHVlID0gZGVzZXEucmVzdWx0cyRwdmFsdWUsDQogICAgcGFkaiA9IGRlc2VxLnJlc3VsdHMkcGFkaiwNCiAgICBjYW5jZXJfdHlwZSA9IHByb2plY3QsDQogICAgZ2VuZV9zeW1ib2wgPSBweXJvcHRvc2lzLmdlbmVzW3Jvd25hbWVzKGRlc2VxLnJlc3VsdHMpLCAiZ2VuZV9zeW1ib2wiXQ0KICApDQp9DQoNCmRlc2VxLmJibC5kYXRhLmNvbWJpbmVkIDwtIGJpbmRfcm93cyhkZXNlcS5iYmwuZGF0YSkNCmRlc2VxLmJibC5kYXRhLmNvbWJpbmVkIDwtIGRwbHlyOjpmaWx0ZXIoZGVzZXEuYmJsLmRhdGEuY29tYmluZWQsIGFicyhsb2cyRm9sZENoYW5nZSkgPj0gMS41ICYgcGFkaiA8IDAuMDUpDQpkZXNlcS5iYmwuZGF0YS5jb21iaW5lZA0KYGBgDQpQbG90IHRoZSByZXN1bHRzLg0KDQpgYGB7cn0NCmRlc2VxLmJibC5kYXRhLmNvbWJpbmVkIDwtIGRlc2VxLmJibC5kYXRhLmNvbWJpbmVkICU+JQ0KICBtdXRhdGUoZmRyX2NhdGVnb3J5ID0gY3V0KHBhZGosDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYygtSW5mLCAxZS0xNSwgMWUtMTAsIDFlLTUsIDAuMDUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIjwxMF4tMTUiLCAiMTBeLTEwIiwgIjEwXi01IiwgIjAuMDUiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByaWdodCA9IEZBTFNFKSkNCg0KdG9wX2dlbmVzIDwtIGRlc2VxLmJibC5kYXRhLmNvbWJpbmVkICU+JQ0KICBncm91cF9ieShjYW5jZXJfdHlwZSkgJT4lDQogIG11dGF0ZShyYW5rID0gcmFuaygtYWJzKGxvZzJGb2xkQ2hhbmdlKSkpICU+JQ0KICBkcGx5cjo6ZmlsdGVyKHJhbmsgPD0gMTApICU+JQ0KICB1bmdyb3VwKCkNCg0KZ2dwbG90KHRvcF9nZW5lcywgYWVzKHk9Y2FuY2VyX3R5cGUsIHg9Z2VuZV9zeW1ib2wsIHNpemU9ZmRyX2NhdGVnb3J5LCBmaWxsPWxvZzJGb2xkQ2hhbmdlKSkgKw0KICAgIGdlb21fcG9pbnQoYWxwaGE9MC41LCBzaGFwZT0yMSwgY29sb3I9ImJsYWNrIikgKw0KICAgIHNjYWxlX3NpemVfbWFudWFsKHZhbHVlcyA9IHNpemVzKSArDQogICAgc2NhbGVfZmlsbF9ncmFkaWVudDIobG93ID0gImJsdWUiLCBtaWQgPSAid2hpdGUiLCBoaWdoID0gInJlZCIsIGxpbWl0cyA9IGMobWluKGRlc2VxLmJibC5kYXRhLmNvbWJpbmVkJGxvZzJGb2xkQ2hhbmdlKSxtYXgoZGVzZXEuYmJsLmRhdGEuY29tYmluZWQkbG9nMkZvbGRDaGFuZ2UpKSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgdGhlbWUoDQogICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gOSwgYW5nbGUgPSA5MCwgaGp1c3QgPSAxKQ0KICAgICkgKw0KICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikgKw0KICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSsNCiAgICBsYWJzKHNpemUgPSAiRkRSIiwgZmlsbCA9ICJsb2cyIEZDIiwgeSA9ICJDYW5jZXIgdHlwZSIsIHggPSAiR2VuZSIpDQpgYGA=